You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by co...@apache.org on 2016/10/18 15:06:05 UTC
svn commit: r1765457 - in /webservices/wss4j/trunk:
ws-security-common/src/main/java/org/apache/wss4j/common/
ws-security-common/src/main/java/org/apache/wss4j/common/crypto/
ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/
ws-security-dom/s...
Author: coheigea
Date: Tue Oct 18 15:06:04 2016
New Revision: 1765457
URL: http://svn.apache.org/viewvc?rev=1765457&view=rev
Log:
added support for a constraint on issuer DN of client certificate
Added:
webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureIssuerCertConstraintsTest.java
webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureIssuerCertConstaintsTest.java
Modified:
webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ConfigurationConstants.java
webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CertificateStore.java
webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Crypto.java
webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CryptoBase.java
webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Merlin.java
webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/MerlinAKI.java
webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/RequestData.java
webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/WSHandler.java
webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/SignatureTrustValidator.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/SamlSecurityTokenImpl.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/X509SecurityTokenImpl.java
webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/setup/ConfigurationConverter.java
Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ConfigurationConstants.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ConfigurationConstants.java?rev=1765457&r1=1765456&r2=1765457&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ConfigurationConstants.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/ConfigurationConstants.java Tue Oct 18 15:06:04 2016
@@ -817,6 +817,14 @@ public class ConfigurationConstants {
public static final String SIG_SUBJECT_CERT_CONSTRAINTS = "sigSubjectCertConstraints";
/**
+ * This configuration tag is a comma separated String of regular expressions which
+ * will be applied to the issuer DN of the certificate used for signature
+ * validation, after trust verification of the certificate chain associated with the
+ * certificate.
+ */
+ public static final String SIG_ISSUER_CERT_CONSTRAINTS = "sigIssuerCertConstraints";
+
+ /**
* Time-To-Live is the time difference between creation and expiry time in
* seconds in the WSS Timestamp. After this time the SOAP request is
* invalid (at least the security data shall be treated this way).
Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CertificateStore.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CertificateStore.java?rev=1765457&r1=1765456&r2=1765457&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CertificateStore.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CertificateStore.java Tue Oct 18 15:06:04 2016
@@ -268,7 +268,16 @@ public class CertificateStore extends Cr
}
// Finally check Cert Constraints
- if (!matches(certs[0], subjectCertConstraints)) {
+ if (!matchesSubjectDnPattern(certs[0], subjectCertConstraints)) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
+ }
+ }
+
+ @Override
+ public void verifyTrust(X509Certificate[] certs, boolean enableRevocation, Collection<Pattern> subjectCertConstraints,
+ Collection<Pattern> issuerCertConstraints) throws WSSecurityException {
+ verifyTrust(certs,enableRevocation,subjectCertConstraints);
+ if (!matchesIssuerDnPattern(certs[0], issuerCertConstraints)) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
}
}
Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Crypto.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Crypto.java?rev=1765457&r1=1765456&r2=1765457&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Crypto.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Crypto.java Tue Oct 18 15:06:04 2016
@@ -217,6 +217,21 @@ public interface Crypto {
) throws WSSecurityException;
/**
+ * Evaluate whether a given certificate chain should be trusted.
+ *
+ * @param certs Certificate chain to validate
+ * @param enableRevocation whether to enable CRL verification or not
+ * @param subjectCertConstraints A set of constraints on the Subject DN of the certificates
+ * @param issuerCertConstraints A set of constraints on the Issuer DN of the certificates
+ * @throws WSSecurityException if the certificate chain is invalid
+ */
+ void verifyTrust(
+ X509Certificate[] certs, boolean enableRevocation,
+ Collection<Pattern> subjectCertConstraints,Collection<Pattern> issuerCertConstraints
+ ) throws WSSecurityException;
+
+
+ /**
* Evaluate whether a given public key should be trusted directly (located
*
* @param certs Certificate chain to validate
Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CryptoBase.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CryptoBase.java?rev=1765457&r1=1765456&r2=1765457&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CryptoBase.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/CryptoBase.java Tue Oct 18 15:06:04 2016
@@ -318,25 +318,60 @@ public abstract class CryptoBase impleme
* has to match ONE of the subject cert constraints (not all).
*/
protected boolean
- matches(
+ matchesSubjectDnPattern(
final X509Certificate cert, final Collection<Pattern> subjectDNPatterns
) {
- if (subjectDNPatterns == null || subjectDNPatterns.isEmpty()) {
- LOG.warn("No Subject DN Certificate Constraints were defined. This could be a security issue");
- return true;
+
+ if (cert == null) {
+ LOG.debug("The certificate is null so no constraints matching was possible");
+ return false;
}
- if (!subjectDNPatterns.isEmpty()) {
+ String subjectName = cert.getSubjectX500Principal().getName();
+ return matchesName(subjectName,subjectDNPatterns);
+ }
+
+ /**
+ * @return true if the certificate's Issuer DN matches the constraints defined in the
+ * subject DNConstraints; false, otherwise. The certificate subject DN only
+ * has to match ONE of the subject cert constraints (not all).
+ */
+ protected boolean
+ matchesIssuerDnPattern(
+ final X509Certificate cert, final Collection<Pattern> issuerDNPatterns
+ ) {
+
if (cert == null) {
LOG.debug("The certificate is null so no constraints matching was possible");
return false;
}
- String subjectName = cert.getSubjectX500Principal().getName();
+ String issuerDn = cert.getIssuerDN().getName();
+ return matchesName(issuerDn,issuerDNPatterns);
+ }
+
+ /**
+ * @return true if the provided name matches the constraints defined in the
+ * subject DNConstraints; false, otherwise. The certificate subject DN only
+ * has to match ONE of the subject cert constraints (not all).
+ */
+ protected boolean
+ matchesName(
+ final String name, final Collection<Pattern> patterns
+ ) {
+ if (patterns == null || patterns.isEmpty()) {
+ LOG.warn("No Subject DN Certificate Constraints were defined. This could be a security issue");
+ return true;
+ }
+ if (!patterns.isEmpty()) {
+ if (name == null || name.isEmpty()) {
+ LOG.debug("The name is null so no constraints matching was possible");
+ return false;
+ }
boolean subjectMatch = false;
- for (Pattern subjectDNPattern : subjectDNPatterns) {
- final Matcher matcher = subjectDNPattern.matcher(subjectName);
+ for (Pattern subjectDNPattern : patterns) {
+ final Matcher matcher = subjectDNPattern.matcher(name);
if (matcher.matches()) {
if (LOG.isDebugEnabled()) {
- LOG.debug("Subject DN " + subjectName + " matches with pattern " + subjectDNPattern);
+ LOG.debug("Name " + name + " matches with pattern " + subjectDNPattern);
}
subjectMatch = true;
break;
Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Merlin.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Merlin.java?rev=1765457&r1=1765456&r2=1765457&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Merlin.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/Merlin.java Tue Oct 18 15:06:04 2016
@@ -947,7 +947,16 @@ public class Merlin extends CryptoBase {
}
// Finally check Cert Constraints
- if (!matches(certs[0], subjectCertConstraints)) {
+ if (!matchesSubjectDnPattern(certs[0], subjectCertConstraints)) {
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
+ }
+ }
+
+ @Override
+ public void verifyTrust(X509Certificate[] certs, boolean enableRevocation, Collection<Pattern> subjectCertConstraints,
+ Collection<Pattern> issuerCertConstraints) throws WSSecurityException {
+ verifyTrust(certs,enableRevocation,subjectCertConstraints);
+ if (!matchesIssuerDnPattern(certs[0], issuerCertConstraints)) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
}
}
Modified: webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/MerlinAKI.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/MerlinAKI.java?rev=1765457&r1=1765456&r2=1765457&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/MerlinAKI.java (original)
+++ webservices/wss4j/trunk/ws-security-common/src/main/java/org/apache/wss4j/common/crypto/MerlinAKI.java Tue Oct 18 15:06:04 2016
@@ -227,7 +227,7 @@ public class MerlinAKI extends Merlin {
}
// Finally check Cert Constraints
- if (!matches(certs[0], subjectCertConstraints)) {
+ if (!matchesSubjectDnPattern(certs[0], subjectCertConstraints)) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
}
}
Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/RequestData.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/RequestData.java?rev=1765457&r1=1765456&r2=1765457&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/RequestData.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/RequestData.java Tue Oct 18 15:06:04 2016
@@ -73,6 +73,7 @@ public class RequestData {
private ReplayCache nonceReplayCache;
private ReplayCache samlOneTimeUseReplayCache;
private Collection<Pattern> subjectDNPatterns = new ArrayList<>();
+ private Collection<Pattern> issuerDNPatterns = new ArrayList<>();
private final List<BSPRule> ignoredBSPRules = new LinkedList<>();
private boolean appendSignatureAfterTimestamp;
private int originalSignatureActionPosition;
@@ -448,6 +449,21 @@ public class RequestData {
}
/**
+ * Get the Signature Issuer DN Cert Constraints
+ * @return
+ */
+ public Collection<Pattern> getIssuerDNPatterns() {
+ return issuerDNPatterns;
+ }
+ /**
+ * Set the Signature Issuer DN Cert Constraints
+ *
+ */
+ public void setIssuerDNPatterns(Collection<Pattern> issuerDNPatterns) {
+ this.issuerDNPatterns = issuerDNPatterns;
+ }
+
+ /**
* Set the Audience Restrictions
*/
public void setAudienceRestrictions(List<String> audienceRestrictions) {
Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/WSHandler.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/WSHandler.java?rev=1765457&r1=1765456&r2=1765457&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/WSHandler.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/handler/WSHandler.java Tue Oct 18 15:06:04 2016
@@ -1333,6 +1333,24 @@ public abstract class WSHandler {
reqData.setSubjectCertConstraints(subjectCertConstraints);
}
}
+ String issuerCertConstraintsStringValue =
+ getString(WSHandlerConstants.SIG_ISSUER_CERT_CONSTRAINTS, reqData.getMsgContext());
+ if (issuerCertConstraintsStringValue != null) {
+ String[] issuerCertConstraintsList = issuerCertConstraintsStringValue.split(",");
+ if (issuerCertConstraintsList != null) {
+ Collection<Pattern> issuerCertConstraints =
+ new ArrayList<>(issuerCertConstraintsList.length);
+ for (String certConstraint : issuerCertConstraintsList) {
+ try {
+ issuerCertConstraints.add(Pattern.compile(certConstraint.trim()));
+ } catch (PatternSyntaxException ex) {
+ LOG.debug(ex.getMessage(), ex);
+ throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, ex);
+ }
+ }
+ reqData.setIssuerDNPatterns(issuerCertConstraints);
+ }
+ }
boolean expandXOP =
decodeBooleanConfigValue(
Modified: webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/SignatureTrustValidator.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/SignatureTrustValidator.java?rev=1765457&r1=1765456&r2=1765457&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/SignatureTrustValidator.java (original)
+++ webservices/wss4j/trunk/ws-security-dom/src/main/java/org/apache/wss4j/dom/validate/SignatureTrustValidator.java Tue Oct 18 15:06:04 2016
@@ -105,7 +105,8 @@ public class SignatureTrustValidator imp
// certificate was really signed by the issuer stated in the certificate
//
Collection<Pattern> subjectCertConstraints = data.getSubjectCertConstraints();
- crypto.verifyTrust(certificates, enableRevocation, subjectCertConstraints);
+ Collection<Pattern> issuerCertConstraints = data.getIssuerDNPatterns();
+ crypto.verifyTrust(certificates, enableRevocation, subjectCertConstraints,issuerCertConstraints);
if (LOG.isDebugEnabled()) {
String subjectString = certificates[0].getSubjectX500Principal().getName();
LOG.debug(
Added: webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureIssuerCertConstraintsTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureIssuerCertConstraintsTest.java?rev=1765457&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureIssuerCertConstraintsTest.java (added)
+++ webservices/wss4j/trunk/ws-security-dom/src/test/java/org/apache/wss4j/dom/message/SignatureIssuerCertConstraintsTest.java Tue Oct 18 15:06:04 2016
@@ -0,0 +1,147 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.wss4j.dom.message;
+
+import java.util.Collections;
+import java.util.regex.Pattern;
+
+import org.apache.wss4j.common.crypto.Crypto;
+import org.apache.wss4j.common.crypto.CryptoFactory;
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.common.util.XMLUtils;
+import org.apache.wss4j.dom.WSConstants;
+import org.apache.wss4j.dom.common.SOAPUtil;
+import org.apache.wss4j.dom.common.SecurityTestUtil;
+import org.apache.wss4j.dom.engine.WSSConfig;
+import org.apache.wss4j.dom.engine.WSSecurityEngine;
+import org.apache.wss4j.dom.handler.RequestData;
+import org.apache.wss4j.dom.handler.WSHandlerResult;
+import org.apache.wss4j.dom.util.WSSecurityUtil;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+
+/**
+ * A set of test-cases for signing and verifying SOAP requests, where the issuer of the certificate used to
+ * verify the signature is validated against a set of cert constraints.
+ */
+public class SignatureIssuerCertConstraintsTest extends org.junit.Assert {
+ private static final org.slf4j.Logger LOG =
+ org.slf4j.LoggerFactory.getLogger(SignatureIssuerCertConstraintsTest.class);
+ private Crypto crypto = null;
+ private Crypto cryptoCA = null;
+
+ @org.junit.AfterClass
+ public static void cleanup() throws Exception {
+ SecurityTestUtil.cleanup();
+ }
+
+ public SignatureIssuerCertConstraintsTest() throws Exception {
+ WSSConfig.init();
+ crypto = CryptoFactory.getInstance("wss40.properties");
+ cryptoCA = CryptoFactory.getInstance("wss40CA.properties");
+ }
+
+ /**
+ * The test uses the BinarySecurityToken key identifier type.
+ */
+ @Test
+ public void testBSTSignature() throws Exception {
+ WSSecSignature builder = new WSSecSignature();
+ builder.setUserInfo("wss40", "security");
+ builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+
+ Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+ WSSecHeader secHeader = new WSSecHeader(doc);
+ secHeader.insertSecurityHeader();
+ Document signedDoc = builder.build(doc, crypto, secHeader);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Signed message with BST key identifier:");
+ String outputString =
+ XMLUtils.prettyDocumentToString(signedDoc);
+ LOG.debug(outputString);
+ }
+
+ Element securityHeader = WSSecurityUtil.getSecurityHeader(signedDoc, null);
+ String certConstraint = ".*CN=Werner.*OU=Apache.*";
+ verify(securityHeader, cryptoCA, certConstraint);
+
+ certConstraint = ".*CN=Werner2.*O=Apache.*";
+ try {
+ verify(securityHeader, cryptoCA, certConstraint);
+ fail("Failure expected on a bad cert constraint");
+ } catch (WSSecurityException ex) {
+ assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
+ }
+ }
+
+ /**
+ * The test uses the BinarySecurityToken key identifier type.
+ */
+ @Test
+ public void testBSTSignaturePKIPath() throws Exception {
+ WSSecSignature builder = new WSSecSignature();
+ builder.setUserInfo("wss40", "security");
+ builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+ builder.setUseSingleCertificate(false);
+
+ Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
+ WSSecHeader secHeader = new WSSecHeader(doc);
+ secHeader.insertSecurityHeader();
+ Document signedDoc = builder.build(doc, crypto, secHeader);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Signed message with BST key identifier:");
+ String outputString =
+ XMLUtils.prettyDocumentToString(signedDoc);
+ LOG.debug(outputString);
+ }
+
+ Element securityHeader = WSSecurityUtil.getSecurityHeader(signedDoc, null);
+ String certConstraint = ".*CN=Werner.*OU=Apache.*";
+ verify(securityHeader, cryptoCA, certConstraint);
+
+ certConstraint = ".*CN=Werner2.*O=Apache.*";
+ try {
+ verify(securityHeader, cryptoCA, certConstraint);
+ fail("Failure expected on a bad cert constraint");
+ } catch (WSSecurityException ex) {
+ assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
+ }
+ }
+
+ private WSHandlerResult verify(
+ Element securityHeader, Crypto sigCrypto, String certConstraint
+ ) throws Exception {
+ WSSecurityEngine secEngine = new WSSecurityEngine();
+ RequestData data = new RequestData();
+ data.setSigVerCrypto(sigCrypto);
+
+ if (certConstraint != null) {
+ Pattern issuerDNPattern = Pattern.compile(certConstraint.trim());
+ data.setIssuerDNPatterns(Collections.singletonList(issuerDNPattern));
+ }
+
+ return secEngine.processSecurityHeader(securityHeader, data);
+ }
+
+}
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java?rev=1765457&r1=1765456&r2=1765457&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/ext/WSSSecurityProperties.java Tue Oct 18 15:06:04 2016
@@ -110,6 +110,7 @@ public class WSSSecurityProperties exten
private ReplayCache samlOneTimeUseReplayCache;
private boolean validateSamlSubjectConfirmation = true;
private Collection<Pattern> subjectDNPatterns = new ArrayList<>();
+ private Collection<Pattern> issuerDNPatterns = new ArrayList<>();
private List<String> audienceRestrictions = new ArrayList<>();
private boolean requireTimestampExpires;
@@ -169,6 +170,7 @@ public class WSSSecurityProperties exten
this.validateSamlSubjectConfirmation = wssSecurityProperties.validateSamlSubjectConfirmation;
this.encryptSymmetricEncrytionKey = wssSecurityProperties.encryptSymmetricEncrytionKey;
this.subjectDNPatterns = wssSecurityProperties.subjectDNPatterns;
+ this.issuerDNPatterns = wssSecurityProperties.issuerDNPatterns;
this.attachmentCallbackHandler = wssSecurityProperties.attachmentCallbackHandler;
this.msgContext = wssSecurityProperties.msgContext;
this.audienceRestrictions = wssSecurityProperties.audienceRestrictions;
@@ -869,6 +871,20 @@ public class WSSSecurityProperties exten
public Collection<Pattern> getSubjectCertConstraints() {
return subjectDNPatterns;
}
+ /**
+ * Set the Signature Issuer Cert Constraints
+ */
+ public void setIssuerDNConstraints(Collection<Pattern> issuerDNPatterns) {
+ this.issuerDNPatterns = issuerDNPatterns;
+ }
+ /**
+ * Get the Signature Issuer Cert Constraints
+ */
+ public Collection<Pattern> getIssuerDNConstraints() {
+ return issuerDNPatterns;
+ }
+
+
/**
* Set the Audience Restrictions
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/SamlSecurityTokenImpl.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/SamlSecurityTokenImpl.java?rev=1765457&r1=1765456&r2=1765457&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/SamlSecurityTokenImpl.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/SamlSecurityTokenImpl.java Tue Oct 18 15:06:04 2016
@@ -206,11 +206,14 @@ public class SamlSecurityTokenImpl exten
if (x509Certificates != null && x509Certificates.length > 0) {
boolean enableRevocation = false;
Collection<Pattern> subjectCertConstraints = null;
+ Collection<Pattern> issuerCertConstraints = null;
if (securityProperties != null) {
enableRevocation = securityProperties.isEnableRevocation();
subjectCertConstraints = securityProperties.getSubjectCertConstraints();
+ issuerCertConstraints = securityProperties.getIssuerDNConstraints();
+
}
- crypto.verifyTrust(x509Certificates, enableRevocation, subjectCertConstraints);
+ crypto.verifyTrust(x509Certificates, enableRevocation, subjectCertConstraints,issuerCertConstraints);
}
PublicKey publicKey = getPublicKey();
if (publicKey != null) {
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/X509SecurityTokenImpl.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/X509SecurityTokenImpl.java?rev=1765457&r1=1765456&r2=1765457&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/X509SecurityTokenImpl.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/impl/securityToken/X509SecurityTokenImpl.java Tue Oct 18 15:06:04 2016
@@ -113,11 +113,13 @@ public abstract class X509SecurityTokenI
if (x509Certificates != null && x509Certificates.length > 0) {
boolean enableRevocation = false;
Collection<Pattern> subjectCertConstraints = null;
+ Collection<Pattern> issuerCertConstraints = null;
if (securityProperties != null) {
enableRevocation = securityProperties.isEnableRevocation();
subjectCertConstraints = securityProperties.getSubjectCertConstraints();
+ issuerCertConstraints = securityProperties.getIssuerDNConstraints();
}
- getCrypto().verifyTrust(x509Certificates, enableRevocation, subjectCertConstraints);
+ getCrypto().verifyTrust(x509Certificates, enableRevocation, subjectCertConstraints,issuerCertConstraints);
}
}
Modified: webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/setup/ConfigurationConverter.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/setup/ConfigurationConverter.java?rev=1765457&r1=1765456&r2=1765457&view=diff
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/setup/ConfigurationConverter.java (original)
+++ webservices/wss4j/trunk/ws-security-stax/src/main/java/org/apache/wss4j/stax/setup/ConfigurationConverter.java Tue Oct 18 15:06:04 2016
@@ -549,6 +549,24 @@ public final class ConfigurationConverte
properties.setSubjectCertConstraints(subjectCertConstraints);
}
}
+ // Subject Cert Constraints
+ String issuerCertConstraintsString =
+ getString(ConfigurationConstants.SIG_ISSUER_CERT_CONSTRAINTS, config);
+ if (issuerCertConstraintsString != null) {
+ String[] certConstraintsList = issuerCertConstraintsString.split(",");
+ if (certConstraintsList != null) {
+ Collection<Pattern> issuerCertConstraints =
+ new ArrayList<>(certConstraintsList.length);
+ for (String certConstraint : certConstraintsList) {
+ try {
+ issuerCertConstraints.add(Pattern.compile(certConstraint.trim()));
+ } catch (PatternSyntaxException ex) {
+ LOG.error(ex.getMessage(), ex);
+ }
+ }
+ properties.setSubjectCertConstraints(issuerCertConstraints);
+ }
+ }
properties.setUtTTL(decodeTimeToLive(config, false));
properties.setUtFutureTTL(decodeFutureTimeToLive(config, false));
Added: webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureIssuerCertConstaintsTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureIssuerCertConstaintsTest.java?rev=1765457&view=auto
==============================================================================
--- webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureIssuerCertConstaintsTest.java (added)
+++ webservices/wss4j/trunk/ws-security-stax/src/test/java/org/apache/wss4j/stax/test/SignatureIssuerCertConstaintsTest.java Tue Oct 18 15:06:04 2016
@@ -0,0 +1,202 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.wss4j.stax.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Pattern;
+
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.wss4j.common.ext.WSSecurityException;
+import org.apache.wss4j.dom.handler.RequestData;
+import org.apache.wss4j.dom.handler.WSHandlerConstants;
+import org.apache.wss4j.stax.ext.WSSConstants;
+import org.apache.wss4j.stax.ext.WSSSecurityProperties;
+import org.apache.wss4j.stax.setup.InboundWSSec;
+import org.apache.wss4j.stax.setup.WSSec;
+import org.apache.wss4j.stax.test.utils.StAX2DOM;
+import org.junit.Assert;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+
+/**
+ * A set of test-cases for signing and verifying SOAP requests, where the certificate used to
+ * verify the signature is validated against a set of cert constraints.
+ */
+public class SignatureIssuerCertConstaintsTest extends AbstractTestBase {
+
+ @Test
+ public void testBSTSignature() throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ {
+ InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
+ String action = WSHandlerConstants.SIGNATURE;
+ Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, new Properties());
+
+ //some test that we can really sure we get what we want from WSS4J
+ NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
+ Assert.assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
+
+ javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
+ transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
+ }
+
+ //done signature; now test sig-verification: This should pass with a correct cert constraint check
+ {
+ WSSSecurityProperties securityProperties = new WSSSecurityProperties();
+ securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("wss40CA.jks"), "security".toCharArray());
+ String certConstraint = ".*CN=Werner.*OU=Apache.*";
+ Pattern issuerDNPattern = Pattern.compile(certConstraint.trim());
+ securityProperties.setIssuerDNConstraints(Collections.singletonList(issuerDNPattern));
+
+ InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
+ XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
+
+ Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
+
+ //header element must still be there
+ NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
+ Assert.assertEquals(nodeList.getLength(), 1);
+ Assert.assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
+ }
+
+ //done signature; now test sig-verification: This should fail with an incorrect cert constraint check
+ {
+ WSSSecurityProperties securityProperties = new WSSSecurityProperties();
+ securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("wss40CA.jks"), "security".toCharArray());
+ String certConstraint = ".*CN=Werner2.*OU=Apache.*";
+ Pattern issuerDNPattern = Pattern.compile(certConstraint.trim());
+ securityProperties.setIssuerDNConstraints(Collections.singletonList(issuerDNPattern));
+
+ InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
+ XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
+
+ try {
+ StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
+ Assert.fail("Expected failure on a incorrect cert constraint check");
+ } catch (Exception ex) {
+ String errorMessage = "The security token could not be authenticated or authorized";
+ Assert.assertTrue(ex.getMessage().contains(errorMessage));
+ }
+ }
+ }
+
+ @Test
+ public void testBSTSignaturePKIPath() throws Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ {
+ InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
+ String action = WSHandlerConstants.SIGNATURE;
+ Properties properties = new Properties();
+ properties.put(WSHandlerConstants.USE_SINGLE_CERTIFICATE, "false");
+ Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
+
+ //some test that we can really sure we get what we want from WSS4J
+ NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
+ Assert.assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
+
+ javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
+ transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
+ }
+
+ //done signature; now test sig-verification: This should pass with a correct cert constraint check
+ {
+ WSSSecurityProperties securityProperties = new WSSSecurityProperties();
+ securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("wss40CA.jks"), "security".toCharArray());
+ String certConstraint = ".*CN=Werner.*OU=Apache.*";
+ Pattern issuerDNPattern = Pattern.compile(certConstraint.trim());
+ securityProperties.setIssuerDNConstraints(Collections.singletonList(issuerDNPattern));
+
+ InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
+ XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
+
+ Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
+
+ //header element must still be there
+ NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
+ Assert.assertEquals(nodeList.getLength(), 1);
+ Assert.assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
+ }
+
+ //done signature; now test sig-verification: This should fail with an incorrect cert constraint check
+ {
+ WSSSecurityProperties securityProperties = new WSSSecurityProperties();
+ securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("wss40CA.jks"), "security".toCharArray());
+ String certConstraint = ".*CN=Werner2.*OU=Apache.*";
+ Pattern issuerDNPattern = Pattern.compile(certConstraint.trim());
+ securityProperties.setIssuerDNConstraints(Collections.singletonList(issuerDNPattern));
+
+ InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
+ XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
+
+ try {
+ StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
+ Assert.fail("Expected failure on a incorrect cert constraint check");
+ } catch (Exception ex) {
+ String errorMessage = "The security token could not be authenticated or authorized";
+ Assert.assertTrue(ex.getMessage().contains(errorMessage));
+ }
+ }
+ }
+
+ @Override
+ protected Map<String, Object> doOutboundSecurityWithWSS4J_1(
+ InputStream sourceDocument, String action, final Properties properties
+ ) throws WSSecurityException, TransformerException, IOException {
+ CustomWSS4JHandler wss4JHandler = new CustomWSS4JHandler();
+ final Map<String, Object> messageContext = getMessageContext(sourceDocument);
+ messageContext.put(WSHandlerConstants.ACTION, action);
+ messageContext.put(WSHandlerConstants.USER, "wss40");
+ messageContext.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
+
+ Properties sigProperties = new Properties();
+ sigProperties.setProperty("org.apache.wss4j.crypto.provider", "org.apache.wss4j.common.crypto.Merlin");
+ sigProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.file", "wss40.jks");
+ sigProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.password", "security");
+ sigProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.alias", "wss40");
+ wss4JHandler.setPassword(messageContext, "security");
+ messageContext.put(WSHandlerConstants.SIG_PROP_REF_ID, "" + sigProperties.hashCode());
+ messageContext.put("" + sigProperties.hashCode(), sigProperties);
+
+ Enumeration<?> enumeration = properties.propertyNames();
+ while (enumeration.hasMoreElements()) {
+ String s = (String) enumeration.nextElement();
+ messageContext.put(s, properties.get(s));
+ }
+
+ RequestData requestData = new RequestData();
+ requestData.setMsgContext(messageContext);
+
+ wss4JHandler.doSender(messageContext, requestData, true);
+
+ return messageContext;
+ }
+
+}