diff --git a/pac4j-saml/src/main/java/org/pac4j/saml/config/SAML2Configuration.java b/pac4j-saml/src/main/java/org/pac4j/saml/config/SAML2Configuration.java index 06c4201f7f..efef7d382e 100644 --- a/pac4j-saml/src/main/java/org/pac4j/saml/config/SAML2Configuration.java +++ b/pac4j-saml/src/main/java/org/pac4j/saml/config/SAML2Configuration.java @@ -18,6 +18,7 @@ import org.opensaml.saml.common.xml.SAMLConstants; import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap; import org.opensaml.xmlsec.impl.BasicSignatureSigningConfiguration; +import org.opensaml.xmlsec.signature.support.SignatureConstants; import org.pac4j.core.context.HttpConstants; import org.pac4j.core.exception.TechnicalException; import org.pac4j.core.logout.handler.DefaultLogoutHandler; @@ -774,7 +775,7 @@ private void initSignatureSigningConfiguration() { this.signatureReferenceDigestMethods = new ArrayList<>( config.getSignatureReferenceDigestMethods()); this.signatureReferenceDigestMethods - .remove("http://www.w3.org/2001/04/xmlenc#sha512"); + .remove(SignatureConstants.ALGO_ID_DIGEST_SHA512); LOGGER.info("Bootstrapped Signature Reference Digest Methods"); } if (this.signatureCanonicalizationAlgorithm == null) { diff --git a/pac4j-saml/src/main/java/org/pac4j/saml/metadata/SAML2MetadataGenerator.java b/pac4j-saml/src/main/java/org/pac4j/saml/metadata/SAML2MetadataGenerator.java index 4c30864aab..c54239a778 100644 --- a/pac4j-saml/src/main/java/org/pac4j/saml/metadata/SAML2MetadataGenerator.java +++ b/pac4j-saml/src/main/java/org/pac4j/saml/metadata/SAML2MetadataGenerator.java @@ -8,6 +8,7 @@ import org.opensaml.saml.common.SAMLObjectBuilder; import org.opensaml.saml.common.xml.SAMLConstants; import org.opensaml.saml.ext.saml2alg.DigestMethod; +import org.opensaml.saml.ext.saml2alg.SigningMethod; import org.opensaml.saml.ext.saml2mdreqinit.RequestInitiator; import org.opensaml.saml.metadata.resolver.MetadataResolver; import org.opensaml.saml.metadata.resolver.impl.AbstractBatchMetadataResolver; @@ -24,6 +25,10 @@ import org.opensaml.saml.saml2.metadata.SPSSODescriptor; import org.opensaml.saml.saml2.metadata.SingleLogoutService; import org.opensaml.security.credential.UsageType; +import org.opensaml.xmlsec.SignatureSigningConfiguration; +import org.opensaml.xmlsec.algorithm.AlgorithmRegistry; +import org.opensaml.xmlsec.algorithm.AlgorithmSupport; +import org.opensaml.xmlsec.config.impl.DefaultSecurityConfigurationBootstrap; import org.opensaml.xmlsec.signature.KeyInfo; import org.pac4j.saml.crypto.CredentialProvider; import org.pac4j.saml.util.Configuration; @@ -36,6 +41,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; /** * Generates metadata object with standard values and overriden user defined values. @@ -52,6 +58,8 @@ public class SAML2MetadataGenerator implements SAMLMetadataGenerator { protected final MarshallerFactory marshallerFactory = Configuration.getMarshallerFactory(); + protected final AlgorithmRegistry globalAlgorithmRegistry = AlgorithmSupport.getGlobalAlgorithmRegistry(); + protected CredentialProvider credentialProvider; protected String entityId; @@ -72,6 +80,15 @@ public class SAML2MetadataGenerator implements SAMLMetadataGenerator { protected List requestedAttributes = new ArrayList<>(); + protected SignatureSigningConfiguration defaultSignatureSigningConfiguration = + DefaultSecurityConfigurationBootstrap.buildDefaultSignatureSigningConfiguration(); + + protected List blackListedSignatureSigningAlgorithms = null; + + protected List signatureAlgorithms = null; + + protected List signatureReferenceDigestMethods = null; + @Override public final MetadataResolver buildMetadataResolver(final Resource metadataResource) throws Exception { final AbstractBatchMetadataResolver resolver; @@ -115,50 +132,29 @@ protected final Extensions generateMetadataExtensions() { this.builderFactory.getBuilder(Extensions.DEFAULT_ELEMENT_NAME); final Extensions extensions = builderExt.buildObject(); + extensions.getNamespaceManager().registerAttributeName(SigningMethod.TYPE_NAME); extensions.getNamespaceManager().registerAttributeName(DigestMethod.TYPE_NAME); - final SAMLObjectBuilder builder = (SAMLObjectBuilder) - this.builderFactory.getBuilder(DigestMethod.DEFAULT_ELEMENT_NAME); - - DigestMethod method = builder.buildObject(); - method.setAlgorithm("http://www.w3.org/2001/04/xmlenc#sha512"); - extensions.getUnknownXMLObjects().add(method); - - method = builder.buildObject(); - method.setAlgorithm("http://www.w3.org/2001/04/xmldsig-more#sha384"); - extensions.getUnknownXMLObjects().add(method); - - method = builder.buildObject(); - method.setAlgorithm("http://www.w3.org/2001/04/xmlenc#sha256"); - extensions.getUnknownXMLObjects().add(method); + List filteredSignatureAlgorithms = filterSignatureAlgorithms(getSignatureAlgorithms()); + List filteredSignatureReferenceDigestMethods = filterSignatureAlgorithms(getSignatureReferenceDigestMethods()); - method = builder.buildObject(); - method.setAlgorithm("http://www.w3.org/2001/04/xmldsig-more#sha224"); - extensions.getUnknownXMLObjects().add(method); + final SAMLObjectBuilder signingMethodBuilder = (SAMLObjectBuilder) + this.builderFactory.getBuilder(SigningMethod.DEFAULT_ELEMENT_NAME); - method = builder.buildObject(); - method.setAlgorithm("http://www.w3.org/2000/09/xmldsig#sha1"); - extensions.getUnknownXMLObjects().add(method); - - method = builder.buildObject(); - method.setAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"); - extensions.getUnknownXMLObjects().add(method); - - method = builder.buildObject(); - method.setAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"); - extensions.getUnknownXMLObjects().add(method); - - method = builder.buildObject(); - method.setAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"); - extensions.getUnknownXMLObjects().add(method); + for (String signingMethod : filteredSignatureAlgorithms) { + SigningMethod method = signingMethodBuilder.buildObject(); + method.setAlgorithm(signingMethod); + extensions.getUnknownXMLObjects().add(method); + } - method = builder.buildObject(); - method.setAlgorithm("http://www.w3.org/2000/09/xmldsig#rsa-sha1"); - extensions.getUnknownXMLObjects().add(method); + final SAMLObjectBuilder digestMethodBuilder = (SAMLObjectBuilder) + this.builderFactory.getBuilder(DigestMethod.DEFAULT_ELEMENT_NAME); - method = builder.buildObject(); - method.setAlgorithm("http://www.w3.org/2000/09/xmldsig#dsa-sha1"); - extensions.getUnknownXMLObjects().add(method); + for (String digestMethod : filteredSignatureReferenceDigestMethods) { + DigestMethod method = digestMethodBuilder.buildObject(); + method.setAlgorithm(digestMethod); + extensions.getUnknownXMLObjects().add(method); + } return extensions; } @@ -354,4 +350,51 @@ public List getRequestedAttributes() { public void setRequestedAttributes(final List requestedAttributes) { this.requestedAttributes = requestedAttributes; } + + public List getBlackListedSignatureSigningAlgorithms() { + if (blackListedSignatureSigningAlgorithms == null) { + this.blackListedSignatureSigningAlgorithms = + new ArrayList<>(defaultSignatureSigningConfiguration.getBlacklistedAlgorithms()); + } + + return blackListedSignatureSigningAlgorithms; + } + + public void setBlackListedSignatureSigningAlgorithms(List blackListedSignatureSigningAlgorithms) { + this.blackListedSignatureSigningAlgorithms = blackListedSignatureSigningAlgorithms; + } + + public List getSignatureAlgorithms() { + if (signatureAlgorithms == null) { + this.signatureAlgorithms = defaultSignatureSigningConfiguration.getSignatureAlgorithms(); + } + + return signatureAlgorithms; + } + + public void setSignatureAlgorithms(List signatureAlgorithms) { + this.signatureAlgorithms = signatureAlgorithms; + } + + public List getSignatureReferenceDigestMethods() { + if (signatureReferenceDigestMethods == null) { + this.signatureReferenceDigestMethods = defaultSignatureSigningConfiguration.getSignatureReferenceDigestMethods(); + } + return signatureReferenceDigestMethods; + } + + public void setSignatureReferenceDigestMethods(List signatureReferenceDigestMethods) { + this.signatureReferenceDigestMethods = signatureReferenceDigestMethods; + } + + private List filterForRuntimeSupportedAlgorithms(final List algorithms) { + final List filteredAlgorithms = new ArrayList<>(algorithms); + return filteredAlgorithms.stream().filter(uri -> globalAlgorithmRegistry.isRuntimeSupported(uri)).collect(Collectors.toList()); + } + + private List filterSignatureAlgorithms(final List algorithms) { + final List filteredAlgorithms = filterForRuntimeSupportedAlgorithms(algorithms); + this.signatureAlgorithms.removeAll(this.blackListedSignatureSigningAlgorithms); + return filteredAlgorithms; + } } diff --git a/pac4j-saml/src/main/java/org/pac4j/saml/metadata/SAML2ServiceProviderMetadataResolver.java b/pac4j-saml/src/main/java/org/pac4j/saml/metadata/SAML2ServiceProviderMetadataResolver.java index 5226bae7c7..beb6f1e849 100644 --- a/pac4j-saml/src/main/java/org/pac4j/saml/metadata/SAML2ServiceProviderMetadataResolver.java +++ b/pac4j-saml/src/main/java/org/pac4j/saml/metadata/SAML2ServiceProviderMetadataResolver.java @@ -95,6 +95,13 @@ private MetadataResolver prepareServiceProviderMetadata() { // the logout URL is callback URL with an extra parameter metadataGenerator.setSingleLogoutServiceUrl(logoutUrl); + // Algorithm support + metadataGenerator.setBlackListedSignatureSigningAlgorithms( + new ArrayList<>(configuration.getBlackListedSignatureSigningAlgorithms()) + ); + metadataGenerator.setSignatureAlgorithms(configuration.getSignatureAlgorithms()); + metadataGenerator.setSignatureReferenceDigestMethods(configuration.getSignatureReferenceDigestMethods()); + // Initialize metadata provider for our SP and get the XML as a String final EntityDescriptor entity = metadataGenerator.buildEntityDescriptor(); final String tempMetadata = metadataGenerator.getMetadata(entity);