@@ -421,8 +421,9 @@ public function doForTrustMark(
421421 );
422422
423423 $ this ->validateSubjectClaim ($ trustMark , $ leafEntityConfiguration );
424+ $ this ->validateTrustMarkIssuers ($ trustMark , $ trustAnchorEntityConfiguration );
424425
425- // If Trust Mark Issuer is the Trust Anchor itself, we don't have to resolve chain, as Trust Anchor is trusted
426+ // If Trust Mark Issuer is the Trust Anchor itself, we don't have to resolve a chain, as Trust Anchor is trusted
426427 // out-of-band. Otherwise, we have to resolve trust for Trust Mark Issuer.
427428 $ trustMarkIssuerEntityConfiguration =
428429 $ trustMark ->getIssuer () === $ trustAnchorEntityConfiguration ->getIssuer () ?
@@ -516,6 +517,91 @@ public function validateSubjectClaim(
516517 }
517518
518519
520+ /**
521+ * @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
522+ * @throws \SimpleSAML\OpenID\Exceptions\TrustMarkException
523+ * @throws \SimpleSAML\OpenID\Exceptions\JwsException
524+ */
525+ public function validateTrustMarkIssuers (
526+ TrustMark $ trustMark ,
527+ EntityStatement $ trustAnchorEntityConfiguration ,
528+ ): void {
529+ $ this ->logger ?->debug('Validating Trust Mark Issuers. ' );
530+
531+ if (is_null ($ trustMarkIssuersClaimBag = $ trustAnchorEntityConfiguration ->getTrustMarkIssuers ())) {
532+ $ this ->logger ?->debug(
533+ sprintf (
534+ 'Trust Anchor %s does not define Trust Mark Issuers. Skipping validation. ' ,
535+ $ trustAnchorEntityConfiguration ->getIssuer (),
536+ ),
537+ );
538+ return ;
539+ }
540+
541+ $ this ->logger ?->debug(
542+ sprintf (
543+ 'Trust Anchor %s defines Trust Mark Issuers. ' ,
544+ $ trustAnchorEntityConfiguration ->getIssuer (),
545+ ),
546+ ['trustMarkIssuers ' => $ trustMarkIssuersClaimBag ->jsonSerialize ()],
547+ );
548+
549+ $ trustMarkIssuersClaimValue = $ trustMarkIssuersClaimBag ->get ($ trustMark ->getTrustMarkType ());
550+
551+ if (is_null ($ trustMarkIssuersClaimValue )) {
552+ $ this ->logger ?->debug(
553+ sprintf (
554+ 'Trust Anchor %s does not define issuers of Trust Mark %s. Skipping validation. ' ,
555+ $ trustAnchorEntityConfiguration ->getIssuer (),
556+ $ trustMark ->getTrustMarkType (),
557+ ),
558+ );
559+ return ;
560+ }
561+
562+ if ($ trustMarkIssuersClaimValue ->getTrustMarkIssuers () === []) {
563+ $ this ->logger ?->debug(
564+ sprintf (
565+ 'Trust Anchor %s defines any issuers of Trust Mark %s. Skipping validation. ' ,
566+ $ trustAnchorEntityConfiguration ->getIssuer (),
567+ $ trustMark ->getTrustMarkType (),
568+ ),
569+ );
570+ return ;
571+ }
572+
573+ $ this ->logger ?->debug(
574+ sprintf (
575+ 'Trust Anchor %s defines issuers %s of Trust Mark %s. ' ,
576+ $ trustAnchorEntityConfiguration ->getIssuer (),
577+ implode (', ' , $ trustMarkIssuersClaimValue ->getTrustMarkIssuers ()),
578+ $ trustMark ->getTrustMarkType (),
579+ ),
580+ );
581+
582+ if (!in_array ($ trustMark ->getIssuer (), $ trustMarkIssuersClaimValue ->getTrustMarkIssuers (), true )) {
583+ $ error = sprintf (
584+ 'Trust Mark %s is not issued by any of the Trust Mark Issuers %s defined by Trust Anchor %s. ' ,
585+ $ trustMark ->getTrustMarkType (),
586+ implode (', ' , $ trustMarkIssuersClaimValue ->getTrustMarkIssuers ()),
587+ $ trustAnchorEntityConfiguration ->getIssuer (),
588+ );
589+
590+ $ this ->logger ?->error($ error );
591+ throw new TrustMarkException ($ error );
592+ }
593+
594+ $ this ->logger ?->debug(
595+ sprintf (
596+ 'Trust Mark %s is issued by one of the Trust Mark Issuers %s defined by Trust Anchor %s. ' ,
597+ $ trustMark ->getTrustMarkType (),
598+ implode (', ' , $ trustMarkIssuersClaimValue ->getTrustMarkIssuers ()),
599+ $ trustAnchorEntityConfiguration ->getIssuer (),
600+ ),
601+ );
602+ }
603+
604+
519605 /**
520606 * @throws \SimpleSAML\OpenID\Exceptions\EntityStatementException
521607 * @throws \SimpleSAML\OpenID\Exceptions\JwsException
0 commit comments