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 2011/01/24 14:15:51 UTC
svn commit: r1062763 - in /webservices/wss4j/trunk/src:
main/java/org/apache/ws/security/
main/java/org/apache/ws/security/components/crypto/
main/java/org/apache/ws/security/processor/
main/java/org/apache/ws/security/saml/ext/ main/java/org/apache/ws...
Author: coheigea
Date: Mon Jan 24 13:15:50 2011
New Revision: 1062763
URL: http://svn.apache.org/viewvc?rev=1062763&view=rev
Log:
[WSS-266] - A first cut at this issue
- Added a set of Validators for signature trust verification, username token authentication, and Timestamp validation
- Removed PublicKeyCallback - this is now done as part of Crypto
Added:
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/Credential.java
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/SignatureTrustValidator.java
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/TimestampValidator.java
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/UsernameTokenValidator.java
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/Validator.java
Removed:
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/PublicKeyCallback.java
webservices/wss4j/trunk/src/test/java/org/apache/ws/security/common/PublicKeyCallbackHandler.java
Modified:
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/components/crypto/Crypto.java
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/components/crypto/CryptoBase.java
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SAMLTokenProcessor.java
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SignatureProcessor.java
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/TimestampProcessor.java
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/UsernameTokenProcessor.java
webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java
webservices/wss4j/trunk/src/test/java/org/apache/ws/security/common/KeystoreCallbackHandler.java
webservices/wss4j/trunk/src/test/java/org/apache/ws/security/message/SignatureKeyValueTest.java
webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenHOKTest.java
webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SignedSamlTokenHOKTest.java
Modified: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/components/crypto/Crypto.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/components/crypto/Crypto.java?rev=1062763&r1=1062762&r2=1062763&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/components/crypto/Crypto.java (original)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/components/crypto/Crypto.java Mon Jan 24 13:15:50 2011
@@ -24,6 +24,7 @@ import java.io.InputStream;
import java.math.BigInteger;
import java.security.KeyStore;
import java.security.PrivateKey;
+import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
@@ -268,6 +269,15 @@ public interface Crypto {
* @throws WSSecurityException
*/
public boolean validateCertPath(X509Certificate[] certs) throws WSSecurityException;
+
+ /**
+ * Evaluate whether a given public key should be trusted.
+ * Essentially, this amounts to checking to see if there is a certificate in the keystore
+ * or truststore, whose public key matches the transmitted public key.
+ * @param publicKey The PublicKey to be evaluated
+ * @return whether the PublicKey parameter is trusted or not
+ */
+ public boolean verifyTrust(PublicKey publicKey) throws WSSecurityException;
/**
* Lookup X509 Certificates in the keystore according to a given DN of the subject of the certificate
Modified: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/components/crypto/CryptoBase.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/components/crypto/CryptoBase.java?rev=1062763&r1=1062762&r2=1062763&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/components/crypto/CryptoBase.java (original)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/components/crypto/CryptoBase.java Mon Jan 24 13:15:50 2011
@@ -995,6 +995,71 @@ public abstract class CryptoBase impleme
}
/**
+ * Evaluate whether a given public key should be trusted.
+ * Essentially, this amounts to checking to see if there is a certificate in the keystore
+ * or truststore, whose public key matches the transmitted public key.
+ * @param publicKey The PublicKey to be evaluated
+ * @return whether the PublicKey parameter is trusted or not
+ */
+ public boolean verifyTrust(PublicKey publicKey) throws WSSecurityException {
+ //
+ // If the public key is null, do not trust the signature
+ //
+ if (publicKey == null) {
+ return false;
+ }
+
+ //
+ // Search the keystore for the transmitted public key (direct trust)
+ //
+ boolean trust = findPublicKeyInKeyStore(publicKey, keystore);
+ if (trust) {
+ return true;
+ } else {
+ //
+ // Now search the truststore for the transmitted public key (direct trust)
+ //
+ trust = findPublicKeyInKeyStore(publicKey, truststore);
+ if (trust) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Find the Public Key in a keystore.
+ */
+ private boolean findPublicKeyInKeyStore(PublicKey publicKey, KeyStore keyStoreToSearch) {
+ try {
+ for (Enumeration<String> e = keyStoreToSearch.aliases(); e.hasMoreElements();) {
+ String alias = e.nextElement();
+ Certificate[] certs = keyStoreToSearch.getCertificateChain(alias);
+ Certificate cert;
+ if (certs == null || certs.length == 0) {
+ // no cert chain, so lets check if getCertificate gives us a result.
+ cert = keyStoreToSearch.getCertificate(alias);
+ if (cert == null) {
+ continue;
+ }
+ } else {
+ cert = certs[0];
+ }
+ if (!(cert instanceof X509Certificate)) {
+ continue;
+ }
+ X509Certificate x509cert = (X509Certificate) cert;
+ if (publicKey.equals(x509cert.getPublicKey())) {
+ return true;
+ }
+ }
+ } catch (KeyStoreException e) {
+ return false;
+ }
+ return false;
+ }
+
+ /**
* Get all of the aliases of the X500Principal argument in the supplied KeyStore
* @param subjectRDN either an X500Principal or a BouncyCastle X509Name instance.
* @param store The KeyStore
Modified: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SAMLTokenProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SAMLTokenProcessor.java?rev=1062763&r1=1062762&r2=1062763&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SAMLTokenProcessor.java (original)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SAMLTokenProcessor.java Mon Jan 24 13:15:50 2011
@@ -27,8 +27,12 @@ import org.apache.ws.security.WSSConfig;
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.saml.SAMLKeyInfo;
import org.apache.ws.security.saml.ext.AssertionWrapper;
import org.apache.ws.security.util.DOM2Writer;
+import org.apache.ws.security.validate.Credential;
+import org.apache.ws.security.validate.SignatureTrustValidator;
+import org.apache.ws.security.validate.Validator;
import org.w3c.dom.Element;
@@ -38,6 +42,8 @@ import javax.security.auth.callback.Call
public class SAMLTokenProcessor implements Processor {
private static Log log = LogFactory.getLog(SAMLTokenProcessor.class.getName());
+ private Validator validator = new SignatureTrustValidator();
+
public List<WSSecurityEngineResult> handleToken(
Element elem,
Crypto crypto,
@@ -69,12 +75,20 @@ public class SAMLTokenProcessor implemen
) throws WSSecurityException {
AssertionWrapper assertion = new AssertionWrapper(token);
if (assertion.isSigned()) {
- assertion.verify(crypto);
+ SAMLKeyInfo samlKeyInfo = assertion.verify(crypto);
+
+ // Now verify trust on the signature credential
+ validator.setCrypto(crypto);
+ Credential credential = new Credential();
+ credential.setPublicKey(samlKeyInfo.getPublicKey());
+ credential.setCertificates(samlKeyInfo.getCerts());
+ validator.validate(credential);
}
if (log.isDebugEnabled()) {
log.debug("SAML Assertion issuer " + assertion.getIssuerString());
log.debug(DOM2Writer.nodeToString(token));
}
+
return assertion;
}
Modified: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SignatureProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SignatureProcessor.java?rev=1062763&r1=1062762&r2=1062763&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SignatureProcessor.java (original)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/SignatureProcessor.java Mon Jan 24 13:15:50 2011
@@ -21,7 +21,6 @@ package org.apache.ws.security.processor
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.ws.security.PublicKeyCallback;
import org.apache.ws.security.PublicKeyPrincipal;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSDataRef;
@@ -38,12 +37,14 @@ import org.apache.ws.security.str.Signat
import org.apache.ws.security.transform.STRTransform;
import org.apache.ws.security.transform.STRTransformUtil;
import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.ws.security.validate.Credential;
+import org.apache.ws.security.validate.SignatureTrustValidator;
+import org.apache.ws.security.validate.Validator;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
-import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.xml.crypto.MarshalException;
@@ -62,12 +63,9 @@ import javax.xml.crypto.dsig.keyinfo.Key
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.KeyValue;
-import java.math.BigInteger;
import java.security.Key;
import java.security.PublicKey;
import java.security.Principal;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.List;
@@ -79,7 +77,8 @@ public class SignatureProcessor implemen
private XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance("DOM");
private KeyInfoFactory keyInfoFactory = KeyInfoFactory.getInstance("DOM");
-
+ private Validator validator = new SignatureTrustValidator();
+
public List<WSSecurityEngineResult> handleToken(
Element elem,
Crypto crypto,
@@ -102,6 +101,9 @@ public class SignatureProcessor implemen
PublicKey publicKey = null;
byte[] secretKey = null;
String signatureMethod = getSignatureMethod(elem);
+
+ validator.setCrypto(crypto);
+
if (keyInfoElement == null) {
certs = getDefaultCerts(crypto);
principal = certs[0].getSubjectX500Principal();
@@ -114,7 +116,10 @@ public class SignatureProcessor implemen
);
if (strElement == null) {
publicKey = parseKeyValue(keyInfoElement);
- principal = validatePublicKey(cb, publicKey);
+ Credential credential = new Credential();
+ credential.setPublicKey(publicKey);
+ validator.validate(credential);
+ principal = new PublicKeyPrincipal(publicKey);
} else {
STRParser strParser = new SignatureSTRParser();
Map<String, Object> parameters = new HashMap<String, Object>();
@@ -129,7 +134,12 @@ public class SignatureProcessor implemen
certs = strParser.getCertificates();
publicKey = strParser.getPublicKey();
secretKey = strParser.getSecretKey();
- validateCredentials(certs, crypto);
+ if (certs != null || publicKey != null) {
+ Credential credential = new Credential();
+ credential.setPublicKey(publicKey);
+ credential.setCertificates(certs);
+ validator.validate(credential);
+ }
}
}
@@ -189,214 +199,6 @@ public class SignatureProcessor implemen
}
}
- /**
- * Validate the credentials that were extracted from the SecurityTokenReference
- * TODO move into Validator
- * @throws WSSecurityException if the credentials are invalid
- */
- private void validateCredentials(
- X509Certificate[] certs,
- Crypto crypto
- ) throws WSSecurityException {
- //
- // Validate certificates and verify trust
- //
- validateCertificates(certs);
- if (certs != null) {
- boolean trust = false;
- if (certs.length == 1) {
- trust = verifyTrust(certs[0], crypto);
- } else if (certs.length > 1) {
- trust = verifyTrust(certs, crypto);
- }
- if (!trust) {
- throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
- }
- }
- }
-
- /**
- * Validate an array of certificates by checking the validity of each cert
- * @param certsToValidate The array of certificates to validate
- * @throws WSSecurityException
- */
- private static void validateCertificates(
- X509Certificate[] certsToValidate
- ) throws WSSecurityException {
- if (certsToValidate != null && certsToValidate.length > 0) {
- try {
- for (int i = 0; i < certsToValidate.length; i++) {
- certsToValidate[i].checkValidity();
- }
- } catch (CertificateExpiredException e) {
- throw new WSSecurityException(
- WSSecurityException.FAILED_CHECK, "invalidCert", null, e
- );
- } catch (CertificateNotYetValidException e) {
- throw new WSSecurityException(
- WSSecurityException.FAILED_CHECK, "invalidCert", null, e
- );
- }
- }
- }
-
-
- /**
- * Evaluate whether a given certificate should be trusted.
- *
- * Policy used in this implementation:
- * 1. Search the keystore for the transmitted certificate
- * 2. Search the keystore for a connection to the transmitted certificate
- * (that is, search for certificate(s) of the issuer of the transmitted certificate
- * 3. Verify the trust path for those certificates found because the search for the issuer
- * might be fooled by a phony DN (String!)
- *
- * @param cert the certificate that should be validated against the keystore
- * @return true if the certificate is trusted, false if not
- * @throws WSSecurityException
- */
- private static boolean verifyTrust(X509Certificate cert, Crypto crypto)
- throws WSSecurityException {
-
- // If no certificate was transmitted, do not trust the signature
- if (cert == null) {
- return false;
- }
-
- String subjectString = cert.getSubjectX500Principal().getName();
- String issuerString = cert.getIssuerX500Principal().getName();
- BigInteger issuerSerial = cert.getSerialNumber();
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("Transmitted certificate has subject " + subjectString);
- LOG.debug(
- "Transmitted certificate has issuer " + issuerString + " (serial "
- + issuerSerial + ")"
- );
- }
-
- //
- // FIRST step - Search the keystore for the transmitted certificate
- //
- if (crypto.isCertificateInKeyStore(cert)) {
- return true;
- }
-
- //
- // SECOND step - Search for the issuer of the transmitted certificate in the
- // keystore or the truststore
- //
- String[] aliases = crypto.getAliasesForDN(issuerString);
-
- // If the alias has not been found, the issuer is not in the keystore/truststore
- // As a direct result, do not trust the transmitted certificate
- if (aliases == null || aliases.length < 1) {
- if (LOG.isDebugEnabled()) {
- LOG.debug(
- "No aliases found in keystore for issuer " + issuerString
- + " of certificate for " + subjectString
- );
- }
- return false;
- }
-
- //
- // THIRD step
- // Check the certificate trust path for every alias of the issuer found in the
- // keystore/truststore
- //
- for (int i = 0; i < aliases.length; i++) {
- String alias = aliases[i];
-
- if (LOG.isDebugEnabled()) {
- LOG.debug(
- "Preparing to validate certificate path with alias " + alias
- + " for issuer " + issuerString
- );
- }
-
- // Retrieve the certificate(s) for the alias from the keystore/truststore
- X509Certificate[] certs = crypto.getCertificates(alias);
-
- // If no certificates have been found, there has to be an error:
- // The keystore/truststore can find an alias but no certificate(s)
- if (certs == null || certs.length < 1) {
- throw new WSSecurityException(
- "Could not get certificates for alias " + alias
- );
- }
-
- //
- // Form a certificate chain from the transmitted certificate
- // and the certificate(s) of the issuer from the keystore/truststore
- //
- X509Certificate[] x509certs = new X509Certificate[certs.length + 1];
- x509certs[0] = cert;
- for (int j = 0; j < certs.length; j++) {
- 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
- //
- if (crypto.validateCertPath(x509certs)) {
- 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;
- }
-
-
- /**
- * 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
- */
- private 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;
- }
-
-
private PublicKey parseKeyValue(
Element keyInfoElement
) throws WSSecurityException {
@@ -446,36 +248,6 @@ public class SignatureProcessor implemen
return null;
}
- /**
- * Validate a public key via a CallbackHandler
- * @param cb The CallbackHandler object
- * @param publicKey The PublicKey to validate
- * @return A PublicKeyPrincipal object encapsulating the public key after successful
- * validation
- * @throws WSSecurityException
- */
- private static Principal validatePublicKey(
- CallbackHandler cb,
- PublicKey publicKey
- ) throws WSSecurityException {
- PublicKeyCallback pwcb =
- new PublicKeyCallback(publicKey);
- try {
- Callback[] callbacks = new Callback[]{pwcb};
- cb.handle(callbacks);
- if (!pwcb.isVerified()) {
- throw new WSSecurityException(
- WSSecurityException.FAILED_AUTHENTICATION, null, null, null
- );
- }
- } catch (Exception e) {
- throw new WSSecurityException(
- WSSecurityException.FAILED_AUTHENTICATION, null, null, e
- );
- }
- return new PublicKeyPrincipal(publicKey);
- }
-
/**
* Verify the WS-Security signature.
Modified: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/TimestampProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/TimestampProcessor.java?rev=1062763&r1=1062762&r2=1062763&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/TimestampProcessor.java (original)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/TimestampProcessor.java Mon Jan 24 13:15:50 2011
@@ -28,6 +28,9 @@ import org.apache.ws.security.WSSecurity
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.message.token.Timestamp;
+import org.apache.ws.security.validate.Credential;
+import org.apache.ws.security.validate.TimestampValidator;
+import org.apache.ws.security.validate.Validator;
import org.w3c.dom.Element;
import java.util.List;
@@ -35,6 +38,7 @@ import javax.security.auth.callback.Call
public class TimestampProcessor implements Processor {
private static Log log = LogFactory.getLog(TimestampProcessor.class.getName());
+ private Validator validator = new TimestampValidator();
public List<WSSecurityEngineResult> handleToken(
Element elem,
@@ -51,7 +55,11 @@ public class TimestampProcessor implemen
// Decode Timestamp, add the found time (created/expiry) to result
//
Timestamp timestamp = new Timestamp(elem);
- handleTimestamp(timestamp, wsc);
+ Credential credential = new Credential();
+ credential.setTimestamp(timestamp);
+ validator.setWSSConfig(wsc);
+ validator.validate(credential);
+
WSSecurityEngineResult result =
new WSSecurityEngineResult(WSConstants.TS, timestamp);
result.put(WSSecurityEngineResult.TAG_ID, timestamp.getID());
@@ -60,23 +68,4 @@ public class TimestampProcessor implemen
return java.util.Collections.singletonList(result);
}
- private void handleTimestamp(
- Timestamp timestamp,
- WSSConfig wssConfig
- ) throws WSSecurityException {
- if (log.isDebugEnabled()) {
- log.debug("Preparing to verify the timestamp");
- }
-
- // Validate whether the security semantics have expired
- if ((wssConfig.isTimeStampStrict() && timestamp.isExpired())
- || !timestamp.verifyCreated(wssConfig.getTimeStampTTL())) {
- throw new WSSecurityException(
- WSSecurityException.MESSAGE_EXPIRED,
- "invalidTimestamp",
- new Object[] {"The security semantics of the message have expired"}
- );
- }
- }
-
}
Modified: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/UsernameTokenProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/UsernameTokenProcessor.java?rev=1062763&r1=1062762&r2=1062763&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/UsernameTokenProcessor.java (original)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/processor/UsernameTokenProcessor.java Mon Jan 24 13:15:50 2011
@@ -23,24 +23,24 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSDocInfo;
-import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.WSUsernameTokenPrincipal;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.message.token.UsernameToken;
-import org.apache.ws.security.util.Base64;
+import org.apache.ws.security.validate.Credential;
+import org.apache.ws.security.validate.UsernameTokenValidator;
+import org.apache.ws.security.validate.Validator;
import org.w3c.dom.Element;
-import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import java.io.IOException;
import java.util.List;
public class UsernameTokenProcessor implements Processor {
private static Log log = LogFactory.getLog(UsernameTokenProcessor.class.getName());
+
+ private Validator validator = new UsernameTokenValidator();
public List<WSSecurityEngineResult> handleToken(
Element elem, Crypto crypto, Crypto decCrypto, CallbackHandler cb,
@@ -49,8 +49,10 @@ public class UsernameTokenProcessor impl
if (log.isDebugEnabled()) {
log.debug("Found UsernameToken list element");
}
+ validator.setCallbackHandler(cb);
+ validator.setWSSConfig(wsc);
- UsernameToken token = handleUsernameToken(elem, cb, wsc);
+ UsernameToken token = handleUsernameToken(elem, wsc);
WSUsernameTokenPrincipal principal =
new WSUsernameTokenPrincipal(token.getName(), token.isHashed());
@@ -80,7 +82,6 @@ public class UsernameTokenProcessor impl
* <code>USERNAME_TOKEN_UNKNOWN</code>.
*
* @param token the DOM element that contains the UsernameToken
- * @param cb the reference to the callback object
* @param wssConfig The WSSConfig object from which to obtain configuration
* @return UsernameToken the UsernameToken object that was parsed
* @throws WSSecurityException
@@ -88,127 +89,22 @@ public class UsernameTokenProcessor impl
public UsernameToken
handleUsernameToken(
Element token,
- CallbackHandler cb,
WSSConfig wssConfig
) throws WSSecurityException {
- if (cb == null) {
- throw new WSSecurityException(WSSecurityException.FAILURE, "noCallback");
- }
- boolean handleCustomPasswordTypes = false;
boolean allowNamespaceQualifiedPasswordTypes = false;
- boolean passwordsAreEncoded = false;
-
if (wssConfig != null) {
- handleCustomPasswordTypes = wssConfig.getHandleCustomPasswordTypes();
allowNamespaceQualifiedPasswordTypes =
wssConfig.getAllowNamespaceQualifiedPasswordTypes();
- passwordsAreEncoded = wssConfig.getPasswordsAreEncoded();
}
//
- // Parse the UsernameToken element
+ // Parse and validate the UsernameToken element
//
UsernameToken ut = new UsernameToken(token, allowNamespaceQualifiedPasswordTypes);
- ut.setPasswordsAreEncoded(passwordsAreEncoded);
- String user = ut.getName();
- String password = ut.getPassword();
- String nonce = ut.getNonce();
- String createdTime = ut.getCreated();
- String pwType = ut.getPasswordType();
- if (log.isDebugEnabled()) {
- log.debug("UsernameToken user " + user);
- log.debug("UsernameToken password type " + pwType);
- }
+ Credential credential = new Credential();
+ credential.setUsernametoken(ut);
+ validator.validate(credential);
- if (wssConfig != null) {
- String requiredPasswordType = wssConfig.getRequiredPasswordType();
- if (requiredPasswordType != null && !requiredPasswordType.equals(pwType)) {
- if (log.isDebugEnabled()) {
- log.debug("Authentication failed as the received password type does not "
- + "match the required password type of: " + requiredPasswordType);
- }
- throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
- }
- }
- //
- // If the UsernameToken is hashed or plaintext, then retrieve the password from the
- // callback handler and compare directly. If the UsernameToken is of some unknown type,
- // then delegate authentication to the callback handler
- //
- if (ut.isHashed() || WSConstants.PASSWORD_TEXT.equals(pwType)
- || (password != null && (pwType == null || "".equals(pwType.trim())))) {
- WSPasswordCallback pwCb =
- new WSPasswordCallback(user, null, pwType, WSPasswordCallback.USERNAME_TOKEN);
- try {
- cb.handle(new Callback[]{pwCb});
- } catch (IOException e) {
- if (log.isDebugEnabled()) {
- log.debug(e);
- }
- throw new WSSecurityException(
- WSSecurityException.FAILED_AUTHENTICATION, null, null, e
- );
- } catch (UnsupportedCallbackException e) {
- if (log.isDebugEnabled()) {
- log.debug(e);
- }
- throw new WSSecurityException(
- WSSecurityException.FAILED_AUTHENTICATION, null, null, e
- );
- }
- String origPassword = pwCb.getPassword();
- if (origPassword == null) {
- if (log.isDebugEnabled()) {
- log.debug("Callback supplied no password for: " + user);
- }
- throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
- }
- if (ut.isHashed()) {
- String passDigest;
- if (passwordsAreEncoded) {
- passDigest = UsernameToken.doPasswordDigest(nonce, createdTime, Base64.decode(origPassword));
- } else {
- passDigest = UsernameToken.doPasswordDigest(nonce, createdTime, origPassword);
- }
- if (!passDigest.equals(password)) {
- throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
- }
- } else {
- if (!origPassword.equals(password)) {
- throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
- }
- }
- ut.setRawPassword(origPassword);
- } else {
- if (pwType != null && !handleCustomPasswordTypes) {
- if (log.isDebugEnabled()) {
- log.debug("Authentication failed as handleCustomUsernameTokenTypes is false");
- }
- throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
- }
- WSPasswordCallback pwCb = new WSPasswordCallback(user, password,
- pwType, WSPasswordCallback.USERNAME_TOKEN_UNKNOWN);
- try {
- cb.handle(new Callback[]{pwCb});
- } catch (IOException e) {
- if (log.isDebugEnabled()) {
- log.debug(e);
- }
- throw new WSSecurityException(
- WSSecurityException.FAILED_AUTHENTICATION, null, null, e
- );
- } catch (UnsupportedCallbackException e) {
- if (log.isDebugEnabled()) {
- log.debug(e);
- }
- throw new WSSecurityException(
- WSSecurityException.FAILED_AUTHENTICATION, null, null, e
- );
- }
- String origPassword = pwCb.getPassword();
- ut.setRawPassword(origPassword);
- }
-
return ut;
}
Modified: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java?rev=1062763&r1=1062762&r2=1062763&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java (original)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/saml/ext/AssertionWrapper.java Mon Jan 24 13:15:50 2011
@@ -510,9 +510,10 @@ public class AssertionWrapper {
/**
* Verify the signature of this assertion
*
+ * @return the SAMLKeyInfo structure containing the credentials used to verify the signature
* @throws ValidationException
*/
- public void verify(Crypto crypto) throws WSSecurityException {
+ public SAMLKeyInfo verify(Crypto crypto) throws WSSecurityException {
Signature sig = null;
if (saml2 != null && saml2.getSignature() != null) {
sig = saml2.getSignature();
@@ -553,9 +554,11 @@ public class AssertionWrapper {
} catch (ValidationException ex) {
throw new WSSecurityException("SAML signature validation failed", ex);
}
+ return samlKeyInfo;
} else {
log.debug("AssertionWrapper: no signature to validate");
}
+ return null;
}
Added: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/Credential.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/Credential.java?rev=1062763&view=auto
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/Credential.java (added)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/Credential.java Mon Jan 24 13:15:50 2011
@@ -0,0 +1,70 @@
+/**
+ * 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.ws.security.validate;
+
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+
+import org.apache.ws.security.message.token.Timestamp;
+import org.apache.ws.security.message.token.UsernameToken;
+
+/**
+ * This interface describes an abstract concept of a Credential to be validated.
+ */
+public class Credential {
+
+ private PublicKey publicKey;
+ private X509Certificate[] certs;
+ private Timestamp timestamp;
+ private UsernameToken usernametoken;
+
+ public void setPublicKey(PublicKey publicKey) {
+ this.publicKey = publicKey;
+ }
+
+ public PublicKey getPublicKey() {
+ return publicKey;
+ }
+
+ public void setCertificates(X509Certificate[] certs) {
+ this.certs = certs;
+ }
+
+ public X509Certificate[] getCertificates() {
+ return certs;
+ }
+
+ public void setTimestamp(Timestamp timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public Timestamp getTimestamp() {
+ return timestamp;
+ }
+
+ public void setUsernametoken(UsernameToken usernametoken) {
+ this.usernametoken = usernametoken;
+ }
+
+ public UsernameToken getUsernametoken() {
+ return usernametoken;
+ }
+
+}
Added: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/SignatureTrustValidator.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/SignatureTrustValidator.java?rev=1062763&view=auto
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/SignatureTrustValidator.java (added)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/SignatureTrustValidator.java Mon Jan 24 13:15:50 2011
@@ -0,0 +1,264 @@
+/**
+ * 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.ws.security.validate;
+
+import java.math.BigInteger;
+import java.security.PublicKey;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+
+import javax.security.auth.callback.CallbackHandler;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+
+/**
+ * This interface describes a pluggable way of validating credentials that have been extracted
+ * by the processors.
+ */
+public class SignatureTrustValidator implements Validator {
+
+ private static Log LOG = LogFactory.getLog(SignatureTrustValidator.class.getName());
+ private Crypto crypto;
+
+ public void validate(Credential credential) throws WSSecurityException {
+ if (credential == null) {
+ throw new WSSecurityException("Credential cannot be null");
+ }
+ X509Certificate[] certs = credential.getCertificates();
+ PublicKey publicKey = credential.getPublicKey();
+ if (crypto == null) {
+ throw new WSSecurityException("Crypto instance cannot be null");
+ }
+
+ if (certs != null && certs.length > 0) {
+ validateCertificates(certs);
+ boolean trust = false;
+ if (certs.length == 1) {
+ trust = verifyTrustInCert(certs);
+ } else {
+ trust = verifyTrustInCerts(certs);
+ }
+ if (trust) {
+ return;
+ }
+ }
+ if (publicKey != null) {
+ boolean trust = validatePublicKey(publicKey);
+ if (trust) {
+ return;
+ }
+ }
+ throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION, null);
+ }
+
+ public void setWSSConfig(WSSConfig wssConfig) {
+ //
+ }
+
+ public void setCrypto(Crypto crypto) {
+ this.crypto = crypto;
+ }
+
+ public void setCallbackHandler(CallbackHandler callbackHandler) {
+ //
+ }
+
+ /**
+ * Validate the certificates by checking the validity of each cert
+ * @throws WSSecurityException
+ */
+ private void validateCertificates(X509Certificate[] certificates) throws WSSecurityException {
+ try {
+ for (int i = 0; i < certificates.length; i++) {
+ certificates[i].checkValidity();
+ }
+ } catch (CertificateExpiredException e) {
+ throw new WSSecurityException(
+ WSSecurityException.FAILED_CHECK, "invalidCert", null, e
+ );
+ } catch (CertificateNotYetValidException e) {
+ throw new WSSecurityException(
+ WSSecurityException.FAILED_CHECK, "invalidCert", null, e
+ );
+ }
+ }
+
+ /**
+ * Evaluate whether a given certificate should be trusted.
+ *
+ * Policy used in this implementation:
+ * 1. Search the keystore for the transmitted certificate
+ * 2. Search the keystore for a connection to the transmitted certificate
+ * (that is, search for certificate(s) of the issuer of the transmitted certificate
+ * 3. Verify the trust path for those certificates found because the search for the issuer
+ * might be fooled by a phony DN (String!)
+ *
+ * @param cert the certificate that should be validated against the keystore
+ * @return true if the certificate is trusted, false if not
+ * @throws WSSecurityException
+ */
+ private boolean verifyTrustInCert(X509Certificate[] certificates) throws WSSecurityException {
+ X509Certificate cert = certificates[0];
+
+ String subjectString = cert.getSubjectX500Principal().getName();
+ String issuerString = cert.getIssuerX500Principal().getName();
+ BigInteger issuerSerial = cert.getSerialNumber();
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Transmitted certificate has subject " + subjectString);
+ LOG.debug(
+ "Transmitted certificate has issuer " + issuerString + " (serial "
+ + issuerSerial + ")"
+ );
+ }
+
+ //
+ // FIRST step - Search the keystore for the transmitted certificate
+ //
+ if (crypto.isCertificateInKeyStore(cert)) {
+ return true;
+ }
+
+ //
+ // SECOND step - Search for the issuer of the transmitted certificate in the
+ // keystore or the truststore
+ //
+ String[] aliases = crypto.getAliasesForDN(issuerString);
+
+ // If the alias has not been found, the issuer is not in the keystore/truststore
+ // As a direct result, do not trust the transmitted certificate
+ if (aliases == null || aliases.length < 1) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "No aliases found in keystore for issuer " + issuerString
+ + " of certificate for " + subjectString
+ );
+ }
+ return false;
+ }
+
+ //
+ // THIRD step
+ // Check the certificate trust path for every alias of the issuer found in the
+ // keystore/truststore
+ //
+ for (int i = 0; i < aliases.length; i++) {
+ String alias = aliases[i];
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(
+ "Preparing to validate certificate path with alias " + alias
+ + " for issuer " + issuerString
+ );
+ }
+
+ // Retrieve the certificate(s) for the alias from the keystore/truststore
+ X509Certificate[] certs = crypto.getCertificates(alias);
+
+ // If no certificates have been found, there has to be an error:
+ // The keystore/truststore can find an alias but no certificate(s)
+ if (certs == null || certs.length < 1) {
+ throw new WSSecurityException(
+ "Could not get certificates for alias " + alias
+ );
+ }
+
+ //
+ // Form a certificate chain from the transmitted certificate
+ // and the certificate(s) of the issuer from the keystore/truststore
+ //
+ X509Certificate[] x509certs = new X509Certificate[certs.length + 1];
+ x509certs[0] = cert;
+ for (int j = 0; j < certs.length; j++) {
+ 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
+ //
+ if (crypto.validateCertPath(x509certs)) {
+ 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;
+ }
+
+ /**
+ * 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
+ */
+ private boolean verifyTrustInCerts(X509Certificate[] certificates) 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;
+ }
+
+ /**
+ * Validate a public key
+ * @throws WSSecurityException
+ */
+ private boolean validatePublicKey(PublicKey publicKey) throws WSSecurityException {
+ return crypto.verifyTrust(publicKey);
+ }
+
+}
Added: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/TimestampValidator.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/TimestampValidator.java?rev=1062763&view=auto
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/TimestampValidator.java (added)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/TimestampValidator.java Mon Jan 24 13:15:50 2011
@@ -0,0 +1,72 @@
+/**
+ * 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.ws.security.validate;
+
+import javax.security.auth.callback.CallbackHandler;
+
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.Timestamp;
+
+/**
+ * This interface describes a pluggable way of validating credentials that have been extracted
+ * by the processors.
+ */
+public class TimestampValidator implements Validator {
+
+ private WSSConfig wssConfig;
+
+ public void validate(Credential credential) throws WSSecurityException {
+ if (credential == null) {
+ throw new WSSecurityException("Credential cannot be null");
+ }
+ Timestamp timeStamp = credential.getTimestamp();
+ if (timeStamp == null) {
+ throw new WSSecurityException(WSSecurityException.MESSAGE_EXPIRED, "invalidTimestamp");
+ }
+ if (wssConfig == null) {
+ throw new WSSecurityException("WSSConfig cannot be null");
+ }
+
+ // Validate whether the security semantics have expired
+ if ((wssConfig.isTimeStampStrict() && timeStamp.isExpired())
+ || !timeStamp.verifyCreated(wssConfig.getTimeStampTTL())) {
+ throw new WSSecurityException(
+ WSSecurityException.MESSAGE_EXPIRED,
+ "invalidTimestamp",
+ new Object[] {"The security semantics of the message have expired"}
+ );
+ }
+ }
+
+ public void setWSSConfig(WSSConfig wssConfig) {
+ this.wssConfig = wssConfig;
+ }
+
+ public void setCrypto(Crypto crypto) {
+ //
+ }
+
+ public void setCallbackHandler(CallbackHandler callbackHandler) {
+ //
+ }
+
+}
Added: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/UsernameTokenValidator.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/UsernameTokenValidator.java?rev=1062763&view=auto
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/UsernameTokenValidator.java (added)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/UsernameTokenValidator.java Mon Jan 24 13:15:50 2011
@@ -0,0 +1,182 @@
+/**
+ * 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.ws.security.validate;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.message.token.UsernameToken;
+import org.apache.ws.security.util.Base64;
+
+/**
+ * This interface describes a pluggable way of validating credentials that have been extracted
+ * by the processors.
+ */
+public class UsernameTokenValidator implements Validator {
+
+ private static Log log = LogFactory.getLog(UsernameTokenValidator.class.getName());
+
+ private WSSConfig wssConfig;
+ private CallbackHandler callbackHandler;
+
+ public void validate(Credential credential) throws WSSecurityException {
+ if (credential == null) {
+ throw new WSSecurityException("Credential cannot be null");
+ }
+ if (wssConfig == null) {
+ throw new WSSecurityException("WSSConfig cannot be null");
+ }
+ if (callbackHandler == null) {
+ throw new WSSecurityException(WSSecurityException.FAILURE, "noCallback");
+ }
+
+ boolean handleCustomPasswordTypes = wssConfig.getHandleCustomPasswordTypes();
+ boolean passwordsAreEncoded = wssConfig.getPasswordsAreEncoded();
+
+ UsernameToken usernameToken = credential.getUsernametoken();
+ if (usernameToken == null) {
+ throw new WSSecurityException("Username Token cannot be null");
+ }
+ usernameToken.setPasswordsAreEncoded(passwordsAreEncoded);
+
+ String user = usernameToken.getName();
+ String password = usernameToken.getPassword();
+ String nonce = usernameToken.getNonce();
+ String createdTime = usernameToken.getCreated();
+ String pwType = usernameToken.getPasswordType();
+ if (log.isDebugEnabled()) {
+ log.debug("UsernameToken user " + user);
+ log.debug("UsernameToken password type " + pwType);
+ }
+
+ String requiredPasswordType = wssConfig.getRequiredPasswordType();
+ if (requiredPasswordType != null && !requiredPasswordType.equals(pwType)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Authentication failed as the received password type does not "
+ + "match the required password type of: " + requiredPasswordType);
+ }
+ throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
+ }
+
+
+ //
+ // If the UsernameToken is hashed or plaintext, then retrieve the password from the
+ // callback handler and compare directly. If the UsernameToken is of some unknown type,
+ // then delegate authentication to the callback handler
+ //
+ if (usernameToken.isHashed() || WSConstants.PASSWORD_TEXT.equals(pwType)
+ || (password != null && (pwType == null || "".equals(pwType.trim())))) {
+ WSPasswordCallback pwCb =
+ new WSPasswordCallback(user, null, pwType, WSPasswordCallback.USERNAME_TOKEN);
+ try {
+ callbackHandler.handle(new Callback[]{pwCb});
+ } catch (IOException e) {
+ if (log.isDebugEnabled()) {
+ log.debug(e);
+ }
+ throw new WSSecurityException(
+ WSSecurityException.FAILED_AUTHENTICATION, null, null, e
+ );
+ } catch (UnsupportedCallbackException e) {
+ if (log.isDebugEnabled()) {
+ log.debug(e);
+ }
+ throw new WSSecurityException(
+ WSSecurityException.FAILED_AUTHENTICATION, null, null, e
+ );
+ }
+ String origPassword = pwCb.getPassword();
+ if (origPassword == null) {
+ if (log.isDebugEnabled()) {
+ log.debug("Callback supplied no password for: " + user);
+ }
+ throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
+ }
+ if (usernameToken.isHashed()) {
+ String passDigest;
+ if (passwordsAreEncoded) {
+ passDigest = UsernameToken.doPasswordDigest(nonce, createdTime, Base64.decode(origPassword));
+ } else {
+ passDigest = UsernameToken.doPasswordDigest(nonce, createdTime, origPassword);
+ }
+ if (!passDigest.equals(password)) {
+ throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
+ }
+ } else {
+ if (!origPassword.equals(password)) {
+ throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
+ }
+ }
+ usernameToken.setRawPassword(origPassword);
+ } else {
+ if (pwType != null && !handleCustomPasswordTypes) {
+ if (log.isDebugEnabled()) {
+ log.debug("Authentication failed as handleCustomUsernameTokenTypes is false");
+ }
+ throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
+ }
+ WSPasswordCallback pwCb = new WSPasswordCallback(user, password,
+ pwType, WSPasswordCallback.USERNAME_TOKEN_UNKNOWN);
+ try {
+ callbackHandler.handle(new Callback[]{pwCb});
+ } catch (IOException e) {
+ if (log.isDebugEnabled()) {
+ log.debug(e);
+ }
+ throw new WSSecurityException(
+ WSSecurityException.FAILED_AUTHENTICATION, null, null, e
+ );
+ } catch (UnsupportedCallbackException e) {
+ if (log.isDebugEnabled()) {
+ log.debug(e);
+ }
+ throw new WSSecurityException(
+ WSSecurityException.FAILED_AUTHENTICATION, null, null, e
+ );
+ }
+ String origPassword = pwCb.getPassword();
+ usernameToken.setRawPassword(origPassword);
+ }
+
+ }
+
+ public void setWSSConfig(WSSConfig wssConfig) {
+ this.wssConfig = wssConfig;
+ }
+
+ public void setCrypto(Crypto crypto) {
+ //
+ }
+
+ public void setCallbackHandler(CallbackHandler callbackHandler) {
+ this.callbackHandler = callbackHandler;
+ }
+
+}
Added: webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/Validator.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/Validator.java?rev=1062763&view=auto
==============================================================================
--- webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/Validator.java (added)
+++ webservices/wss4j/trunk/src/main/java/org/apache/ws/security/validate/Validator.java Mon Jan 24 13:15:50 2011
@@ -0,0 +1,42 @@
+/**
+ * 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.ws.security.validate;
+
+import javax.security.auth.callback.CallbackHandler;
+
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+
+/**
+ * This interface describes a pluggable way of validating credentials that have been extracted
+ * by the processors.
+ */
+public interface Validator {
+
+ public void validate(Credential credential) throws WSSecurityException;
+
+ public void setCrypto(Crypto crypto);
+
+ public void setCallbackHandler(CallbackHandler callbackHandler);
+
+ public void setWSSConfig(WSSConfig wssConfig);
+
+}
Modified: webservices/wss4j/trunk/src/test/java/org/apache/ws/security/common/KeystoreCallbackHandler.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/test/java/org/apache/ws/security/common/KeystoreCallbackHandler.java?rev=1062763&r1=1062762&r2=1062763&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/test/java/org/apache/ws/security/common/KeystoreCallbackHandler.java (original)
+++ webservices/wss4j/trunk/src/test/java/org/apache/ws/security/common/KeystoreCallbackHandler.java Mon Jan 24 13:15:50 2011
@@ -47,15 +47,7 @@ public class KeystoreCallbackHandler imp
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
- switch (pc.getUsage()) {
- case WSPasswordCallback.CUSTOM_TOKEN:
- case WSPasswordCallback.DECRYPT: {
- pc.setPassword(users.get(pc.getIdentifier()));
- break;
- }
- default:
- throw new IOException("Authentication failed");
- }
+ pc.setPassword(users.get(pc.getIdentifier()));
} else {
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}
Modified: webservices/wss4j/trunk/src/test/java/org/apache/ws/security/message/SignatureKeyValueTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/test/java/org/apache/ws/security/message/SignatureKeyValueTest.java?rev=1062763&r1=1062762&r2=1062763&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/test/java/org/apache/ws/security/message/SignatureKeyValueTest.java (original)
+++ webservices/wss4j/trunk/src/test/java/org/apache/ws/security/message/SignatureKeyValueTest.java Mon Jan 24 13:15:50 2011
@@ -25,7 +25,6 @@ import org.apache.ws.security.PublicKeyP
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityEngine;
import org.apache.ws.security.WSSecurityEngineResult;
-import org.apache.ws.security.common.PublicKeyCallbackHandler;
import org.apache.ws.security.common.SOAPUtil;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
@@ -43,11 +42,6 @@ public class SignatureKeyValueTest exten
private static final Log LOG = LogFactory.getLog(SignatureKeyValueTest.class);
private WSSecurityEngine secEngine = new WSSecurityEngine();
private Crypto crypto = CryptoFactory.getInstance("wss40.properties");
- private PublicKeyCallbackHandler callbackHandler = new PublicKeyCallbackHandler();
-
- public SignatureKeyValueTest() {
- callbackHandler.setKeyStore(crypto.getKeyStore());
- }
/**
* Successful RSAKeyValue test.
@@ -158,7 +152,7 @@ public class SignatureKeyValueTest exten
* @throws java.lang.Exception Thrown when there is a problem in verification
*/
private List<WSSecurityEngineResult> verify(Document doc) throws Exception {
- return secEngine.processSecurityHeader(doc, null, callbackHandler, null);
+ return secEngine.processSecurityHeader(doc, null, null, crypto);
}
}
Modified: webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenHOKTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenHOKTest.java?rev=1062763&r1=1062762&r2=1062763&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenHOKTest.java (original)
+++ webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SamlTokenHOKTest.java Mon Jan 24 13:15:50 2011
@@ -260,7 +260,7 @@ public class SamlTokenHOKTest extends or
*/
private List<WSSecurityEngineResult> verify(Document doc) throws Exception {
List<WSSecurityEngineResult> results =
- secEngine.processSecurityHeader(doc, null, null, null);
+ secEngine.processSecurityHeader(doc, null, null, crypto);
String outputString =
org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
assertTrue(outputString.indexOf("counter_port_type") > 0 ? true : false);
Modified: webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SignedSamlTokenHOKTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SignedSamlTokenHOKTest.java?rev=1062763&r1=1062762&r2=1062763&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SignedSamlTokenHOKTest.java (original)
+++ webservices/wss4j/trunk/src/test/java/org/apache/ws/security/saml/SignedSamlTokenHOKTest.java Mon Jan 24 13:15:50 2011
@@ -145,61 +145,6 @@ public class SignedSamlTokenHOKTest exte
}
/**
- * Test that creates, sends and processes a signed SAML 1.1 authentication assertion, where
- * the configuration is loaded from a properties file
- */
- @org.junit.Test
- @SuppressWarnings("unchecked")
- public void testSAML1AuthnAssertionFromProperties() throws Exception {
- SAMLIssuer saml = SAMLIssuerFactory.getInstance("saml_hok.properties");
- AssertionWrapper assertion = saml.newAssertion();
-
- WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
- wsSign.setUserInfo("wss40", "security");
- wsSign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
- wsSign.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
- wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
-
- Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
- WSSecHeader secHeader = new WSSecHeader();
- secHeader.insertSecurityHeader(doc);
-
- Document signedDoc =
- wsSign.build(doc, userCrypto, assertion, null, null, null, secHeader);
-
- String outputString =
- org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
- if (LOG.isDebugEnabled()) {
- LOG.debug("Signed SAML 1.1 Authn Assertion (key holder):");
- LOG.debug(outputString);
- }
- assertTrue(outputString.indexOf("http://www.w3.org/2001/04/xmlenc#sha256") != -1);
- assertTrue(outputString.indexOf("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256") != -1);
-
- List<WSSecurityEngineResult> results = verify(signedDoc, trustCrypto);
-
- // Test we processed a SAML assertion
- WSSecurityEngineResult actionResult =
- WSSecurityUtil.fetchActionResult(results, WSConstants.ST_SIGNED);
- AssertionWrapper receivedAssertion =
- (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
- assertTrue(receivedAssertion != null);
- assert receivedAssertion.isSigned();
-
- // Test we processed a signature (SOAP body)
- actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
- assertTrue(actionResult != null);
- assertFalse(actionResult.isEmpty());
- final List<WSDataRef> refs =
- (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
- assertTrue(refs.size() == 1);
-
- WSDataRef wsDataRef = (WSDataRef)refs.get(0);
- String xpath = wsDataRef.getXpath();
- assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
- }
-
- /**
* Test that creates, sends and processes a signed SAML 1.1 attribute assertion.
*/
@org.junit.Test
@@ -473,7 +418,6 @@ public class SignedSamlTokenHOKTest exte
saml.setIssuerKeyName("wss40_server");
saml.setIssuerKeyPassword("security");
saml.setSignAssertion(true);
- // saml.setSamlVersion("2.0");
saml.setCallbackHandler(callbackHandler);
AssertionWrapper assertion = saml.newAssertion();