You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ws.apache.org by co...@apache.org on 2010/11/10 17:35:52 UTC
svn commit: r1033575 - in /webservices/wss4j/trunk: keys/
src/org/apache/ws/security/action/ src/org/apache/ws/security/handler/
src/org/apache/ws/security/processor/ test/ test/wssec/
Author: coheigea
Date: Wed Nov 10 16:35:51 2010
New Revision: 1033575
URL: http://svn.apache.org/viewvc?rev=1033575&view=rev
Log:
[WSS-40] - Committed a fix for trunk.
Added:
webservices/wss4j/trunk/keys/client_keystore.jks (with props)
webservices/wss4j/trunk/keys/server_keystore.jks (with props)
webservices/wss4j/trunk/test/wss40_client.properties
webservices/wss4j/trunk/test/wss40_server.properties
Modified:
webservices/wss4j/trunk/src/org/apache/ws/security/action/SignatureAction.java
webservices/wss4j/trunk/src/org/apache/ws/security/handler/RequestData.java
webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java
webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java
webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java
webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS40.java
Added: webservices/wss4j/trunk/keys/client_keystore.jks
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/keys/client_keystore.jks?rev=1033575&view=auto
==============================================================================
Binary file - no diff available.
Propchange: webservices/wss4j/trunk/keys/client_keystore.jks
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: webservices/wss4j/trunk/keys/server_keystore.jks
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/keys/server_keystore.jks?rev=1033575&view=auto
==============================================================================
Binary file - no diff available.
Propchange: webservices/wss4j/trunk/keys/server_keystore.jks
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/action/SignatureAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/action/SignatureAction.java?rev=1033575&r1=1033574&r2=1033575&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/action/SignatureAction.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/action/SignatureAction.java Wed Nov 10 16:35:51 2010
@@ -51,6 +51,7 @@ public class SignatureAction implements
}
wsSign.setUserInfo(reqData.getSignatureUser(), pwcb.getPassword());
+ wsSign.setUseSingleCertificate(reqData.isUseSingleCert());
if (reqData.getSignatureParts().size() > 0) {
wsSign.setParts(reqData.getSignatureParts());
}
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/handler/RequestData.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/handler/RequestData.java?rev=1033575&r1=1033574&r2=1033575&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/handler/RequestData.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/handler/RequestData.java Wed Nov 10 16:35:51 2010
@@ -66,6 +66,7 @@ public class RequestData {
private boolean useDerivedKey = true;
private int derivedKeyIterations = UsernameToken.DEFAULT_ITERATION;
private boolean useDerivedKeyForMAC = true;
+ private boolean useSingleCert = true;
public void clear() {
soapConstants = null;
@@ -84,6 +85,7 @@ public class RequestData {
useDerivedKey = true;
derivedKeyIterations = UsernameToken.DEFAULT_ITERATION;
useDerivedKeyForMAC = true;
+ useSingleCert = true;
}
public Object getMsgContext() {
@@ -353,4 +355,22 @@ public class RequestData {
return useDerivedKeyForMAC;
}
+ /**
+ * Whether to use a single certificate or a whole certificate chain when
+ * constructing a BinarySecurityToken used for direct reference in Signature.
+ * @param useSingleCert true if only to use a single certificate
+ */
+ public void setUseSingleCert(boolean useSingleCert) {
+ this.useSingleCert = useSingleCert;
+ }
+
+ /**
+ * Whether to use a single certificate or a whole certificate chain when
+ * constructing a BinarySecurityToken used for direct reference in Signature.
+ * @return whether to use a single certificate
+ */
+ public boolean isUseSingleCert() {
+ return useSingleCert;
+ }
+
}
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java?rev=1033575&r1=1033574&r2=1033575&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java Wed Nov 10 16:35:51 2010
@@ -597,6 +597,9 @@ public abstract class WSHandler {
int iSecretKeyLength = Integer.parseInt(secretKeyLength);
reqData.setSecretKeyLength(iSecretKeyLength);
}
+
+ boolean useSingleCert = decodeUseSingleCertificate(reqData);
+ reqData.setUseSingleCert(useSingleCert);
}
protected void decodeEncryptionParameter(RequestData reqData)
@@ -826,6 +829,26 @@ public abstract class WSHandler {
"WSHandler: illegal timestampStrict parameter"
);
}
+
+ protected boolean decodeUseSingleCertificate(RequestData reqData)
+ throws WSSecurityException {
+ String useSingleCert =
+ getString(WSHandlerConstants.USE_SINGLE_CERTIFICATE, reqData.getMsgContext());
+
+ if (useSingleCert == null) {
+ return true;
+ }
+ if ("0".equals(useSingleCert) || "false".equals(useSingleCert)) {
+ return false;
+ }
+ if ("1".equals(useSingleCert) || "true".equals(useSingleCert)) {
+ return true;
+ }
+
+ throw new WSSecurityException(
+ "WSHandler: illegal useSingleCert parameter"
+ );
+ }
/**
* Get a password to construct a UsernameToken or sign a message.
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java?rev=1033575&r1=1033574&r2=1033575&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java Wed Nov 10 16:35:51 2010
@@ -596,6 +596,13 @@ public class WSHandlerConstants {
public static final String SIGNATURE_PARTS = "signatureParts";
/**
+ * This parameter sets whether to use a single certificate or a whole certificate
+ * chain when constructing a BinarySecurityToken used for direct reference in
+ * signature. The default is true, meaning that only a single certificate is used.
+ */
+ public static final String USE_SINGLE_CERTIFICATE = "useSingleCertificate";
+
+ /**
* This parameter sets the length of the secret (derived) key to use for the
* WSE UT_SIGN functionality.
*
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java?rev=1033575&r1=1033574&r2=1033575&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/processor/SignatureProcessor.java Wed Nov 10 16:35:51 2010
@@ -194,6 +194,7 @@ public class SignatureProcessor implemen
PublicKey publicKey = null;
Principal principal = null;
KeyValue keyValue = null;
+ boolean validateCertificateChain = false;
Element keyInfoElement =
WSSecurityUtil.getDirectChildElement(
@@ -256,7 +257,9 @@ public class SignatureProcessor implemen
QName el = new QName(token.getNamespaceURI(), token.getLocalName());
if (el.equals(WSSecurityEngine.BINARY_TOKEN)) {
certs = getCertificatesTokenReference(token, crypto);
- principal = validateCertificates(certs, crypto);
+ if (certs != null && certs.length > 1) {
+ validateCertificateChain = true;
+ }
} else if (el.equals(WSSecurityEngine.SAML_TOKEN)) {
if (crypto == null) {
throw new WSSecurityException(
@@ -265,7 +268,6 @@ public class SignatureProcessor implemen
}
SAMLKeyInfo samlKi = SAMLUtil.getSAMLKeyInfo(token, crypto, cb);
certs = samlKi.getCerts();
- validateCertificates(certs, crypto);
secretKey = samlKi.getSecret();
principal = createPrincipalFromSAMLKeyInfo(samlKi);
} else if (el.equals(WSSecurityEngine.ENCRYPTED_KEY)){
@@ -295,7 +297,9 @@ public class SignatureProcessor implemen
principal = ut.createPrincipal();
} else if (processor instanceof BinarySecurityTokenProcessor) {
certs = ((BinarySecurityTokenProcessor)processor).getCertificates();
- principal = validateCertificates(certs, crypto);
+ if (certs != null && certs.length > 1) {
+ validateCertificateChain = true;
+ }
} else if (processor instanceof EncryptedKeyProcessor) {
EncryptedKeyProcessor encryptedKeyProcessor =
(EncryptedKeyProcessor)processor;
@@ -327,14 +331,12 @@ public class SignatureProcessor implemen
SAMLKeyInfo samlKi =
SAMLUtil.getSAMLKeyInfo(samlp.getSamlTokenElement(), crypto, cb);
certs = samlKi.getCerts();
- validateCertificates(certs, crypto);
secretKey = samlKi.getSecret();
publicKey = samlKi.getPublicKey();
principal = createPrincipalFromSAMLKeyInfo(samlKi);
}
} else if (secRef.containsX509Data() || secRef.containsX509IssuerSerial()) {
certs = secRef.getX509IssuerSerial(crypto);
- principal = validateCertificates(certs, crypto);
} else if (secRef.containsKeyIdentifier()) {
if (secRef.getKeyIdentifierValueType().equals(SecurityTokenReference.ENC_KEY_SHA1_URI)) {
String id = secRef.getKeyIdentifierValue();
@@ -351,13 +353,11 @@ public class SignatureProcessor implemen
}
SAMLKeyInfo samlKi = SAMLUtil.getSAMLKeyInfo(token, crypto, cb);
certs = samlKi.getCerts();
- validateCertificates(certs, crypto);
secretKey = samlKi.getSecret();
publicKey = samlKi.getPublicKey();
principal = createPrincipalFromSAMLKeyInfo(samlKi);
} else {
certs = secRef.getKeyIdentifier(crypto);
- principal = validateCertificates(certs, crypto);
}
} else {
throw new WSSecurityException(
@@ -379,6 +379,25 @@ public class SignatureProcessor implemen
&& publicKey == null) {
throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
}
+
+ //
+ // Validate certificates and verify trust
+ //
+ validateCertificates(certs);
+ if (certs != null) {
+ if (principal == null) {
+ principal = certs[0].getSubjectX500Principal();
+ }
+ boolean trust = false;
+ if (!validateCertificateChain || certs.length == 1) {
+ trust = verifyTrust(certs[0], crypto);
+ } else if (validateCertificateChain && certs.length > 1) {
+ trust = verifyTrust(certs, crypto);
+ }
+ if (!trust) {
+ throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
+ }
+ }
//
// Perform the signature verification and build up a List of elements that the
@@ -442,15 +461,12 @@ public class SignatureProcessor implemen
/**
- * Validate an array of certificates by checking the validity of each cert, and verifying trust
+ * Validate an array of certificates by checking the validity of each cert
* @param certsToValidate The array of certificates to validate
- * @param crypto The crypto object representing the keystore
- * @return A principal representing the first element in the array (if it exists)
* @throws WSSecurityException
*/
- public static Principal validateCertificates(
- X509Certificate[] certsToValidate,
- Crypto crypto
+ public static void validateCertificates(
+ X509Certificate[] certsToValidate
) throws WSSecurityException {
if (certsToValidate != null && certsToValidate.length > 0) {
try {
@@ -466,12 +482,7 @@ public class SignatureProcessor implemen
WSSecurityException.FAILED_CHECK, "invalidCert", null, e
);
}
- if (!verifyTrust(certsToValidate[0], crypto)) {
- throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
- }
- return certsToValidate[0].getSubjectX500Principal();
}
- return null;
}
@@ -570,7 +581,7 @@ public class SignatureProcessor implemen
x509certs[j + 1] = certs[j];
}
- ///
+ //
// Use the validation method from the crypto to check whether the subjects'
// certificate was really signed by the issuer stated in the certificate
//
@@ -594,6 +605,43 @@ public class SignatureProcessor implemen
return false;
}
+
+ /**
+ * Evaluate whether the given certificate chain should be trusted.
+ *
+ * @param certificates the certificate chain that should be validated against the keystore
+ * @return true if the certificate chain is trusted, false if not
+ * @throws WSSecurityException
+ */
+ public static boolean verifyTrust(X509Certificate[] certificates, Crypto crypto)
+ throws WSSecurityException {
+ String subjectString = certificates[0].getSubjectX500Principal().getName();
+ //
+ // Use the validation method from the crypto to check whether the subjects'
+ // certificate was really signed by the issuer stated in the certificate
+ //
+ if (certificates != null && certificates.length > 1
+ && crypto.validateCertPath(certificates)) {
+ if (log.isDebugEnabled()) {
+ log.debug(
+ "Certificate path has been verified for certificate with subject "
+ + subjectString
+ );
+ }
+ return true;
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug(
+ "Certificate path could not be verified for certificate with subject "
+ + subjectString
+ );
+ }
+
+ return false;
+ }
+
+
/**
* Get the default principal from the KeyStore
Added: webservices/wss4j/trunk/test/wss40_client.properties
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/wss40_client.properties?rev=1033575&view=auto
==============================================================================
--- webservices/wss4j/trunk/test/wss40_client.properties (added)
+++ webservices/wss4j/trunk/test/wss40_client.properties Wed Nov 10 16:35:51 2010
@@ -0,0 +1,5 @@
+org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
+org.apache.ws.security.crypto.merlin.keystore.type=jks
+org.apache.ws.security.crypto.merlin.keystore.password=password
+org.apache.ws.security.crypto.merlin.keystore.alias=Client_CertChain
+org.apache.ws.security.crypto.merlin.keystore.file=keys/client_keystore.jks
Added: webservices/wss4j/trunk/test/wss40_server.properties
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/wss40_server.properties?rev=1033575&view=auto
==============================================================================
--- webservices/wss4j/trunk/test/wss40_server.properties (added)
+++ webservices/wss4j/trunk/test/wss40_server.properties Wed Nov 10 16:35:51 2010
@@ -0,0 +1,5 @@
+org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
+org.apache.ws.security.crypto.merlin.keystore.type=jks
+org.apache.ws.security.crypto.merlin.keystore.password=password
+org.apache.ws.security.crypto.merlin.keystore.alias=CA_Cert
+org.apache.ws.security.crypto.merlin.keystore.file=keys/server_keystore.jks
Modified: webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS40.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS40.java?rev=1033575&r1=1033574&r2=1033575&view=diff
==============================================================================
--- webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS40.java (original)
+++ webservices/wss4j/trunk/test/wssec/TestWSSecurityWSS40.java Wed Nov 10 16:35:51 2010
@@ -25,12 +25,15 @@ import junit.framework.TestSuite;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.WSSecurityEngine;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.message.WSSecSignature;
import org.apache.ws.security.message.WSSecHeader;
import org.apache.ws.security.util.WSSecurityUtil;
@@ -108,7 +111,6 @@ public class TestWSSecurityWSS40 extends
return new TestSuite(TestWSSecurityWSS40.class);
}
-
/**
* Test signing a SOAP message using a BST.
*/
@@ -139,6 +141,40 @@ public class TestWSSecurityWSS40 extends
assertTrue (cert != null);
}
+ public void testBSTCertChain() throws Exception {
+ Crypto clientCrypto = CryptoFactory.getInstance("wss40_client.properties");
+ WSSecSignature sign = new WSSecSignature();
+ sign.setUserInfo("Client_CertChain", "password");
+ sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+ sign.setUseSingleCertificate(false);
+
+ Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
+
+ WSSecHeader secHeader = new WSSecHeader();
+ secHeader.insertSecurityHeader(doc);
+ Document signedDoc = sign.build(doc, clientCrypto, secHeader);
+
+ if (LOG.isDebugEnabled()) {
+ String outputString =
+ org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
+ LOG.debug("BST CA Cert");
+ LOG.debug(outputString);
+ }
+ //
+ // Verify the signature
+ //
+ Crypto serverCrypto = CryptoFactory.getInstance("wss40_server.properties");
+ List results = verify(signedDoc, serverCrypto);
+ WSSecurityEngineResult result =
+ WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
+ X509Certificate cert =
+ (X509Certificate)result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
+ assertTrue (cert != null);
+ X509Certificate[] certs =
+ (X509Certificate[])result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES);
+ assertTrue (certs != null && certs.length == 2);
+ }
+
/**
* Test signing a SOAP message using a BST, sending the CA cert as well in the
* message.
@@ -170,6 +206,9 @@ public class TestWSSecurityWSS40 extends
X509Certificate cert =
(X509Certificate)result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
assertTrue (cert != null);
+ X509Certificate[] certs =
+ (X509Certificate[])result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES);
+ assertTrue (certs != null && certs.length == 2);
}
@@ -237,6 +276,48 @@ public class TestWSSecurityWSS40 extends
}
}
+ /**
+ * A test for "SignatureAction does not set DigestAlgorithm on WSSecSignature instance"
+ */
+ public void testMultipleCertsWSHandler() throws Exception {
+ final WSSConfig cfg = WSSConfig.getNewInstance();
+ final int action = WSConstants.SIGN;
+ final RequestData reqData = new RequestData();
+ reqData.setWssConfig(cfg);
+ reqData.setUsername("wss40");
+ java.util.Map config = new java.util.TreeMap();
+ config.put(WSHandlerConstants.SIG_PROP_FILE, "wss40.properties");
+ config.put("password", "security");
+ config.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
+ config.put(WSHandlerConstants.USE_SINGLE_CERTIFICATE, "false");
+ reqData.setMsgContext(config);
+
+ final java.util.Vector actions = new java.util.Vector();
+ actions.add(new Integer(action));
+ final Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
+ MyHandler handler = new MyHandler();
+ handler.send(
+ action,
+ doc,
+ reqData,
+ actions,
+ true
+ );
+
+ //
+ // Verify the signature
+ //
+ List results = verify(doc, cryptoCA);
+ WSSecurityEngineResult result =
+ WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
+ X509Certificate cert =
+ (X509Certificate)result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
+ assertTrue (cert != null);
+ X509Certificate[] certs =
+ (X509Certificate[])result.get(WSSecurityEngineResult.TAG_X509_CERTIFICATES);
+ assertTrue (certs != null && certs.length == 2);
+ }
+
/**
* Verifies the soap envelope
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ws.apache.org
For additional commands, e-mail: dev-help@ws.apache.org