[java-opensaml] branch main updated: OSJ-420 - SAML20AssertionValidator allows non-Entity Issuers

Scott Cantor cantor.2 at osu.edu
Fri Oct 4 19:45:23 UTC 2024


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch main
in repository java-opensaml.

View the commit online:
http://git.shibboleth.net/view/?p=java-opensaml.git;a=commit;h=5a991f8823403584ac93337280eed001987f2815

The following commit(s) were added to refs/heads/main by this push:
     new 5a991f882 OSJ-420 - SAML20AssertionValidator allows non-Entity Issuers
5a991f882 is described below

commit 5a991f8823403584ac93337280eed001987f2815
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Fri Oct 4 15:45:20 2024 -0400

    OSJ-420 - SAML20AssertionValidator allows non-Entity Issuers
    
    https://shibboleth.atlassian.net/browse/OSJ-420
    
    Added new boolean option to enforce issuer format.
---
 .../saml2/assertion/SAML20AssertionValidator.java  | 14 ++++++++++
 .../SAML2AssertionValidationParameters.java        |  9 ++++++
 .../DefaultAssertionValidationContextBuilder.java  | 32 ++++++++++++++++++++++
 3 files changed, 55 insertions(+)

diff --git a/opensaml-saml-api/src/main/java/org/opensaml/saml/saml2/assertion/SAML20AssertionValidator.java b/opensaml-saml-api/src/main/java/org/opensaml/saml/saml2/assertion/SAML20AssertionValidator.java
index 9c139465b..372ce8952 100644
--- a/opensaml-saml-api/src/main/java/org/opensaml/saml/saml2/assertion/SAML20AssertionValidator.java
+++ b/opensaml-saml-api/src/main/java/org/opensaml/saml/saml2/assertion/SAML20AssertionValidator.java
@@ -41,6 +41,7 @@ import org.opensaml.saml.saml2.core.Assertion;
 import org.opensaml.saml.saml2.core.Condition;
 import org.opensaml.saml.saml2.core.Conditions;
 import org.opensaml.saml.saml2.core.Issuer;
+import org.opensaml.saml.saml2.core.NameIDType;
 import org.opensaml.saml.saml2.core.Statement;
 import org.opensaml.saml.saml2.core.Subject;
 import org.opensaml.saml.saml2.core.SubjectConfirmation;
@@ -431,6 +432,7 @@ public class SAML20AssertionValidator {
         return ValidationResult.VALID;
     }
     
+// Checkstyle: CyclomaticComplexity OFF
     /**
      * Validates the Assertion {@link Issuer}.
      * 
@@ -455,6 +457,17 @@ public class SAML20AssertionValidator {
         }
         
         log.debug("Evaluating Assertion Issuer of : {}", issuer);
+        
+        final Boolean requireEntityIssuer = (Boolean) context.getStaticParameters().get(
+                SAML2AssertionValidationParameters.REQUIRE_ENTITY_ISSUER);
+        if (requireEntityIssuer != null && requireEntityIssuer) {
+            assert issuerElement != null;
+            if (issuerElement.getFormat() != null && !NameIDType.ENTITY.equals(issuerElement.getFormat())) {
+                context.getValidationFailureMessages().add(
+                        String.format("Issuer had invalid Format: %s", issuerElement.getFormat()));
+                return ValidationResult.INVALID;
+            }
+        }
 
         final Set<String> validIssuers;
         try {
@@ -484,6 +497,7 @@ public class SAML20AssertionValidator {
                 "Issuer of Assertion '%s' did not match any valid issuers", assertion.getID()));
         return ValidationResult.INVALID;
     }
+// Checkstyle: CyclomaticComplexity ON
 
     /**
      * Validates the signature of the assertion, if it is signed.
diff --git a/opensaml-saml-api/src/main/java/org/opensaml/saml/saml2/assertion/SAML2AssertionValidationParameters.java b/opensaml-saml-api/src/main/java/org/opensaml/saml/saml2/assertion/SAML2AssertionValidationParameters.java
index 7bfcfa716..6d163d8f7 100644
--- a/opensaml-saml-api/src/main/java/org/opensaml/saml/saml2/assertion/SAML2AssertionValidationParameters.java
+++ b/opensaml-saml-api/src/main/java/org/opensaml/saml/saml2/assertion/SAML2AssertionValidationParameters.java
@@ -17,6 +17,7 @@ package org.opensaml.saml.saml2.assertion;
 import javax.annotation.Nonnull;
 
 import org.opensaml.saml.saml2.core.AuthnStatement;
+import org.opensaml.saml.saml2.core.NameIDType;
 import org.opensaml.saml.saml2.core.SubjectLocality;
 
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
@@ -62,6 +63,14 @@ public final class SAML2AssertionValidationParameters {
      */
     @Nonnull @NotEmpty public static final String VALID_ISSUERS = STD_PREFIX + ".ValidIssuers";
 
