Index: 3rdParty_sources/opensaml/org/opensaml/DefaultBootstrap.java =================================================================== diff -u -r3209d0745e0d05225bcc4da28894cd4b4b0b5f34 -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/DefaultBootstrap.java (.../DefaultBootstrap.java) (revision 3209d0745e0d05225bcc4da28894cd4b4b0b5f34) +++ 3rdParty_sources/opensaml/org/opensaml/DefaultBootstrap.java (.../DefaultBootstrap.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -17,14 +17,18 @@ package org.opensaml; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import org.apache.xml.security.Init; import org.opensaml.saml1.binding.artifact.SAML1ArtifactBuilderFactory; import org.opensaml.saml2.binding.artifact.SAML2ArtifactBuilderFactory; +import org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory; import org.opensaml.xml.ConfigurationException; import org.opensaml.xml.XMLConfigurator; import org.opensaml.xml.parse.StaticBasicParserPool; import org.opensaml.xml.parse.XMLParserException; import org.opensaml.xml.security.DefaultSecurityConfigurationBootstrap; +import org.opensaml.xml.security.x509.tls.StrictHostnameVerifier; import org.owasp.esapi.ESAPI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,6 +37,10 @@ * This class can be used to bootstrap the OpenSAML library with the default configurations that ship with the library. */ public class DefaultBootstrap { + + /** System property used to disable global default HTTPS hostname verification in Apache Commons HttpClient. */ + public static final String SYSPROP_HTTPCLIENT_HTTPS_DISABLE_HOSTNAME_VERIFICATION = + "org.opensaml.httpclient.https.disableHostnameVerification"; /** List of default XMLTooling configuration files. */ private static String[] xmlToolingConfigs = { @@ -98,9 +106,22 @@ initializeParserPool(); initializeESAPI(); + + initializeHttpClient(); } /** + * Initializes the Apache Commons HttpClient library. + */ + protected static void initializeHttpClient() { + if (!Boolean.getBoolean(SYSPROP_HTTPCLIENT_HTTPS_DISABLE_HOSTNAME_VERIFICATION)) { + ProtocolSocketFactory socketFactory = + new TLSProtocolSocketFactory(null, null, new StrictHostnameVerifier()); + Protocol.registerProtocol("https", new Protocol("https", socketFactory, 443)); + } + } + + /** * Initializes the OWASPI ESAPI library. */ protected static void initializeESAPI() { Index: 3rdParty_sources/opensaml/org/opensaml/common/impl/AbstractSAMLObject.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/common/impl/AbstractSAMLObject.java (.../AbstractSAMLObject.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/common/impl/AbstractSAMLObject.java (.../AbstractSAMLObject.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -46,6 +46,11 @@ return super.equals(obj); } + /** {@inheritDoc} */ + public int hashCode() { + return super.hashCode(); + } + /** * A helper function for derived classes that checks to see if the old and new value are equal and if so releases * the cached dom. Derived classes are expected to use this thus: Index: 3rdParty_sources/opensaml/org/opensaml/saml1/core/AssertionArtifact.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml1/core/AssertionArtifact.java (.../AssertionArtifact.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/saml1/core/AssertionArtifact.java (.../AssertionArtifact.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -21,6 +21,7 @@ import org.opensaml.common.SAMLObject; import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.xml.schema.XSString; /** * This interface is for the SAML1 AssertionArtifact extention point. @@ -34,12 +35,15 @@ public static final QName DEFAULT_ELEMENT_NAME = new QName(SAMLConstants.SAML10P_NS, DEFAULT_ELEMENT_LOCAL_NAME, SAMLConstants.SAML1P_PREFIX); - /** Local name of the XSI type. */ - public static final String TYPE_LOCAL_NAME = "AssertionArtifactType"; + /** Local name of the XSI type. + * @deprecated no replacement + */ + public static final String TYPE_LOCAL_NAME = XSString.TYPE_LOCAL_NAME; - /** QName of the XSI type. */ - public static final QName TYPE_NAME = new QName(SAMLConstants.SAML10P_NS, TYPE_LOCAL_NAME, - SAMLConstants.SAML1P_PREFIX); + /** QName of the XSI type. + * @deprecated no replacement + */ + public static final QName TYPE_NAME = XSString.TYPE_NAME; /** * Get the contents of the artifact. Index: 3rdParty_sources/opensaml/org/opensaml/saml1/core/StatusCode.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml1/core/StatusCode.java (.../StatusCode.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/saml1/core/StatusCode.java (.../StatusCode.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -62,11 +62,17 @@ public static final QName REQUEST_VERSION_TOO_LOW = new QName(SAMLConstants.SAML10P_NS, "RequestVersionTooLow", SAMLConstants.SAML1P_PREFIX); - /** RequestVersionDepricated status value. */ - public static final QName REQUEST_VERSION_DEPRICATED = new QName(SAMLConstants.SAML10P_NS, - "RequestVersionDepricated", SAMLConstants.SAML1P_PREFIX); + /** RequestVersionDeprecated status value. */ + public static final QName REQUEST_VERSION_DEPRECATED = new QName(SAMLConstants.SAML10P_NS, + "RequestVersionDeprecated", SAMLConstants.SAML1P_PREFIX); - /** TooManyResponses status value. */ + /** + * RequestVersionDepricated status value (sic). + * + * @deprecated due to typo, use {@link #REQUEST_VERSION_DEPRECATED} instead. + * */ + public static final QName REQUEST_VERSION_DEPRICATED = REQUEST_VERSION_DEPRECATED; + public static final QName TOO_MANY_RESPONSES = new QName(SAMLConstants.SAML10P_NS, "TooManyResponses", SAMLConstants.SAML1P_PREFIX); Index: 3rdParty_sources/opensaml/org/opensaml/saml1/core/StatusDetail.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml1/core/StatusDetail.java (.../StatusDetail.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/saml1/core/StatusDetail.java (.../StatusDetail.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -37,7 +37,7 @@ public final static QName DEFAULT_ELEMENT_NAME = new QName(SAMLConstants.SAML10P_NS, DEFAULT_ELEMENT_LOCAL_NAME, SAMLConstants.SAML1P_PREFIX); /** Local name of the XSI type */ - public final static String TYPE_LOCAL_NAME = "StatusDetailype"; + public final static String TYPE_LOCAL_NAME = "StatusDetailType"; /** QName of the XSI type */ public final static QName TYPE_NAME = new QName(SAMLConstants.SAML10P_NS, TYPE_LOCAL_NAME, SAMLConstants.SAML1P_PREFIX); Index: 3rdParty_sources/opensaml/org/opensaml/saml1/core/StatusMessage.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml1/core/StatusMessage.java (.../StatusMessage.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/saml1/core/StatusMessage.java (.../StatusMessage.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -21,6 +21,7 @@ import org.opensaml.common.SAMLObject; import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.xml.schema.XSString; /** * This interface defines how the object representing a SAML1 StatusMessage element behaves. @@ -33,11 +34,15 @@ /** Default element name */ public final static QName DEFAULT_ELEMENT_NAME = new QName(SAMLConstants.SAML10P_NS, DEFAULT_ELEMENT_LOCAL_NAME, SAMLConstants.SAML1P_PREFIX); - /** Local name of the XSI type */ - public final static String TYPE_LOCAL_NAME = "ActionType"; + /** Local name of the XSI type + * @deprecated no replacement + */ + public final static String TYPE_LOCAL_NAME = XSString.TYPE_LOCAL_NAME; - /** QName of the XSI type */ - public final static QName TYPE_NAME = new QName(SAMLConstants.SAML10P_NS, TYPE_LOCAL_NAME, SAMLConstants.SAML1P_PREFIX); + /** QName of the XSI type + * @deprecated no replacement + */ + public final static QName TYPE_NAME = XSString.TYPE_NAME; /** Return the contents of this */ String getMessage(); Index: 3rdParty_sources/opensaml/org/opensaml/saml1/core/Subject.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml1/core/Subject.java (.../Subject.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/saml1/core/Subject.java (.../Subject.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -36,7 +36,7 @@ public final static QName DEFAULT_ELEMENT_NAME = new QName(SAMLConstants.SAML1_NS, DEFAULT_ELEMENT_LOCAL_NAME, SAMLConstants.SAML1_PREFIX); /** Local name of the XSI type */ - public final static String TYPE_LOCAL_NAME = "ActionType"; + public final static String TYPE_LOCAL_NAME = "SubjectType"; /** QName of the XSI type */ public final static QName TYPE_NAME = new QName(SAMLConstants.SAML1_NS, TYPE_LOCAL_NAME, SAMLConstants.SAML1_PREFIX); Index: 3rdParty_sources/opensaml/org/opensaml/saml2/binding/decoding/BaseSAML2MessageDecoder.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml2/binding/decoding/BaseSAML2MessageDecoder.java (.../BaseSAML2MessageDecoder.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/saml2/binding/decoding/BaseSAML2MessageDecoder.java (.../BaseSAML2MessageDecoder.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -222,7 +222,7 @@ QName relyingPartyRole = messageContext.getPeerEntityRole(); if (relyingPartyMD != null && relyingPartyRole != null) { List roles = relyingPartyMD.getRoleDescriptors(relyingPartyRole, - SAMLConstants.SAML11P_NS); + SAMLConstants.SAML20P_NS); if (roles != null && roles.size() > 0) { messageContext.setPeerEntityRoleMetadata(roles.get(0)); } Index: 3rdParty_sources/opensaml/org/opensaml/saml2/core/RequestedAuthnContext.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml2/core/RequestedAuthnContext.java (.../RequestedAuthnContext.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/saml2/core/RequestedAuthnContext.java (.../RequestedAuthnContext.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -41,7 +41,7 @@ SAMLConstants.SAML20P_PREFIX); /** Local name of the XSI type. */ - public static final String TYPE_LOCAL_NAME = "ActionType"; + public static final String TYPE_LOCAL_NAME = "RequestedAuthnContextType"; /** QName of the XSI type. */ public static final QName TYPE_NAME = new QName(SAMLConstants.SAML20P_NS, TYPE_LOCAL_NAME, Index: 3rdParty_sources/opensaml/org/opensaml/saml2/core/Scoping.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml2/core/Scoping.java (.../Scoping.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/saml2/core/Scoping.java (.../Scoping.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -41,7 +41,7 @@ SAMLConstants.SAML20P_PREFIX); /** Local name of the XSI type. */ - public static final String TYPE_LOCAL_NAME = "ActionType"; + public static final String TYPE_LOCAL_NAME = "ScopingType"; /** QName of the XSI type. */ public static final QName TYPE_NAME = new QName(SAMLConstants.SAML20P_NS, TYPE_LOCAL_NAME, Index: 3rdParty_sources/opensaml/org/opensaml/saml2/core/impl/AuthzDecisionStatementImpl.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml2/core/impl/AuthzDecisionStatementImpl.java (.../AuthzDecisionStatementImpl.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/saml2/core/impl/AuthzDecisionStatementImpl.java (.../AuthzDecisionStatementImpl.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -69,7 +69,7 @@ /** {@inheritDoc} */ public void setResource(String newResourceURI) { - this.resource = prepareForAssignment(this.resource, newResourceURI); + this.resource = prepareForAssignment(this.resource, newResourceURI, false); } /** {@inheritDoc} */ Index: 3rdParty_sources/opensaml/org/opensaml/saml2/core/validator/AuthzDecisionStatementSchemaValidator.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml2/core/validator/AuthzDecisionStatementSchemaValidator.java (.../AuthzDecisionStatementSchemaValidator.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/saml2/core/validator/AuthzDecisionStatementSchemaValidator.java (.../AuthzDecisionStatementSchemaValidator.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -50,7 +50,7 @@ * @throws ValidationException */ protected void validateResource(AuthzDecisionStatement authzDS) throws ValidationException { - if (DatatypeHelper.isEmpty(authzDS.getResource())) { + if (authzDS.getResource() == null) { throw new ValidationException("Resource required"); } } @@ -78,4 +78,4 @@ throw new ValidationException("One or more Actions required"); } } -} \ No newline at end of file +} Index: 3rdParty_sources/opensaml/org/opensaml/saml2/core/validator/RequestAbstractTypeSchemaValidator.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml2/core/validator/RequestAbstractTypeSchemaValidator.java (.../RequestAbstractTypeSchemaValidator.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/saml2/core/validator/RequestAbstractTypeSchemaValidator.java (.../RequestAbstractTypeSchemaValidator.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -71,7 +71,7 @@ if (request.getVersion() == null) { throw new ValidationException("Version attribute must not be null"); } - if (request.getVersion().toString() != SAMLVersion.VERSION_20.toString()) { + if (!DatatypeHelper.safeEquals(request.getVersion().toString(), SAMLVersion.VERSION_20.toString())) { throw new ValidationException("Wrong SAML Version"); } } Index: 3rdParty_sources/opensaml/org/opensaml/saml2/core/validator/StatusResponseTypeSchemaValidator.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml2/core/validator/StatusResponseTypeSchemaValidator.java (.../StatusResponseTypeSchemaValidator.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/saml2/core/validator/StatusResponseTypeSchemaValidator.java (.../StatusResponseTypeSchemaValidator.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -79,7 +79,7 @@ protected void validateVersion(StatusResponse response) throws ValidationException { if (response.getVersion() == null) throw new ValidationException("Version attribute must not be null"); - if (response.getVersion().toString() != SAMLVersion.VERSION_20.toString()) + if (!DatatypeHelper.safeEquals(response.getVersion().toString(), SAMLVersion.VERSION_20.toString())) throw new ValidationException("Wrong SAML Version"); } Index: 3rdParty_sources/opensaml/org/opensaml/saml2/metadata/provider/AbstractMetadataProvider.java =================================================================== diff -u -r3209d0745e0d05225bcc4da28894cd4b4b0b5f34 -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml2/metadata/provider/AbstractMetadataProvider.java (.../AbstractMetadataProvider.java) (revision 3209d0745e0d05225bcc4da28894cd4b4b0b5f34) +++ 3rdParty_sources/opensaml/org/opensaml/saml2/metadata/provider/AbstractMetadataProvider.java (.../AbstractMetadataProvider.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -535,15 +535,14 @@ if (!DatatypeHelper.safeEquals(descriptor.getEntityID(), entityID)) { // skip this one, it isn't what we're looking for descriptor = null; - } - if (!isValid(descriptor)) { + } else if (!isValid(descriptor)) { log.trace("Found entity descriptor for entity with ID {} but it is no longer valid, skipping it.", entityID); descriptor = null; } } else { - log - .trace("Metadata was an EntitiesDescriptor, checking if any of its descendant EntityDescriptor elements is the one we're looking for."); + log.trace("Metadata was an EntitiesDescriptor, checking if any of its descendant EntityDescriptor " + + "elements is the one we're looking for."); if (metadata instanceof EntitiesDescriptor) { descriptor = getEntityDescriptorById(entityID, (EntitiesDescriptor) metadata); } Index: 3rdParty_sources/opensaml/org/opensaml/saml2/metadata/provider/AbstractReloadingMetadataProvider.java =================================================================== diff -u -r3209d0745e0d05225bcc4da28894cd4b4b0b5f34 -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml2/metadata/provider/AbstractReloadingMetadataProvider.java (.../AbstractReloadingMetadataProvider.java) (revision 3209d0745e0d05225bcc4da28894cd4b4b0b5f34) +++ 3rdParty_sources/opensaml/org/opensaml/saml2/metadata/provider/AbstractReloadingMetadataProvider.java (.../AbstractReloadingMetadataProvider.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -91,8 +91,7 @@ /** Constructor. */ protected AbstractReloadingMetadataProvider() { - taskTimer = new Timer(true); - createdOwnTaskTimer = true; + this(null); } /** @@ -102,9 +101,13 @@ */ protected AbstractReloadingMetadataProvider(Timer backgroundTaskTimer) { if (backgroundTaskTimer == null) { - throw new IllegalArgumentException("Task timer may not be null"); + log.debug("Creating own background task Timer instance"); + taskTimer = new Timer(true); + createdOwnTaskTimer = true; + } else { + log.debug("Using ctor arg-supplied background task Timer instance"); + taskTimer = backgroundTaskTimer; } - taskTimer = backgroundTaskTimer; } /** @@ -246,7 +249,7 @@ * * @throws MetadataProviderException thrown is there is a problem retrieving and processing the metadata */ - public void refresh() throws MetadataProviderException { + public synchronized void refresh() throws MetadataProviderException { DateTime now = new DateTime(ISOChronology.getInstanceUTC()); String mdId = getMetadataIdentifier(); @@ -260,10 +263,15 @@ log.debug("Processing new metadata from '{}'", mdId); processNewMetadata(mdId, now, mdBytes); } - } catch (Exception e) { - log.debug("Error occurred while attempting to refresh metadata from '" + mdId + "'", e); + } catch (Throwable t) { + log.error("Error occurred while attempting to refresh metadata from '" + mdId + "'", t); nextRefresh = new DateTime(ISOChronology.getInstanceUTC()).plus(minRefreshDelay); - throw new MetadataProviderException(e); + if (t instanceof Exception) { + throw new MetadataProviderException((Exception) t); + } else { + throw new MetadataProviderException(String.format("Saw an error of type '%s' with message '%s'", + t.getClass().getName(), t.getMessage())); + } } finally { refresMetadataTask = new RefreshMetadataTask(); long nextRefreshDelay = nextRefresh.getMillis() - System.currentTimeMillis(); Index: 3rdParty_sources/opensaml/org/opensaml/saml2/metadata/provider/FileBackedHTTPMetadataProvider.java =================================================================== diff -u -r3209d0745e0d05225bcc4da28894cd4b4b0b5f34 -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml2/metadata/provider/FileBackedHTTPMetadataProvider.java (.../FileBackedHTTPMetadataProvider.java) (revision 3209d0745e0d05225bcc4da28894cd4b4b0b5f34) +++ 3rdParty_sources/opensaml/org/opensaml/saml2/metadata/provider/FileBackedHTTPMetadataProvider.java (.../FileBackedHTTPMetadataProvider.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -154,6 +154,8 @@ return super.fetchMetadata(); } catch (MetadataProviderException e) { if (metadataBackupFile.exists()) { + log.warn("Problem reading metadata from remote source, processing existing backup file: {}", + metadataBackupFile.getAbsolutePath()); try { return DatatypeHelper.fileToByteArray(metadataBackupFile); } catch (IOException ioe) { Index: 3rdParty_sources/opensaml/org/opensaml/saml2/metadata/provider/RequiredValidUntilFilter.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/saml2/metadata/provider/RequiredValidUntilFilter.java (.../RequiredValidUntilFilter.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/saml2/metadata/provider/RequiredValidUntilFilter.java (.../RequiredValidUntilFilter.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -17,6 +17,9 @@ package org.opensaml.saml2.metadata.provider; +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; + import org.joda.time.DateTime; import org.joda.time.chrono.ISOChronology; import org.opensaml.saml2.metadata.EntitiesDescriptor; @@ -40,10 +43,13 @@ /** The maximum interval, in milliseconds, between now and the validUntil date. */ private long maxValidityInterval; + + /** DatatypeFactory used to convert duration to string representation. */ + private DatatypeFactory dataTypeFactory; /** Constructor. */ public RequiredValidUntilFilter() { - maxValidityInterval = 0; + this(0); } /** @@ -53,11 +59,16 @@ */ public RequiredValidUntilFilter(long maxValidity) { this.maxValidityInterval = maxValidity * 1000; + try { + dataTypeFactory = DatatypeFactory.newInstance(); + } catch (DatatypeConfigurationException e) { + throw new RuntimeException("JVM is required to support XML DatatypeFactory but it does not", e); + } } /** - * Gets the maximum internal, in milliseconds, between now and the validUntil date. A value of less than 1 - * indicates that there is no restriction. + * Gets the maximum internal, in milliseconds, between now and the validUntil date. + * A value of less than 1 indicates that there is no restriction. * * @return maximum internal, in milliseconds, between now and the validUntil date */ @@ -77,8 +88,9 @@ if (maxValidityInterval > 0 && validUntil.isAfter(now)) { long validityInterval = validUntil.getMillis() - now.getMillis(); if (validityInterval > maxValidityInterval) { - throw new FilterException("Metadata's validity interval, " + validityInterval - + "ms, is larger than is allowed, " + maxValidityInterval + "ms."); + throw new FilterException(String.format("Metadata's validity interval %s is larger than is allowed %s", + dataTypeFactory.newDuration(validityInterval).toString(), + dataTypeFactory.newDuration(maxValidityInterval).toString())); } } } Index: 3rdParty_sources/opensaml/org/opensaml/security/SAMLMDCredentialContext.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/opensaml/org/opensaml/security/SAMLMDCredentialContext.java (.../SAMLMDCredentialContext.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/opensaml/org/opensaml/security/SAMLMDCredentialContext.java (.../SAMLMDCredentialContext.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -67,8 +67,18 @@ * Return the list of {@link EncryptionMethod}'s associated with credential context. * * @return a list of SAML metadata encryption method associated with this context + * @deprecated due to typo, use {@link #getEncryptionMethods()}. */ public List getEncryptionMethod() { + return getEncryptionMethods(); + } + + /** + * Return the list of {@link EncryptionMethod}'s associated with credential context. + * + * @return a list of SAML metadata encryption method associated with this context + */ + public List getEncryptionMethods() { return encMethods; } Index: 3rdParty_sources/openws/org/opensaml/util/resource/HttpResource.java =================================================================== diff -u -r4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/openws/org/opensaml/util/resource/HttpResource.java (.../HttpResource.java) (revision 4c92d2863f0a9de8d8135bd2f7347375bb1d4b4d) +++ 3rdParty_sources/openws/org/opensaml/util/resource/HttpResource.java (.../HttpResource.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -26,6 +26,7 @@ import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.httpclient.methods.HeadMethod; +import org.apache.commons.httpclient.params.HttpConnectionManagerParams; import org.apache.commons.httpclient.util.DateParseException; import org.apache.commons.httpclient.util.DateUtil; import org.joda.time.DateTime; @@ -36,6 +37,12 @@ * A resource representing a file retrieved from a URL using Apache Commons HTTPClient. */ public class HttpResource extends AbstractFilteredResource { + + /** HttpClient connection timeout in milliseconds. */ + private static final int CONNECTION_TIMEOUT = 90*1000; + + /** HttpClient socket timeout in milliseconds. */ + private static final int SOCKET_TIMEOUT = 90*1000; /** HTTP URL of the resource. */ private String resourceUrl; @@ -57,6 +64,10 @@ } httpClient = new HttpClient(); + + HttpConnectionManagerParams connMgrParams = httpClient.getHttpConnectionManager().getParams(); + connMgrParams.setConnectionTimeout(CONNECTION_TIMEOUT); + connMgrParams.setSoTimeout(SOCKET_TIMEOUT); } /** @@ -76,6 +87,10 @@ } httpClient = new HttpClient(); + + HttpConnectionManagerParams connMgrParams = httpClient.getHttpConnectionManager().getParams(); + connMgrParams.setConnectionTimeout(CONNECTION_TIMEOUT); + connMgrParams.setSoTimeout(SOCKET_TIMEOUT); } /** {@inheritDoc} */ Index: 3rdParty_sources/openws/org/opensaml/ws/soap/client/http/HttpClientBuilder.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/openws/org/opensaml/ws/soap/client/http/HttpClientBuilder.java (.../HttpClientBuilder.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/openws/org/opensaml/ws/soap/client/http/HttpClientBuilder.java (.../HttpClientBuilder.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -79,6 +79,9 @@ /** Number of times a failed connection to a host should be retried. */ private int connectionRetryAttempts; + + /** Amount of time, in milliseconds, to wait for data to be read from a socket, defaults to 90000. */ + private int socketTimeout; /** Socket factory used for the 'https' scheme. */ private SecureProtocolSocketFactory httpsProtocolSocketFactory; @@ -100,6 +103,7 @@ maxConnectionsPerHost = 5; maxTotalConnectons = 20; connectionRetryAttempts = 0; + socketTimeout = 90*1000; } /** @@ -126,6 +130,8 @@ connMgrParams.setReceiveBufferSize(getReceiveBufferSize()); connMgrParams.setSendBufferSize(getSendBufferSize()); connMgrParams.setTcpNoDelay(isTcpNoDelay()); + // Note: this is deliberately an internal default for now. + connMgrParams.setSoTimeout(socketTimeout); MultiThreadedHttpConnectionManager connMgr = new MultiThreadedHttpConnectionManager(); connMgr.setParams(connMgrParams); Index: 3rdParty_sources/openws/org/opensaml/ws/soap/client/http/TLSProtocolSocketFactory.java =================================================================== diff -u -r3209d0745e0d05225bcc4da28894cd4b4b0b5f34 -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/openws/org/opensaml/ws/soap/client/http/TLSProtocolSocketFactory.java (.../TLSProtocolSocketFactory.java) (revision 3209d0745e0d05225bcc4da28894cd4b4b0b5f34) +++ 3rdParty_sources/openws/org/opensaml/ws/soap/client/http/TLSProtocolSocketFactory.java (.../TLSProtocolSocketFactory.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -155,21 +155,21 @@ /** {@inheritDoc} */ public Socket createSocket(String host, int port) throws IOException { Socket socket = sslContext.getSocketFactory().createSocket(host, port); - verifyHostname(socket); + verifyHostname(socket, host); return socket; } /** {@inheritDoc} */ public Socket createSocket(String host, int port, InetAddress localHost, int clientPort) throws IOException { Socket socket = sslContext.getSocketFactory().createSocket(host, port, localHost, clientPort); - verifyHostname(socket); + verifyHostname(socket, host); return socket; } /** {@inheritDoc} */ public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException { Socket newSocket = sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); - verifyHostname(socket); + verifyHostname(socket, host); return newSocket; } @@ -183,15 +183,15 @@ SocketFactory socketfactory = sslContext.getSocketFactory(); if (timeout == 0) { Socket socket = socketfactory.createSocket(host, port, localHost, localPort); - verifyHostname(socket); + verifyHostname(socket, host); return socket; } else { Socket socket = socketfactory.createSocket(); SocketAddress localaddr = new InetSocketAddress(localHost, localPort); SocketAddress remoteaddr = new InetSocketAddress(host, port); socket.bind(localaddr); socket.connect(remoteaddr, timeout); - verifyHostname(socket); + verifyHostname(socket, host); return socket; } } @@ -213,6 +213,8 @@ * * @throws SSLException if the hostname does not verify against the peer's certificate, * or if there is an error in performing the evaluation + * + * @deprecated Use instead {@link #verifyHostname(Socket, String) */ protected void verifyHostname(Socket socket) throws SSLException { if (hostnameVerifier == null) { @@ -227,8 +229,53 @@ try { SSLSession sslSession = sslSocket.getSession(); - String hostname = sslSession.getPeerHost(); + if (!sslSession.isValid()) { + throw new SSLException("SSLSession was invalid: Likely implicit handshake failure: " + + "Set system property javax.net.debug=all for details"); + } + verifyHostname(sslSocket, sslSession.getPeerHost()); + } catch (SSLException e) { + cleanUpFailedSocket(sslSocket); + throw e; + } catch (Throwable t) { + // Make sure we close the socket on any kind of Exception, RuntimeException or Error. + cleanUpFailedSocket(sslSocket); + throw new SSLException("Error in deprecated verifyHostname(Socket)", t); + } + } + + /** + * Verifies the peer's hostname using the configured {@link HostnameVerifier}. + * + * @param socket the socket connected to the peer whose hostname is to be verified. + * @param hostname the caller-supplied hostname to verify + * + * @throws SSLException if the hostname does not verify against the peer's certificate, + * or if there is an error in performing the evaluation + */ + protected void verifyHostname(Socket socket, String hostname) throws SSLException { + if (hostnameVerifier == null) { + return; + } + + if (hostname == null) { + throw new SSLException("Supplied hostname was null, skipping hostname verification and terminating"); + } + + if (!(socket instanceof SSLSocket)) { + return; + } + + SSLSocket sslSocket = (SSLSocket) socket; + + try { + SSLSession sslSession = sslSocket.getSession(); + if (!sslSession.isValid()) { + throw new SSLException("SSLSession was invalid: Likely implicit handshake failure: " + + "Set system property javax.net.debug=all for details"); + } + if (!hostnameVerifier.verify(hostname, sslSession)) { throw new SSLPeerUnverifiedException("SSL peer failed hostname validation for name: " + hostname); } Index: 3rdParty_sources/openws/org/opensaml/ws/wstrust/impl/CancelTargetImpl.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/openws/org/opensaml/ws/wstrust/impl/CancelTargetImpl.java (.../CancelTargetImpl.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/openws/org/opensaml/ws/wstrust/impl/CancelTargetImpl.java (.../CancelTargetImpl.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -51,7 +51,7 @@ /** {@inheritDoc} */ public void setUnknownXMLObject(XMLObject unknownObject) { - prepareForAssignment(unknownChild, unknownObject); + unknownChild = prepareForAssignment(unknownChild, unknownObject); } /** {@inheritDoc} */ Index: 3rdParty_sources/versions.txt =================================================================== diff -u -r8e1ed196bfc1c28860729d8b0a23878bb3ecf1e7 -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/versions.txt (.../versions.txt) (revision 8e1ed196bfc1c28860729d8b0a23878bb3ecf1e7) +++ 3rdParty_sources/versions.txt (.../versions.txt) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -39,16 +39,16 @@ MySQL Connector/J 5.0.8 -opensaml 2.6.0 +opensaml 2.6.6 -openws 1.5.0 +openws 1.5.6 Quartz 1.5.2 Spring 2.5.6 Struts 1.2.9 -xmltooling 1.4.0 +xmltooling 1.4.6 XStream 1.1.3 \ No newline at end of file Index: 3rdParty_sources/xmltooling/org/opensaml/xml/AbstractXMLObject.java =================================================================== diff -u -r3209d0745e0d05225bcc4da28894cd4b4b0b5f34 -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/AbstractXMLObject.java (.../AbstractXMLObject.java) (revision 3209d0745e0d05225bcc4da28894cd4b4b0b5f34) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/AbstractXMLObject.java (.../AbstractXMLObject.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -290,7 +290,25 @@ * @return the value that should be assigned */ protected String prepareForAssignment(String oldValue, String newValue) { - String newString = DatatypeHelper.safeTrimOrNullString(newValue); + return prepareForAssignment(oldValue, newValue, true); + } + + /** + * A helper function for derived classes. This 'nornmalizes' newString if normalize=true, + * and then if it is different from oldString invalidates the DOM. It returns the new effective value so + * subclasses just have to go. this.foo = * prepareForAssignment(this.foo, foo); + * + * @param oldValue - the current value + * @param newValue - the new value + * @param normalize - whether the newValue should be normalized + * + * @return the value that should be assigned + */ + protected String prepareForAssignment(String oldValue, String newValue, boolean normalize) { + String newString = newValue; + if (normalize) { + newString = DatatypeHelper.safeTrimOrNullString(newString); + } if (!DatatypeHelper.safeEquals(oldValue, newString)) { releaseThisandParentDOM(); Index: 3rdParty_sources/xmltooling/org/opensaml/xml/encryption/Decrypter.java =================================================================== diff -u -r3209d0745e0d05225bcc4da28894cd4b4b0b5f34 -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/encryption/Decrypter.java (.../Decrypter.java) (revision 3209d0745e0d05225bcc4da28894cd4b4b0b5f34) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/encryption/Decrypter.java (.../Decrypter.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -27,17 +27,21 @@ import java.util.List; import java.util.Set; +import javax.xml.XMLConstants; + import org.apache.xml.security.Init; import org.apache.xml.security.encryption.XMLCipher; import org.apache.xml.security.encryption.XMLEncryptionException; import org.opensaml.xml.Configuration; import org.opensaml.xml.XMLObject; +import org.opensaml.xml.XMLRuntimeException; import org.opensaml.xml.io.Marshaller; import org.opensaml.xml.io.MarshallingException; import org.opensaml.xml.io.Unmarshaller; import org.opensaml.xml.io.UnmarshallerFactory; import org.opensaml.xml.io.UnmarshallingException; -import org.opensaml.xml.parse.BasicParserPool; +import org.opensaml.xml.parse.ParserPool; +import org.opensaml.xml.parse.StaticBasicParserPool; import org.opensaml.xml.parse.XMLParserException; import org.opensaml.xml.security.Criteria; import org.opensaml.xml.security.CriteriaSet; @@ -170,13 +174,14 @@ public class Decrypter { /** ParserPool used in parsing decrypted data. */ - private final BasicParserPool parserPool; + private final ParserPool parserPool; /** Unmarshaller factory, used in decryption of EncryptedData objects. */ private UnmarshallerFactory unmarshallerFactory; /** Load-and-Save DOM Implementation singleton. */ // private DOMImplementationLS domImplLS; + /** Class logger. */ private final Logger log = LoggerFactory.getLogger(Decrypter.class); @@ -219,20 +224,15 @@ resolverCriteria = null; kekResolverCriteria = null; - // Note: this is hopefully only temporary, until Xerces implements DOM 3 LSParser.parseWithContext(). - parserPool = new BasicParserPool(); - parserPool.setNamespaceAware(true); + // Note: Use of this internal JAXP ParserPool is hopefully only temporary, + // to be replaced when Xerces implements DOM 3 LSParser.parseWithContext(...). + parserPool = buildParserPool(); - // Note: this is necessary due to an unresolved Xerces deferred DOM issue/bug - HashMap features = new HashMap(); - features.put("http://apache.org/xml/features/dom/defer-node-expansion", Boolean.FALSE); - parserPool.setBuilderFeatures(features); - unmarshallerFactory = Configuration.getUnmarshallerFactory(); defaultRootInNewDocument = false; } - + /** * Get the flag which indicates whether by default the DOM Element which backs a decrypted SAML object * will be the root of a new DOM document. Defaults to false. @@ -339,9 +339,20 @@ * * @return the static criteria set to use */ - public CriteriaSet setKeyResolverCriteria() { + public CriteriaSet getKeyResolverCriteria() { return resolverCriteria; } + + /** + * Get the optional static set of criteria used when resolving credentials based on the KeyInfo of an EncryptedData + * element. + * + * @return the static criteria set to use + * @deprecated due to typo, use {@link #getKeyResolverCriteria()} + */ + public CriteriaSet setKeyResolverCriteria() { + return getKeyResolverCriteria(); + } /** * Set the optional static set of criteria used when resolving credentials based on the KeyInfo of an EncryptedData @@ -586,6 +597,11 @@ } catch (XMLEncryptionException e) { log.error("Error decrypting the encrypted data element", e); throw new DecryptionException("Error decrypting the encrypted data element", e); + } catch (Exception e) { + // Catch anything else, esp. unchecked RuntimeException, and convert to our checked type. + // BouncyCastle in particular is known to throw unchecked exceptions for what we would + // consider "routine" failures. + throw new DecryptionException("Probable runtime exception on decryption:" + e.getMessage(), e); } if (bytes == null) { throw new DecryptionException("EncryptedData could not be decrypted"); @@ -693,6 +709,11 @@ } catch (XMLEncryptionException e) { log.error("Error decrypting encrypted key", e); throw new DecryptionException("Error decrypting encrypted key", e); + } catch (Exception e) { + // Catch anything else, esp. unchecked RuntimeException, and convert to our checked type. + // BouncyCastle in particular is known to throw unchecked exceptions for what we would + // consider "routine" failures. + throw new DecryptionException("Probable runtime exception on decryption:" + e.getMessage(), e); } if (key == null) { throw new DecryptionException("Key could not be decrypted"); @@ -955,6 +976,40 @@ } } } + + /** + * Build the internal parser pool instance used to parse decrypted XML. + * + *

+ * Note: When using a Xerces parser or derivative, the following feature must be set to false: + * http://apache.org/xml/features/dom/defer-node-expansion + *

+ * + * @return a new parser pool instance + */ + protected ParserPool buildParserPool() { + StaticBasicParserPool pp = new StaticBasicParserPool(); + HashMap features = new HashMap(); + + pp.setNamespaceAware(true); + + // Note: this feature config is necessary due to an unresolved Xerces deferred DOM issue/bug + features.put("http://apache.org/xml/features/dom/defer-node-expansion", Boolean.FALSE); + + // The following config is to harden the parser pool against known XML security vulnerabilities + pp.setExpandEntityReferences(false); + features.put(XMLConstants.FEATURE_SECURE_PROCESSING, true); + features.put("http://apache.org/xml/features/disallow-doctype-decl", true); + + pp.setBuilderFeatures(features); + + try { + pp.initialize(); + return pp; + } catch (XMLParserException e) { + throw new XMLRuntimeException("Problem initializing Decrypter internal ParserPool", e); + } + } /* * NOTE: this currently won't work because Xerces doesn't implement LSParser.parseWithContext(). Hopefully they will Index: 3rdParty_sources/xmltooling/org/opensaml/xml/encryption/SimpleKeyInfoReferenceEncryptedKeyResolver.java =================================================================== diff -u -r3209d0745e0d05225bcc4da28894cd4b4b0b5f34 -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/encryption/SimpleKeyInfoReferenceEncryptedKeyResolver.java (.../SimpleKeyInfoReferenceEncryptedKeyResolver.java) (revision 3209d0745e0d05225bcc4da28894cd4b4b0b5f34) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/encryption/SimpleKeyInfoReferenceEncryptedKeyResolver.java (.../SimpleKeyInfoReferenceEncryptedKeyResolver.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -46,7 +46,7 @@ private int depthLimit; /** Constructor. */ - SimpleKeyInfoReferenceEncryptedKeyResolver() { + public SimpleKeyInfoReferenceEncryptedKeyResolver() { depthLimit = 5; } Index: 3rdParty_sources/xmltooling/org/opensaml/xml/parse/BasicParserPool.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/parse/BasicParserPool.java (.../BasicParserPool.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/parse/BasicParserPool.java (.../BasicParserPool.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -23,15 +23,16 @@ import java.io.Reader; import java.lang.ref.SoftReference; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.Stack; +import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.validation.Schema; -import org.opensaml.xml.Configuration; import org.opensaml.xml.util.LazyMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -124,8 +125,8 @@ builderPool = new Stack>(); builderAttributes = new LazyMap(); coalescing = true; - expandEntityReferences = true; - builderFeatures = new LazyMap(); + expandEntityReferences = false; + builderFeatures = buildDefaultFeatures(); ignoreComments = true; ignoreElementContentWhitespace = true; namespaceAware = true; @@ -164,10 +165,11 @@ } if (builder != null) { + prepareBuilder(builder); return new DocumentBuilderProxy(builder, this, version); } - return null; + throw new XMLParserException("Unable to obtain a DocumentBuilder"); } /** {@inheritDoc} */ @@ -206,6 +208,9 @@ DocumentBuilder builder = getBuilder(); Document document = builder.newDocument(); returnBuilder(builder); + if (document == null) { + throw new XMLParserException("DocumentBuilder returned a null Document"); + } return document; } @@ -214,6 +219,9 @@ DocumentBuilder builder = getBuilder(); try { Document document = builder.parse(input); + if (document == null) { + throw new XMLParserException("DocumentBuilder parsed a null Document"); + } return document; } catch (SAXException e) { throw new XMLParserException("Invalid XML", e); @@ -229,6 +237,9 @@ DocumentBuilder builder = getBuilder(); try { Document document = builder.parse(new InputSource(input)); + if (document == null) { + throw new XMLParserException("DocumentBuilder parsed a null Document"); + } return document; } catch (SAXException e) { throw new XMLParserException("Invalid XML", e); @@ -572,20 +583,49 @@ try { DocumentBuilder builder = builderFactory.newDocumentBuilder(); - if (entityResolver != null) { - builder.setEntityResolver(entityResolver); - } - - if (errorHandler != null) { - builder.setErrorHandler(errorHandler); - } - return builder; } catch (ParserConfigurationException e) { log.error("Unable to create new document builder", e); throw new XMLParserException("Unable to create new document builder", e); } } + + /** + * Prepare a document builder instance for use, before returning it from a checkout call. + * + * @param builder the document builder to prepare + */ + private void prepareBuilder(DocumentBuilder builder) { + if (entityResolver != null) { + builder.setEntityResolver(entityResolver); + } + + if (errorHandler != null) { + builder.setErrorHandler(errorHandler); + } + } + + /** + * Build the default set of parser features to use. + * + *

These will be overriden by a call to {@link #setBuilderFeatures(Map)}.

+ * + *

+ * The default features set are: + *

    + *
  • {@link XMLConstants#FEATURE_SECURE_PROCESSING} = true
  • + *
  • http://apache.org/xml/features/disallow-doctype-decl = true
  • + *
+ *

+ * + * @return the default features map + */ + protected Map buildDefaultFeatures() { + HashMap features = new HashMap(); + features.put(XMLConstants.FEATURE_SECURE_PROCESSING, true); + features.put("http://apache.org/xml/features/disallow-doctype-decl", true); + return features; + } /** * A proxy that prevents the manages document builders retrieved from the parser pool. Index: 3rdParty_sources/xmltooling/org/opensaml/xml/parse/ClasspathResolver.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/parse/ClasspathResolver.java (.../ClasspathResolver.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/parse/ClasspathResolver.java (.../ClasspathResolver.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -51,7 +51,10 @@ public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { InputStream resourceStream = resolver(publicId, systemId); if (resourceStream != null) { - return new InputSource(resourceStream); + InputSource is = new InputSource(resourceStream); + is.setSystemId(systemId); + is.setPublicId(publicId); + return is; } return null; Index: 3rdParty_sources/xmltooling/org/opensaml/xml/parse/StaticBasicParserPool.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/parse/StaticBasicParserPool.java (.../StaticBasicParserPool.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/parse/StaticBasicParserPool.java (.../StaticBasicParserPool.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -23,15 +23,16 @@ import java.io.Reader; import java.lang.ref.SoftReference; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.Stack; +import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.validation.Schema; -import org.opensaml.xml.Configuration; import org.opensaml.xml.util.LazyMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -120,8 +121,8 @@ builderPool = new Stack>(); builderAttributes = new LazyMap(); coalescing = true; - expandEntityReferences = true; - builderFeatures = new LazyMap(); + expandEntityReferences = false; + builderFeatures = buildDefaultFeatures(); ignoreComments = true; ignoreElementContentWhitespace = true; namespaceAware = true; @@ -177,10 +178,11 @@ } if (builder != null) { + prepareBuilder(builder); return new DocumentBuilderProxy(builder, this); } - return null; + throw new XMLParserException("Unable to obtain a DocumentBuilder"); } /** {@inheritDoc} */ @@ -222,6 +224,9 @@ DocumentBuilder builder = getBuilder(); Document document = builder.newDocument(); returnBuilder(builder); + if (document == null) { + throw new XMLParserException("DocumentBuilder returned a null Document"); + } return document; } @@ -230,6 +235,9 @@ DocumentBuilder builder = getBuilder(); try { Document document = builder.parse(input); + if (document == null) { + throw new XMLParserException("DocumentBuilder parsed a null Document"); + } return document; } catch (SAXException e) { throw new XMLParserException("Invalid XML", e); @@ -245,6 +253,9 @@ DocumentBuilder builder = getBuilder(); try { Document document = builder.parse(new InputSource(input)); + if (document == null) { + throw new XMLParserException("DocumentBuilder parsed a null Document"); + } return document; } catch (SAXException e) { throw new XMLParserException("Invalid XML", e); @@ -554,20 +565,49 @@ try { DocumentBuilder builder = builderFactory.newDocumentBuilder(); - if (entityResolver != null) { - builder.setEntityResolver(entityResolver); - } - - if (errorHandler != null) { - builder.setErrorHandler(errorHandler); - } - return builder; } catch (ParserConfigurationException e) { log.error("Unable to create new document builder", e); throw new XMLParserException("Unable to create new document builder", e); } } + + /** + * Prepare a document builder instance for use, before returning it from a checkout call. + * + * @param builder the document builder to prepare + */ + private void prepareBuilder(DocumentBuilder builder) { + if (entityResolver != null) { + builder.setEntityResolver(entityResolver); + } + + if (errorHandler != null) { + builder.setErrorHandler(errorHandler); + } + } + + /** + * Build the default set of parser features to use. + * + *

These will be overriden by a call to {@link #setBuilderFeatures(Map)}.

+ * + *

+ * The default features set are: + *

    + *
  • {@link XMLConstants#FEATURE_SECURE_PROCESSING} = true
  • + *
  • http://apache.org/xml/features/disallow-doctype-decl = true
  • + *
+ *

+ * + * @return the default features map + */ + protected Map buildDefaultFeatures() { + HashMap features = new HashMap(); + features.put(XMLConstants.FEATURE_SECURE_PROCESSING, true); + features.put("http://apache.org/xml/features/disallow-doctype-decl", true); + return features; + } /** * A proxy that prevents the manages document builders retrieved from the parser pool. Index: 3rdParty_sources/xmltooling/org/opensaml/xml/security/DefaultSecurityConfigurationBootstrap.java =================================================================== diff -u -r3209d0745e0d05225bcc4da28894cd4b4b0b5f34 -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/security/DefaultSecurityConfigurationBootstrap.java (.../DefaultSecurityConfigurationBootstrap.java) (revision 3209d0745e0d05225bcc4da28894cd4b4b0b5f34) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/security/DefaultSecurityConfigurationBootstrap.java (.../DefaultSecurityConfigurationBootstrap.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -144,6 +144,7 @@ // Generator for X509Credentials X509KeyInfoGeneratorFactory x509Factory = new X509KeyInfoGeneratorFactory(); x509Factory.setEmitEntityCertificate(true); + x509Factory.setEmitEntityCertificateChain(true); defaultManager.registerFactory(basicFactory); defaultManager.registerFactory(x509Factory); Index: 3rdParty_sources/xmltooling/org/opensaml/xml/security/SecurityHelper.java =================================================================== diff -u -r3209d0745e0d05225bcc4da28894cd4b4b0b5f34 -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/security/SecurityHelper.java (.../SecurityHelper.java) (revision 3209d0745e0d05225bcc4da28894cd4b4b0b5f34) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/security/SecurityHelper.java (.../SecurityHelper.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -60,6 +60,7 @@ import org.apache.xml.security.Init; import org.apache.xml.security.algorithms.JCEMapper; import org.opensaml.xml.Configuration; +import org.opensaml.xml.encryption.EncryptionConstants; import org.opensaml.xml.encryption.EncryptionParameters; import org.opensaml.xml.encryption.KeyEncryptionParameters; import org.opensaml.xml.security.credential.BasicCredential; @@ -198,7 +199,18 @@ + "' to key algorithm not available, key generation failed"); throw new NoSuchAlgorithmException("Algorithm URI'" + algoURI + "' is invalid for key generation"); } - Integer keyLength = getKeyLengthFromURI(algoURI); + + Integer keyLength = null; + if (EncryptionConstants.ALGO_ID_BLOCKCIPHER_TRIPLEDES.equals(algoURI) + || EncryptionConstants.ALGO_ID_KEYWRAP_TRIPLEDES.equals(algoURI)) { + // We have to special case this b/c a 3DES key is 192 bits, but with KeyGenerator the JCA providers + // inconsistently allow either 112/168 (SunJCE) or 112/168/192 (BC). Per JCA docs they're all + // required to support 168. We don't do this in getKeyLength() b/c the 3DES key actually is 192 bits. + keyLength = 168; + } else { + keyLength = getKeyLengthFromURI(algoURI); + } + if (keyLength == null) { log.error("Key length could not be determined from algorithm URI, can't generate key"); throw new KeyException("Key length not determinable from algorithm URI, could not generate new key"); @@ -401,7 +413,7 @@ if (key instanceof DSAPrivateKey) { DSAPrivateKey dsaKey = (DSAPrivateKey) key; DSAParams keyParams = dsaKey.getParams(); - BigInteger y = keyParams.getQ().modPow(dsaKey.getX(), keyParams.getP()); + BigInteger y = keyParams.getG().modPow(dsaKey.getX(), keyParams.getP()); DSAPublicKeySpec pubKeySpec = new DSAPublicKeySpec(y, keyParams.getP(), keyParams.getQ(), keyParams.getG()); try { Index: 3rdParty_sources/xmltooling/org/opensaml/xml/security/trust/ExplicitKeyTrustEvaluator.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/security/trust/ExplicitKeyTrustEvaluator.java (.../ExplicitKeyTrustEvaluator.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/security/trust/ExplicitKeyTrustEvaluator.java (.../ExplicitKeyTrustEvaluator.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -105,11 +105,18 @@ */ public boolean validate(Credential untrustedCredential, Iterable trustedCredentials) { + boolean empty = true; + for (Credential trustedCredential : trustedCredentials) { + empty = false; if (validate(untrustedCredential, trustedCredential)) { return true; } } + + if (empty) { + log.debug("No trusted credentials were provided to evaluate against"); + } return false; } Index: 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/BasicX509CredentialNameEvaluator.java =================================================================== diff -u -r3209d0745e0d05225bcc4da28894cd4b4b0b5f34 -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/BasicX509CredentialNameEvaluator.java (.../BasicX509CredentialNameEvaluator.java) (revision 3209d0745e0d05225bcc4da28894cd4b4b0b5f34) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/BasicX509CredentialNameEvaluator.java (.../BasicX509CredentialNameEvaluator.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -217,8 +217,8 @@ log.debug("No trusted name options are active, skipping name evaluation"); return true; } else if (trustedNames == null || trustedNames.isEmpty()) { - log.debug("Supplied trusted names are null or empty, skipping name evaluation"); - return true; + log.debug("Supplied trusted names are null or empty, failing name evaluation"); + return false; } if (log.isDebugEnabled()) { Index: 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/PKIXX509CredentialTrustEngine.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/PKIXX509CredentialTrustEngine.java (.../PKIXX509CredentialTrustEngine.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/PKIXX509CredentialTrustEngine.java (.../PKIXX509CredentialTrustEngine.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -192,6 +192,10 @@ if (credNameEvaluator == null) { log.debug("No credential name evaluator was available, skipping trusted name evaluation"); return true; + } else if (trustedNames == null) { + log.debug("Trusted names was null, signalling PKIX resolver does not support trusted names resolution, " + + "skipping trusted name evaluation"); + return true; } else { return credNameEvaluator.evaluate(untrustedCredential, trustedNames); } Index: 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/StaticPKIXValidationInformationResolver.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/StaticPKIXValidationInformationResolver.java (.../StaticPKIXValidationInformationResolver.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/StaticPKIXValidationInformationResolver.java (.../StaticPKIXValidationInformationResolver.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -25,6 +25,7 @@ import org.opensaml.xml.security.CriteriaSet; import org.opensaml.xml.security.SecurityException; +import org.opensaml.xml.security.criteria.EntityIDCriteria; /** * An implementation of {@link PKIXValidationInformationResolver} which always returns a static, fixed set of @@ -61,8 +62,13 @@ /** {@inheritDoc} */ public Set resolveTrustedNames(CriteriaSet criteriaSet) throws SecurityException, UnsupportedOperationException { - - return trustedNames; + + HashSet temp = new HashSet(trustedNames); + EntityIDCriteria entityIDCriteria = criteriaSet.get(EntityIDCriteria.class); + if (entityIDCriteria != null) { + temp.add(entityIDCriteria.getEntityID()); + } + return temp; } /** {@inheritDoc} */ Index: 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/X509Util.java =================================================================== diff -u -r3209d0745e0d05225bcc4da28894cd4b4b0b5f34 -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/X509Util.java (.../X509Util.java) (revision 3209d0745e0d05225bcc4da28894cd4b4b0b5f34) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/X509Util.java (.../X509Util.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -32,24 +32,22 @@ import java.security.cert.X509CRL; import java.security.cert.X509Certificate; import java.util.Collection; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import javax.security.auth.x500.X500Principal; import org.apache.commons.ssl.TrustMaterial; +import org.bouncycastle.asn1.ASN1Encoding; import org.bouncycastle.asn1.ASN1InputStream; -import org.bouncycastle.asn1.DERObject; -import org.bouncycastle.asn1.DERObjectIdentifier; -import org.bouncycastle.asn1.DERSequence; -import org.bouncycastle.asn1.DERSet; -import org.bouncycastle.asn1.DERString; -import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; -import org.bouncycastle.asn1.x509.X509Extensions; -import org.bouncycastle.util.Arrays; -import org.bouncycastle.x509.extension.SubjectKeyIdentifierStructure; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.ASN1String; +import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.x509.extension.X509ExtensionUtil; -import org.opensaml.xml.schema.SchemaBuilder; import org.opensaml.xml.security.SecurityException; import org.opensaml.xml.security.SecurityHelper; import org.opensaml.xml.util.DatatypeHelper; @@ -69,6 +67,9 @@ /** Common Name (CN) OID. */ public static final String CN_OID = "2.5.4.3"; + + /** Subject Key Identifier (SKI) OID. */ + public static final String SKI_OID = "2.5.29.14"; /** RFC 2459 Other Subject Alt Name type. */ public static final Integer OTHER_ALT_NAME = new Integer(0); @@ -136,12 +137,17 @@ } /** - * Gets the commons names that appear within the given distinguished name. The returned list provides the names in - * the order they appeared in the DN. + * Gets the commons names that appear within the given distinguished name. * + *

+ * The returned list provides the names in the order they appeared in the DN, according to + * RFC 1779/2253 encoding. In this encoding the "most specific" name would typically appear + * in the left-most position, and would appear first in the returned list. + *

+ * * @param dn the DN to extract the common names from * - * @return the common names that appear in the DN in the order they appear or null if the given DN is null + * @return the common names that appear in the DN in the order they appear, or null if the given DN is null */ public static List getCommonNames(X500Principal dn) { Logger log = getLogger(); @@ -153,33 +159,35 @@ List commonNames = new LinkedList(); try { ASN1InputStream asn1Stream = new ASN1InputStream(dn.getEncoded()); - DERObject parent = asn1Stream.readObject(); + ASN1Sequence dnSequence = (ASN1Sequence) asn1Stream.readObject(); - String cn = null; - DERObject dnComponent; - DERSequence grandChild; - DERObjectIdentifier componentId; - for (int i = 0; i < ((DERSequence) parent).size(); i++) { - dnComponent = ((DERSequence) parent).getObjectAt(i).getDERObject(); - if (!(dnComponent instanceof DERSet)) { - log.debug("No DN components."); + // Walk the DN sequence in reverse order from last to first, so that the CN(s) from the most-specific RDN + // are first in the returned list, consistent with RFC 1779/2253 RDN ordering. + for (int i = dnSequence.size()-1; i >= 0; i--) { + ASN1Primitive rdn = dnSequence.getObjectAt(i).toASN1Primitive(); + if (!(rdn instanceof ASN1Set)) { + log.debug("DN RDN was not an instance of ASN1Set."); continue; } + + // Each RDN is an ASN.1 set (note: unordered) + ASN1Set rdnSet = (ASN1Set) rdn; - // Each DN component is a set - for (int j = 0; j < ((DERSet) dnComponent).size(); j++) { - grandChild = (DERSequence) ((DERSet) dnComponent).getObjectAt(j).getDERObject(); + // Walk the attributes within the RDN from first to last, to preserve the ordering of the encoded form. + for (int j = 0; j < rdnSet.size(); j++) { + ASN1Sequence attributeTypeAndValue = (ASN1Sequence) rdnSet.getObjectAt(j).toASN1Primitive(); - if (grandChild.getObjectAt(0) != null - && grandChild.getObjectAt(0).getDERObject() instanceof DERObjectIdentifier) { - componentId = (DERObjectIdentifier) grandChild.getObjectAt(0).getDERObject(); + if (attributeTypeAndValue.getObjectAt(0) != null + && attributeTypeAndValue.getObjectAt(0).toASN1Primitive() instanceof ASN1ObjectIdentifier) { + ASN1ObjectIdentifier attributeTypeId = (ASN1ObjectIdentifier) attributeTypeAndValue + .getObjectAt(0).toASN1Primitive(); - if (CN_OID.equals(componentId.getId())) { - // OK, this dn component is actually a cn attribute - if (grandChild.getObjectAt(1) != null - && grandChild.getObjectAt(1).getDERObject() instanceof DERString) { - cn = ((DERString) grandChild.getObjectAt(1).getDERObject()).getString(); - commonNames.add(cn); + if (CN_OID.equals(attributeTypeId.getId())) { + // OK, this AVA is actually a cn attribute + if (attributeTypeAndValue.getObjectAt(1) != null + && attributeTypeAndValue.getObjectAt(1).toASN1Primitive() instanceof ASN1String) { + ASN1String cn = (ASN1String) attributeTypeAndValue.getObjectAt(1).toASN1Primitive(); + commonNames.add(cn.getString()); } } } @@ -237,7 +245,7 @@ } /** - * Gets the common name components of the issuer and all the subject alt names of a given type. + * Gets the common name components of the subject and all the subject alt names of a given type. * * @param certificate certificate to extract names from * @param altNameTypes type of alt names to extract @@ -266,15 +274,15 @@ */ public static byte[] getSubjectKeyIdentifier(X509Certificate certificate) { Logger log = getLogger(); - byte[] derValue = certificate.getExtensionValue(X509Extensions.SubjectKeyIdentifier.getId()); + byte[] derValue = certificate.getExtensionValue(SKI_OID); + if (derValue == null || derValue.length == 0) { return null; } - SubjectKeyIdentifier ski = null; try { - ski = new SubjectKeyIdentifierStructure(derValue); - return ski.getKeyIdentifier(); + final ASN1Primitive ski = X509ExtensionUtil.fromExtensionValue(derValue); + return ((DEROctetString) ski).getOctets(); } catch (IOException e) { log.error("Unable to extract subject key identifier from certificate: ASN.1 parsing failed: " + e); return null; @@ -466,7 +474,13 @@ || OTHER_ALT_NAME.equals(nameType)) { // these have no defined representation, just return a DER-encoded byte[] - return ((DERObject) nameValue).getDEREncoded(); + try { + return ((ASN1Primitive) nameValue).getEncoded(ASN1Encoding.DER); + } catch (IOException e) { + log.error("Encountered problem producing ASN1Primitive from alt name of type: " + nameType, e); + return null; + } + } log.warn("Encountered unknown alt name type '{}', adding as-is", nameType); Index: 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/tls/StrictHostnameVerifier.java =================================================================== diff -u --- 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/tls/StrictHostnameVerifier.java (revision 0) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/security/x509/tls/StrictHostnameVerifier.java (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -0,0 +1,58 @@ +/* + * Licensed to the University Corporation for Advanced Internet Development, + * Inc. (UCAID) under one or more contributor license agreements. See the + * NOTICE file distributed with this work for additional information regarding + * copyright ownership. The UCAID licenses this file to You under the Apache + * License, Version 2.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.opensaml.xml.security.x509.tls; + +import java.security.cert.X509Certificate; + +import javax.net.ssl.SSLException; + +import org.apache.commons.ssl.Certificates; +import org.apache.commons.ssl.HostnameVerifier.AbstractVerifier; +import org.opensaml.xml.security.x509.X509Util; + +/** + * An implementation of {@link javax.net.ssl.HostnameVerifier} which implements strict hostname validation. + * + *

+ * This verifier implementation is based on the not-yet-commons-ssl {@link AbstractVerifier}. + * It differs from the not-yet-commons-ssl STRICT implementation by performing certificate common name (CN) + * extraction by parsing the ASN.1 representation of the certificate's {@link javax.security.auth.x500.X500Principal}. + * For further implementation details, see the Javadocs for {@link org.apache.commons.ssl.HostnameVerifier.STRICT}. + *

+ */ +public class StrictHostnameVerifier extends AbstractVerifier { + + /** {@inheritDoc} */ + public final void check(final String[] host, final String[] cns, final String[] subjectAlts) throws SSLException { + check(host, cns, subjectAlts, false, true); + } + + /** {@inheritDoc} */ + public void check(String[] host, X509Certificate cert) throws SSLException { + String[] cns = X509Util.getCommonNames(cert.getSubjectX500Principal()).toArray(new String[0]); + String[] subjectAlts = Certificates.getDNSSubjectAlts(cert); + //Note: could use X509Util for subject alt names also, per below. + //List subjectAltsList = X509Util.getAltNames(cert, new Integer[]{X509Util.DNS_ALT_NAME}); + //String[] subjectAlts = subjectAltsList.toArray(new String[0]); + check(host, cns, subjectAlts); + } + + /** {@inheritDoc} */ + public final String toString() { return "XMLTOOLING_STRICT"; } + +} Index: 3rdParty_sources/xmltooling/org/opensaml/xml/signature/SignatureValidator.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/signature/SignatureValidator.java (.../SignatureValidator.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/signature/SignatureValidator.java (.../SignatureValidator.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -74,9 +74,9 @@ throw new ValidationException("Unable to evaluate key against signature", e); } - log.debug("Signature did not validate against the credential's key"); + log.debug("Signature cryptographic validation not successful"); - throw new ValidationException("Signature did not validate against the credential's key"); + throw new ValidationException("Signature cryptographic validation not successful"); } /** Index: 3rdParty_sources/xmltooling/org/opensaml/xml/signature/impl/PKIXSignatureTrustEngine.java =================================================================== diff -u -r3209d0745e0d05225bcc4da28894cd4b4b0b5f34 -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/signature/impl/PKIXSignatureTrustEngine.java (.../PKIXSignatureTrustEngine.java) (revision 3209d0745e0d05225bcc4da28894cd4b4b0b5f34) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/signature/impl/PKIXSignatureTrustEngine.java (.../PKIXSignatureTrustEngine.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -277,6 +277,10 @@ if (credNameEvaluator == null) { log.debug("No credential name evaluator was available, skipping trusted name evaluation"); return true; + } else if (trustedNames == null) { + log.debug("Trusted names was null, signalling PKIX resolver does not support trusted names resolution, " + + "skipping trusted name evaluation"); + return true; } else { return credNameEvaluator.evaluate(untrustedCredential, trustedNames); } Index: 3rdParty_sources/xmltooling/org/opensaml/xml/util/AttributeMap.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/util/AttributeMap.java (.../AttributeMap.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/util/AttributeMap.java (.../AttributeMap.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -83,7 +83,7 @@ /** {@inheritDoc} */ public String put(QName attributeName, String value) { String oldValue = get(attributeName); - if (value != oldValue) { + if (!DatatypeHelper.safeEquals(value, oldValue)) { releaseDOM(); attributes.put(attributeName, value); if (isIDAttribute(attributeName) || Configuration.isIDAttribute(attributeName)) { Index: 3rdParty_sources/xmltooling/org/opensaml/xml/util/IndexingObjectStore.java =================================================================== diff -u -r2e3463e873227c6a3edcb3e02d55270219e553ff -rc08ba6bf73897a72b1699db8aab0f3ad0ba84a60 --- 3rdParty_sources/xmltooling/org/opensaml/xml/util/IndexingObjectStore.java (.../IndexingObjectStore.java) (revision 2e3463e873227c6a3edcb3e02d55270219e553ff) +++ 3rdParty_sources/xmltooling/org/opensaml/xml/util/IndexingObjectStore.java (.../IndexingObjectStore.java) (revision c08ba6bf73897a72b1699db8aab0f3ad0ba84a60) @@ -25,20 +25,29 @@ import net.jcip.annotations.ThreadSafe; /** - * This class is used to store instances of objects that may be created independently but are, in face, the same object. - * For example, {@link org.opensaml.xml.signature.KeyInfo}s contain keys, certs, and CRLs. Multiple unique instances of + *

+ * This class is used to store instances of objects that may be created independently but are, in fact, the same object. + * For example, KeyInfo XML structures contain keys, certs, and CRLs. Multiple unique instances of * a KeyInfo may contain, and separately construct, the exact same cert. KeyInfo could, therefore, create a class-level * instance of this object store and put certs within it. In this manner the cert is only sitting in memory once and * each KeyInfo simply stores a reference (index) to stored object. + *

* + *

* This store uses basic reference counting to keep track of how many of the respective objects are pointing to an - * entry. Adding an object that already exists, as determined by the objects hashCode() method, simply + * entry. Adding an object that already exists, as determined by the object's equals() method, simply * increments the reference counter. Removing an object decrements the counter. Only when the counter reaches zero is * the object actually freed for garbage collection. + *

* - * Note the instance of an object returned by {@link #get(String)} need not be the same object as - * stored via {@link #put(Object)}. However, their hash codes will be equal. Therefore this store should never be - * used to store objects that produce identical hash codes but are not functionally identical objects. + *

+ * Note: the instance of an object returned by {@link #get(String)} need not be the same object as + * stored via {@link #put(Object)}. However, the instances will be equal according to their equals(). + * The indexing and storage is based on use of {@link Map}, so the normal caveats related to use of hash-based + * collection types apply: if the stored object's hashCode() and equals() methods are + * implemented based on mutable properties of the object, then those object instance's properties should not + * be mutated while the object is stored, otherwise unpredictable behavior will result. + *

* * @param type of object being stored */ @@ -50,11 +59,19 @@ /** Backing object data store. */ private Map objectStore; + + /** Map of object instances to the index value used to reference them externally. */ + private Map indexStore; + + /** The last index sequence used. */ + private int lastIndex; /** Constructor. */ public IndexingObjectStore() { rwLock = new ReentrantReadWriteLock(); objectStore = new LazyMap(); + indexStore = new LazyMap(); + lastIndex = 0; } /** Clears the object store. */ @@ -63,6 +80,7 @@ writeLock.lock(); try { objectStore.clear(); + indexStore.clear(); } finally { writeLock.unlock(); } @@ -92,7 +110,13 @@ * @return true if the store is empty, false if not */ public boolean isEmpty() { - return objectStore.isEmpty(); + Lock readLock = rwLock.readLock(); + readLock.lock(); + try { + return objectStore.isEmpty(); + } finally { + readLock.unlock(); + } } /** @@ -111,7 +135,7 @@ Lock writeLock = rwLock.writeLock(); writeLock.lock(); try { - String index = Integer.toString(object.hashCode()); + String index = getIndex(object); StoredObjectWrapper objectWrapper = objectStore.get(index); if (objectWrapper == null) { @@ -172,6 +196,7 @@ objectWrapper.decremementReferenceCount(); if (objectWrapper.getReferenceCount() == 0) { objectStore.remove(index); + removeIndex(objectWrapper.getObject()); } } } finally { @@ -186,8 +211,38 @@ * @return number of items in the store */ public int size() { - return objectStore.size(); + Lock readLock = rwLock.readLock(); + readLock.lock(); + try { + return objectStore.size(); + } finally { + readLock.unlock(); + } } + + /** + * Get the index for the specified object. + * + * @param object the target object + * @return the object index value + */ + protected String getIndex(T object) { + Integer index = indexStore.get(object); + if (index == null) { + index = ++lastIndex; + indexStore.put(object, index); + } + return index.toString(); + } + + /** + * Remove the index for the specified object. + * + * @param object the target index + */ + protected void removeIndex(T object) { + indexStore.remove(object); + } /** Wrapper class that keeps track of the reference count for a stored object. */ private class StoredObjectWrapper {