+    /**
+     * Carries a {@link java.lang.Boolean} flag which indicates whether the issuer must have the
+     * {@link NameIDType#ENTITY} Format.
+     * 
+     * @since 5.2.0
+     */
+    @Nonnull @NotEmpty public static final String REQUIRE_ENTITY_ISSUER = STD_PREFIX + ".RequireEntityIssuer";
+
     /**
      * Carries a {@link java.lang.Boolean} flag which indicates whether the Assertion is required to be signed.
      */
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/profile/impl/DefaultAssertionValidationContextBuilder.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/profile/impl/DefaultAssertionValidationContextBuilder.java
index 9b7564442..f0ca65130 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/profile/impl/DefaultAssertionValidationContextBuilder.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/profile/impl/DefaultAssertionValidationContextBuilder.java
@@ -55,6 +55,7 @@ import org.opensaml.saml.criterion.RoleDescriptorCriterion;
 import org.opensaml.saml.saml2.assertion.SAML2AssertionValidationParameters;
 import org.opensaml.saml.saml2.core.Assertion;
 import org.opensaml.saml.saml2.core.Issuer;
+import org.opensaml.saml.saml2.core.NameIDType;
 import org.opensaml.saml.saml2.metadata.RoleDescriptor;
 import org.opensaml.saml.saml2.profile.impl.ValidateAssertions.AssertionValidationInput;
 import org.opensaml.security.SecurityException;
@@ -118,6 +119,9 @@ public class DefaultAssertionValidationContextBuilder
     /** Function for determining additional valid Issuer values. */
     @Nonnull private Function<ProfileRequestContext, Set<String>> validIssuers;
     
+    /** Predicate for determining whether to require issuer be of the {@link NameIDType#ENTITY} format. */
+    @Nonnull private Predicate<ProfileRequestContext> requireEntityIssuer;
+    
     /** Function for determining the valid InResponseTo value. */
     @Nullable private Function<ProfileRequestContext, String> inResponseTo;
     
@@ -157,6 +161,7 @@ public class DefaultAssertionValidationContextBuilder
         addressRequired = PredicateSupport.alwaysFalse();
         requiredConditions = CollectionSupport.emptySet();
         validIssuers = new DefaultValidIssuersLookupFunction();
+        requireEntityIssuer = PredicateSupport.alwaysFalse();
 
         securityParametersLookupStrategy = new ChildContextLookup<>(SecurityParametersContext.class)
                 .compose(new InboundMessageContextLookup());
@@ -557,6 +562,30 @@ public class DefaultAssertionValidationContextBuilder
     public void setValidIssuers(@Nonnull final Function<ProfileRequestContext,Set<String>> function) {
         validIssuers = Constraint.isNotNull(function, "Valied Issuers function was null");
     }
+    
+    /**
+     * Get the predicate which determines whether to require the Issuer contain the {@link NameIDType#ENTITY} Format.
+     * 
+     * @return predicate
+     * 
+     * @since 5.2.0
+     */
+    @Nonnull public Predicate<ProfileRequestContext> getRequireEntityIssuer() {
+        return requireEntityIssuer;
+    }
+    
+    /**
+     * Get the predicate which determines whether to require the Issuer contain the {@link NameIDType#ENTITY} Format.
+     * 
+     * <p>Defaults to false.</p>
+     * 
+     * @param predicate the condition to set
+     * 
+     * @since 5.2.0
+     */
+    public void setRequireEntityIssuer(@Nonnull final Predicate<ProfileRequestContext> predicate) {
+        requireEntityIssuer = Constraint.isNotNull(predicate, "Entity issuer predicate was null");
+    }
 
     /**
      * Get the function for determining the max allowed time since authentication.
@@ -650,6 +679,9 @@ public class DefaultAssertionValidationContextBuilder
         staticParams.put(SAML2AssertionValidationParameters.VALID_ISSUERS,
                 getValidIssuers().apply(input.getProfileRequestContext()));
         
+        staticParams.put(SAML2AssertionValidationParameters.REQUIRE_ENTITY_ISSUER,
+                Boolean.valueOf(getRequireEntityIssuer().test(input.getProfileRequestContext())));
+        
         // Signature
         populateSignatureParameters(staticParams, input);
         

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list