From 1f15b8cc2bf1af156405f027dce06d98934df8d1 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Wed, 9 May 2012 10:30:37 +0000 Subject: [PATCH] SWS-711 - Upgrade to wss4j 1.6 --- parent/pom.xml | 14 +- .../soap/security/support/KeyStoreUtils.java | 8 +- .../ws/soap/security/wss4j/Wss4jHandler.java | 91 ++---------- .../wss4j/Wss4jSecurityInterceptor.java | 130 ++++++++++-------- .../AbstractWsPasswordCallbackHandler.java | 53 ++----- .../callback/KeyStoreCallbackHandler.java | 16 +-- ...mplePasswordValidationCallbackHandler.java | 18 +-- ...TextPasswordValidationCallbackHandler.java | 93 ------------- ...ityPasswordValidationCallbackHandler.java} | 23 ++-- ...SpringSecurityCallbackHandlerTestCase.java | 30 ++-- .../callback/KeyStoreCallbackHandlerTest.java | 8 +- ...asswordValidationCallbackHandlerTest.java} | 6 +- 12 files changed, 141 insertions(+), 349 deletions(-) delete mode 100644 security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringPlainTextPasswordValidationCallbackHandler.java rename security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/{SpringDigestPasswordValidationCallbackHandler.java => SpringSecurityPasswordValidationCallbackHandler.java} (86%) rename security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/{SpringDigestPasswordValidationCallbackHandlerTest.java => SpringSecurityPasswordValidationCallbackHandlerTest.java} (93%) diff --git a/parent/pom.xml b/parent/pom.xml index 99cd8337..a76e6764 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -526,15 +526,11 @@ org.apache.ws.security wss4j - 1.5.8 + 1.6.5 - axis - axis - - - axis - axis-ant + xalan + xalan xerces @@ -544,10 +540,6 @@ xml-apis xml-apis - - junit - junit - diff --git a/security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreUtils.java b/security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreUtils.java index a92e4721..4370ac34 100644 --- a/security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreUtils.java +++ b/security/src/main/java/org/springframework/ws/soap/security/support/KeyStoreUtils.java @@ -1,11 +1,11 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2012 the original author or authors. * * Licensed 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 + * 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, @@ -68,7 +68,7 @@ public abstract class KeyStoreUtils { factoryBean.setPassword(password); factoryBean.setType(type); factoryBean.afterPropertiesSet(); - return (KeyStore) factoryBean.getObject(); + return factoryBean.getObject(); } /** @@ -117,7 +117,7 @@ public abstract class KeyStoreUtils { factoryBean.setPassword(password); factoryBean.setType(type); factoryBean.afterPropertiesSet(); - return (KeyStore) factoryBean.getObject(); + return factoryBean.getObject(); } } diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jHandler.java index 0b0e553e..32c9e1be 100644 --- a/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jHandler.java +++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jHandler.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2012 the original author or authors. * * Licensed 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 + * 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, @@ -16,26 +16,19 @@ package org.springframework.ws.soap.security.wss4j; -import java.io.IOException; -import java.security.cert.X509Certificate; +import java.util.List; import java.util.Properties; -import java.util.Vector; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.UnsupportedCallbackException; -import org.apache.ws.security.WSConstants; -import org.apache.ws.security.WSPasswordCallback; +import org.springframework.ws.context.MessageContext; + +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.handler.RequestData; import org.apache.ws.security.handler.WSHandler; import org.apache.ws.security.handler.WSHandlerConstants; -import org.apache.ws.security.message.token.Timestamp; import org.w3c.dom.Document; -import org.springframework.ws.context.MessageContext; - /** * @author Tareq Abed Rabbo * @author Arjen Poutsma @@ -46,8 +39,6 @@ class Wss4jHandler extends WSHandler { /** Keys are constants from {@link WSHandlerConstants}; values are strings. */ private Properties options = new Properties(); - private CallbackHandler securementCallbackHandler; - private String securementPassword; private Crypto securementEncryptionCrypto; @@ -61,12 +52,7 @@ class Wss4jHandler extends WSHandler { } @Override - protected boolean checkReceiverResults(Vector wsResult, Vector actions) { - return super.checkReceiverResults(wsResult, actions); - } - - @Override - protected boolean checkReceiverResultsAnyOrder(Vector wsResult, Vector actions) { + protected boolean checkReceiverResultsAnyOrder(List wsResult, List actions) { return super.checkReceiverResultsAnyOrder(wsResult, actions); } @@ -83,10 +69,6 @@ class Wss4jHandler extends WSHandler { return options.getProperty(key); } - void setSecurementCallbackHandler(CallbackHandler securementCallbackHandler) { - this.securementCallbackHandler = securementCallbackHandler; - } - void setSecurementPassword(String securementPassword) { this.securementPassword = securementPassword; } @@ -99,48 +81,6 @@ class Wss4jHandler extends WSHandler { this.securementSignatureCrypto = securementSignatureCrypto; } - /** Gets the password first from securementCallbackHandler, then from securementPassword if not found. */ - @Override - public WSPasswordCallback getPassword(String username, - int doAction, - String clsProp, - String refProp, - RequestData reqData) { - WSPasswordCallback callback; - if (securementCallbackHandler != null) { - int reason = 0; - - switch (doAction) { - case WSConstants.UT: - case WSConstants.UT_SIGN: - reason = WSPasswordCallback.USERNAME_TOKEN; - break; - case WSConstants.SIGN: - reason = WSPasswordCallback.SIGNATURE; - break; - case WSConstants.ENCR: - reason = WSPasswordCallback.KEY_NAME; - break; - } - callback = new WSPasswordCallback(username, reason); - Callback[] callbacks = new Callback[]{callback}; - try { - securementCallbackHandler.handle(callbacks); - } - catch (UnsupportedCallbackException ex) { - throw new Wss4jSecuritySecurementException(ex.getMessage(), ex); - } - catch (IOException ex) { - throw new Wss4jSecuritySecurementException(ex.getMessage(), ex); - } - } - else { - callback = new WSPasswordCallback(username, WSPasswordCallback.UNKNOWN); - callback.setPassword(securementPassword); - } - return callback; - } - @Override public String getPassword(Object msgContext) { return securementPassword; @@ -172,18 +112,11 @@ class Wss4jHandler extends WSHandler { } @Override - protected void doSenderAction(int doAction, Document doc, RequestData reqData, Vector actions, boolean isRequest) - throws WSSecurityException { + protected void doSenderAction(int doAction, + Document doc, + RequestData reqData, + List actions, + boolean isRequest) throws WSSecurityException { super.doSenderAction(doAction, doc, reqData, actions, isRequest); } - - @Override - protected boolean verifyTimestamp(Timestamp timestamp, int timeToLive) throws WSSecurityException { - return super.verifyTimestamp(timestamp, timeToLive); - } - - @Override - protected boolean verifyTrust(X509Certificate cert, RequestData reqData) throws WSSecurityException { - return super.verifyTrust(cert, reqData); - } } diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java index f27c210a..97318739 100755 --- a/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java +++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java @@ -19,7 +19,8 @@ package org.springframework.ws.soap.security.wss4j; import java.io.IOException; import java.security.Principal; import java.security.cert.X509Certificate; -import java.util.Vector; +import java.util.ArrayList; +import java.util.List; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; @@ -49,6 +50,9 @@ import org.apache.ws.security.handler.WSHandlerConstants; import org.apache.ws.security.handler.WSHandlerResult; import org.apache.ws.security.message.token.Timestamp; 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.TimestampValidator; import org.w3c.dom.Document; /** @@ -88,7 +92,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl private String securementActions; - private Vector securementActionsVector; + private List securementActionsVector; private String securementUsername; @@ -98,7 +102,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl private String validationActions; - private Vector validationActionsVector; + private List validationActionsVector; private String validationActor; @@ -118,11 +122,17 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl private final Wss4jHandler handler = new Wss4jHandler(); - private final WSSecurityEngine securityEngine = WSSecurityEngine.getInstance(); + private final WSSecurityEngine securityEngine = new WSSecurityEngine(); + + private boolean enableRevocation; + + private boolean bspCompliant; + + private boolean securementUseDerivedKey; public void setSecurementActions(String securementActions) { this.securementActions = securementActions; - securementActionsVector = new Vector(); + securementActionsVector = new ArrayList(); try { securementAction = WSSecurityUtil.decodeAction(securementActions, securementActionsVector); } @@ -142,24 +152,6 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl handler.setOption(WSHandlerConstants.ACTOR, securementActor); } - /** - * Sets the {@link org.apache.ws.security.WSPasswordCallback} handler to use when securing messages. - * - * @see #setSecurementCallbackHandlers(CallbackHandler[]) - */ - public void setSecurementCallbackHandler(CallbackHandler securementCallbackHandler) { - handler.setSecurementCallbackHandler(securementCallbackHandler); - } - - /** - * Sets the {@link org.apache.ws.security.WSPasswordCallback} handlers to use when securing messages. - * - * @see #setSecurementCallbackHandler(CallbackHandler) - */ - public void setSecurementCallbackHandlers(CallbackHandler[] securementCallbackHandler) { - handler.setSecurementCallbackHandler(new CallbackHandlerChain(securementCallbackHandler)); - } - public void setSecurementEncryptionCrypto(Crypto securementEncryptionCrypto) { handler.setSecurementEncryptionCrypto(securementEncryptionCrypto); } @@ -354,6 +346,13 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl this.securementTimeToLive = securementTimeToLive; } + /** + * Enables the derivation of keys as per the UsernameTokenProfile 1.1 spec. Default is {@code true}. + */ + public void setSecurementUseDerivedKey(boolean securementUseDerivedKey) { + this.securementUseDerivedKey = securementUseDerivedKey; + } + /** Sets the server-side time to live */ public void setValidationTimeToLive(int validationTimeToLive) { if (validationTimeToLive <= 0) { @@ -362,19 +361,11 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl this.validationTimeToLive = validationTimeToLive; } - /** Sets the server-side time to live - * @deprecated Use {@link #setValidationTimeToLive(int)} instead. - */ - @Deprecated - public void setTimeToLive(int timeToLive) { - setValidationTimeToLive(timeToLive); - } - /** Sets the validation actions to be executed by the interceptor. */ public void setValidationActions(String actions) { this.validationActions = actions; try { - validationActionsVector = new Vector(); + validationActionsVector = new ArrayList(); validationAction = WSSecurityUtil.decodeAction(actions, validationActionsVector); } catch (WSSecurityException ex) { @@ -464,6 +455,20 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl wssConfig = config; } + /** + * Set whether to enable CRL checking or not when verifying trust in a certificate. + */ + public void setEnableRevocation(boolean enableRevocation) { + this.enableRevocation = enableRevocation; + } + + /** + * Set the WS-I Basic Security Profile compliance mode. Default is {@code true}. + */ + public void setBspCompliant(boolean bspCompliant) { + this.bspCompliant = bspCompliant; + } + public void afterPropertiesSet() throws Exception { Assert.isTrue(validationActions != null || securementActions != null, "validationActions or securementActions are required"); @@ -481,6 +486,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl // allow for qualified password types for .Net interoperability securityEngine.getWssConfig().setAllowNamespaceQualifiedPasswordTypes(true); + securityEngine.getWssConfig().setWsiBSPCompliant(bspCompliant); } @Override @@ -500,7 +506,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl // action, we need to pass an empty securementActionsVector to avoid // NPE if (securementAction == WSConstants.NO_SECURITY) { - securementActionsVector = new Vector(0); + securementActionsVector = new ArrayList(0); } handler.doSenderAction(securementAction, envelopeAsDocument, requestData, securementActionsVector, false); @@ -532,6 +538,8 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl } requestData.setTimeToLive(securementTimeToLive); + + requestData.setUseDerivedKey(securementUseDerivedKey); requestData.setWssConfig(wssConfig); @@ -555,7 +563,7 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl // Header processing try { - Vector results = securityEngine + List results = securityEngine .processSecurityHeader(envelopeAsDocument, validationActor, validationCallbackHandler, validationSignatureCrypto, validationDecryptionCrypto); @@ -588,13 +596,15 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl /** * Checks whether the received headers match the configured validation actions. Subclasses could override this method * for custom verification behavior. + * + * * @param results the results of the validation function - * @param validationActionsVector the decoded validation actions + * @param validationActions the decoded validation actions * @throws Wss4jSecurityValidationException if the results are deemed invalid */ - protected void checkResults(Vector results, Vector validationActionsVector) + protected void checkResults(List results, List validationActions) throws Wss4jSecurityValidationException { - if (!handler.checkReceiverResultsAnyOrder(results, validationActionsVector)) { + if (!handler.checkReceiverResultsAnyOrder(results, validationActions)) { throw new Wss4jSecurityValidationException("Security processing failed (actions mismatch)"); } } @@ -604,10 +614,10 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl * Confirmation require this. */ @SuppressWarnings("unchecked") - private void updateContextWithResults(MessageContext messageContext, Vector results) { - Vector handlerResults; - if ((handlerResults = (Vector) messageContext.getProperty(WSHandlerConstants.RECV_RESULTS)) == null) { - handlerResults = new Vector(); + private void updateContextWithResults(MessageContext messageContext, List results) { + List handlerResults; + if ((handlerResults = (List) messageContext.getProperty(WSHandlerConstants.RECV_RESULTS)) == null) { + handlerResults = new ArrayList(); messageContext.setProperty(WSHandlerConstants.RECV_RESULTS, handlerResults); } WSHandlerResult rResult = new WSHandlerResult(validationActor, results); @@ -616,35 +626,47 @@ public class Wss4jSecurityInterceptor extends AbstractWsSecurityInterceptor impl } /** Verifies the trust of a certificate. */ - protected void verifyCertificateTrust(Vector results) throws WSSecurityException { - RequestData requestData = new RequestData(); - requestData.setSigCrypto(validationSignatureCrypto); + protected void verifyCertificateTrust(List results) throws WSSecurityException { WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN); if (actionResult != null) { - X509Certificate returnCert = (X509Certificate) actionResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE) - ; - if (!handler.verifyTrust(returnCert, requestData)) { - throw new Wss4jSecurityValidationException("The certificate used for the signature is not trusted"); - } + X509Certificate returnCert = + (X509Certificate) actionResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE); + Credential credential = new Credential(); + credential.setCertificates(new X509Certificate[] { returnCert}); + + RequestData requestData = new RequestData(); + requestData.setSigCrypto(validationSignatureCrypto); + requestData.setEnableRevocation(enableRevocation); + + SignatureTrustValidator validator = new SignatureTrustValidator(); + validator.validate(credential, requestData); } } /** Verifies the timestamp. */ - protected void verifyTimestamp(Vector results) throws WSSecurityException { + protected void verifyTimestamp(List results) throws WSSecurityException { WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.TS); if (actionResult != null) { Timestamp timestamp = (Timestamp) actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP); if (timestamp != null && timestampStrict) { - if (!handler.verifyTimestamp(timestamp, validationTimeToLive)) { - throw new Wss4jSecurityValidationException("Invalid timestamp : " + timestamp.getID()); - } + Credential credential = new Credential(); + credential.setTimestamp(timestamp); + + RequestData requestData = new RequestData(); + WSSConfig config = new WSSConfig(); + config.setTimeStampTTL(validationTimeToLive); + config.setTimeStampStrict(timestampStrict); + requestData.setWssConfig(config); + + TimestampValidator validator = new TimestampValidator(); + validator.validate(credential, requestData); } } } - private void processPrincipal(Vector results) { + private void processPrincipal(List results) { WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.UT); if (actionResult != null) { diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/AbstractWsPasswordCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/AbstractWsPasswordCallbackHandler.java index b30a0da5..99100575 100644 --- a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/AbstractWsPasswordCallbackHandler.java +++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/AbstractWsPasswordCallbackHandler.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2012 the original author or authors. * * Licensed 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 + * 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, @@ -20,11 +20,11 @@ import java.io.IOException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.UnsupportedCallbackException; -import org.apache.ws.security.WSPasswordCallback; - import org.springframework.ws.soap.security.callback.AbstractCallbackHandler; import org.springframework.ws.soap.security.callback.CleanupCallback; +import org.apache.ws.security.WSPasswordCallback; + /** * Abstract base class for {@link javax.security.auth.callback.CallbackHandler} implementations that handle {@link * WSPasswordCallback} callbacks. @@ -56,20 +56,14 @@ public abstract class AbstractWsPasswordCallbackHandler extends AbstractCallback case WSPasswordCallback.SIGNATURE: handleSignature(passwordCallback); break; - case WSPasswordCallback.KEY_NAME: - handleKeyName(passwordCallback); - break; - case WSPasswordCallback.USERNAME_TOKEN_UNKNOWN: - handleUsernameTokenUnknown(passwordCallback); - break; case WSPasswordCallback.SECURITY_CONTEXT_TOKEN: handleSecurityContextToken(passwordCallback); break; case WSPasswordCallback.CUSTOM_TOKEN: handleCustomToken(passwordCallback); break; - case WSPasswordCallback.ENCRYPTED_KEY_TOKEN: - handleEncryptedKeyToken(callback); + case WSPasswordCallback.SECRET_KEY: + handleSecretKey(passwordCallback); break; default: throw new UnsupportedCallbackException(callback, @@ -91,7 +85,7 @@ public abstract class AbstractWsPasswordCallbackHandler extends AbstractCallback * Invoked when the callback has a {@link WSPasswordCallback#DECRYPT} usage. *

* This method is invoked when WSS4J needs a password to get the private key of the {@link - * WSPasswordCallback#getIdentifer() identifier} (username) from the keystore. WSS4J uses this private key to + * WSPasswordCallback#getIdentifier() identifier} (username) from the keystore. WSS4J uses this private key to * decrypt the session (symmetric) key. Because the encryption method uses the public key to encrypt the session key * it needs no password (a public key is usually not protected by a password). *

@@ -116,7 +110,7 @@ public abstract class AbstractWsPasswordCallbackHandler extends AbstractCallback * Invoked when the callback has a {@link WSPasswordCallback#SIGNATURE} usage. *

* This method is invoked when WSS4J needs the password to get the private key of the {@link - * WSPasswordCallback#getIdentifer() identifier} (username) from the keystore. WSS4J uses this private key to + * WSPasswordCallback#getIdentifier() identifier} (username) from the keystore. WSS4J uses this private key to * produce a signature. The signature verfication uses the public key to verfiy the signature. *

* Default implementation throws an {@link UnsupportedCallbackException}. @@ -125,33 +119,6 @@ public abstract class AbstractWsPasswordCallbackHandler extends AbstractCallback throw new UnsupportedCallbackException(callback); } - /** - * Invoked when the callback has a {@link WSPasswordCallback#KEY_NAME} usage. - *

- * This method is invoked when WSS4J needs the key associated with the {@link WSPasswordCallback#getIdentifer() - * identifier}. WSS4J uses this key to encrypt or decrypt parts of the SOAP request. Note, the key must match the - * symmetric encryption/decryption algorithm specified (refer to {@link org.apache.ws.security.handler.WSHandlerConstants#ENC_SYM_ALGO}). - *

- * Default implementation throws an {@link UnsupportedCallbackException}. - */ - protected void handleKeyName(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException { - throw new UnsupportedCallbackException(callback); - } - - /** - * Invoked when the callback has a {@link WSPasswordCallback#USERNAME_TOKEN_UNKNOWN} usage. - *

- * This method is invoked for a not specified password type or a plain text password type. Only the {@link - * WSPasswordCallback#getPassword() password} is set. The callback class now may check if the username and password - * match. If they don't match, the subclass should throw an exception. - *

- * Default implementation throws an {@link UnsupportedCallbackException}. - */ - protected void handleUsernameTokenUnknown(WSPasswordCallback callback) - throws IOException, UnsupportedCallbackException { - throw new UnsupportedCallbackException(callback); - } - /** * Invoked when the callback has a {@link WSPasswordCallback#SECURITY_CONTEXT_TOKEN} usage. *

@@ -174,11 +141,11 @@ public abstract class AbstractWsPasswordCallbackHandler extends AbstractCallback } /** - * Invoked when the callback has a {@link WSPasswordCallback#ENCRYPTED_KEY_TOKEN} usage. + * Invoked when the callback has a {@link WSPasswordCallback#SECRET_KEY} usage. *

* Default implementation throws an {@link UnsupportedCallbackException}. */ - protected void handleEncryptedKeyToken(Callback callback) throws IOException, UnsupportedCallbackException { + protected void handleSecretKey(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException { throw new UnsupportedCallbackException(callback); } diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandler.java index 8535ae67..9de42a06 100644 --- a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandler.java +++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandler.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2012 the original author or authors. * * Licensed 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 + * 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, @@ -23,12 +23,11 @@ import java.security.KeyStore; import javax.crypto.SecretKey; import javax.security.auth.callback.UnsupportedCallbackException; -import org.apache.ws.security.WSPasswordCallback; -import org.apache.ws.security.WSSecurityException; - import org.springframework.beans.factory.InitializingBean; import org.springframework.ws.soap.security.support.KeyStoreUtils; +import org.apache.ws.security.WSPasswordCallback; + /** * Callback handler that uses Java Security KeyStores to handle cryptographic callbacks. Allows for * specific key stores to be set for various cryptographic operations. @@ -87,8 +86,9 @@ public class KeyStoreCallbackHandler extends AbstractWsPasswordCallbackHandler i callback.setPassword(privateKeyPassword); } + @Override - protected void handleKeyName(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException { + protected void handleSecretKey(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException { try { String identifier = callback.getIdentifier(); Key key = keyStore.getKey(identifier, symmetricKeyPassword); @@ -96,11 +96,11 @@ public class KeyStoreCallbackHandler extends AbstractWsPasswordCallbackHandler i callback.setKey(key.getEncoded()); } else { - throw new WSSecurityException("Key [" + key + "] is not a javax.crypto.SecretKey"); + logger.error("Key [" + key + "] is not a javax.crypto.SecretKey"); } } catch (GeneralSecurityException ex) { - throw new WSSecurityException("Could not obtain symmetric key", ex); + logger.error("Could not obtain symmetric key", ex); } } diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimplePasswordValidationCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimplePasswordValidationCallbackHandler.java index 980fcd81..a991594d 100644 --- a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimplePasswordValidationCallbackHandler.java +++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SimplePasswordValidationCallbackHandler.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2012 the original author or authors. * * Licensed 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 + * 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, @@ -26,10 +26,9 @@ import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import org.apache.ws.security.WSPasswordCallback; -import org.apache.ws.security.WSSecurityException; /** - * Simple callback handler that validates passwords agains a in-memory Properties object. Password + * Simple callback handler that validates passwords against a in-memory Properties object. Password * validation is done on a case-sensitive basis. * * @author Tareq Abed Rabbo @@ -65,15 +64,4 @@ public class SimplePasswordValidationCallbackHandler extends AbstractWsPasswordC callback.setPassword(users.get(identifier)); } - @Override - protected void handleUsernameTokenUnknown(WSPasswordCallback callback) - throws IOException, UnsupportedCallbackException { - String identifier = callback.getIdentifier(); - String storedPassword = users.get(identifier); - String givenPassword = callback.getPassword(); - if (storedPassword == null || !storedPassword.equals(givenPassword)) { - throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION); - } - } - } \ No newline at end of file diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringPlainTextPasswordValidationCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringPlainTextPasswordValidationCallbackHandler.java deleted file mode 100644 index 3f57fa93..00000000 --- a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringPlainTextPasswordValidationCallbackHandler.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2005-2010 the original author or authors. - * - * Licensed 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.springframework.ws.soap.security.wss4j.callback; - -import org.apache.ws.security.WSPasswordCallback; -import org.apache.ws.security.WSSecurityException; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.util.Assert; -import org.springframework.ws.soap.security.callback.CleanupCallback; - -import javax.security.auth.callback.UnsupportedCallbackException; -import java.io.IOException; - -/** - * Callback handler that validates a certificate uses an Spring Security AuthenticationManager. Logic based - * on Spring Security's BasicProcessingFilter. - *

- * This handler requires an Spring Security AuthenticationManager to operate. It can be set using the - * authenticationManager property. An Spring Security UsernamePasswordAuthenticationToken is - * created with the username as principal and password as credentials. - * - * @author Arjen Poutsma - * @see org.springframework.security.authentication.UsernamePasswordAuthenticationToken - * @see org.springframework.security.ui.basicauth.BasicProcessingFilter - * @since 1.5.0 - */ -public class SpringPlainTextPasswordValidationCallbackHandler extends AbstractWsPasswordCallbackHandler - implements InitializingBean { - - private AuthenticationManager authenticationManager; - - private boolean ignoreFailure = false; - - /** Sets the Spring Security authentication manager. Required. */ - public void setAuthenticationManager(AuthenticationManager authenticationManager) { - this.authenticationManager = authenticationManager; - } - - public void setIgnoreFailure(boolean ignoreFailure) { - this.ignoreFailure = ignoreFailure; - } - - public void afterPropertiesSet() throws Exception { - Assert.notNull(authenticationManager, "authenticationManager is required"); - } - - @Override - protected void handleCleanup(CleanupCallback callback) throws IOException, UnsupportedCallbackException { - SecurityContextHolder.clearContext(); - } - - @Override - protected void handleUsernameTokenUnknown(WSPasswordCallback callback) - throws IOException, UnsupportedCallbackException { - String identifier = callback.getIdentifier(); - try { - Authentication authResult = authenticationManager - .authenticate(new UsernamePasswordAuthenticationToken(identifier, callback.getPassword())); - if (logger.isDebugEnabled()) { - logger.debug("Authentication success: " + authResult.toString()); - } - SecurityContextHolder.getContext().setAuthentication(authResult); - } - catch (AuthenticationException failed) { - if (logger.isDebugEnabled()) { - logger.debug("Authentication request for user '" + identifier + "' failed: " + failed.toString()); - } - SecurityContextHolder.clearContext(); - if (!ignoreFailure) { - throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION, null, null, failed); - } - } - } -} diff --git a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringDigestPasswordValidationCallbackHandler.java b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringSecurityPasswordValidationCallbackHandler.java similarity index 86% rename from security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringDigestPasswordValidationCallbackHandler.java rename to security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringSecurityPasswordValidationCallbackHandler.java index a9d69633..c81f0608 100644 --- a/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringDigestPasswordValidationCallbackHandler.java +++ b/security/src/main/java/org/springframework/ws/soap/security/wss4j/callback/SpringSecurityPasswordValidationCallbackHandler.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2012 the original author or authors. * * Licensed 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 + * 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, @@ -19,35 +19,32 @@ package org.springframework.ws.soap.security.wss4j.callback; import java.io.IOException; import javax.security.auth.callback.UnsupportedCallbackException; -import org.apache.ws.security.WSPasswordCallback; -import org.apache.ws.security.WSUsernameTokenPrincipal; - import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataAccessException; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserCache; -import org.springframework.security.core.userdetails.cache.NullUserCache; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.core.userdetails.cache.NullUserCache; import org.springframework.util.Assert; import org.springframework.ws.soap.security.callback.CleanupCallback; import org.springframework.ws.soap.security.support.SpringSecurityUtils; +import org.apache.ws.security.WSPasswordCallback; +import org.apache.ws.security.WSUsernameTokenPrincipal; + /** - * Callback handler that validates a password digest using an Spring Security UserDetailsService. Logic - * based on Spring Security's DigestProcessingFilter. + * Callback handler that validates a plain text or digest password using an Spring Security {@code UserDetailsService}. *

- * An Spring Security UserDetailService is used to load UserDetails from. The digest of the + * An Spring Security {@link UserDetailsService} is used to load {@link UserDetails} from. The digest of the * password contained in this details object is then compared with the digest in the message. * * @author Arjen Poutsma - * @see org.springframework.security.core.userdetails.UserDetailsService - * @see org.springframework.security.ui.digestauth.DigestProcessingFilter * @since 1.5.0 */ -public class SpringDigestPasswordValidationCallbackHandler extends AbstractWsPasswordCallbackHandler +public class SpringSecurityPasswordValidationCallbackHandler extends AbstractWsPasswordCallbackHandler implements InitializingBean { private UserCache userCache = new NullUserCache(); diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase.java index ea48269e..63ba9179 100755 --- a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase.java +++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCase.java @@ -19,17 +19,13 @@ package org.springframework.ws.soap.security.wss4j; import java.util.Properties; import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.authentication.TestingAuthenticationToken; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.core.userdetails.memory.InMemoryDaoImpl; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.ws.context.DefaultMessageContext; import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.EndpointInterceptor; import org.springframework.ws.soap.SoapMessage; -import org.springframework.ws.soap.security.wss4j.callback.SpringDigestPasswordValidationCallbackHandler; -import org.springframework.ws.soap.security.wss4j.callback.SpringPlainTextPasswordValidationCallbackHandler; +import org.springframework.ws.soap.security.wss4j.callback.SpringSecurityPasswordValidationCallbackHandler; import org.apache.ws.security.WSConstants; import org.junit.After; @@ -104,28 +100,18 @@ public abstract class Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCa else { interceptor.setSecurementActions(actions); } + SpringSecurityPasswordValidationCallbackHandler callbackHandler = + new SpringSecurityPasswordValidationCallbackHandler(); + InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager(users); + callbackHandler.setUserDetailsService(userDetailsManager); if (digest) { - SpringDigestPasswordValidationCallbackHandler callbackHandler = - new SpringDigestPasswordValidationCallbackHandler(); - InMemoryDaoImpl userDetailsService = new InMemoryDaoImpl(); - userDetailsService.setUserProperties(users); - userDetailsService.afterPropertiesSet(); - callbackHandler.setUserDetailsService(userDetailsService); interceptor.setSecurementPasswordType(WSConstants.PW_DIGEST); - interceptor.setValidationCallbackHandler(callbackHandler); - interceptor.afterPropertiesSet(); } else { - SpringPlainTextPasswordValidationCallbackHandler callbackHandler = - new SpringPlainTextPasswordValidationCallbackHandler(); - Authentication authResult = new TestingAuthenticationToken("Bert", "Ernie"); - expect(authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("Bert", "Ernie"))).andReturn(authResult); - callbackHandler.setAuthenticationManager(authenticationManager); - callbackHandler.afterPropertiesSet(); interceptor.setSecurementPasswordType(WSConstants.PW_TEXT); - interceptor.setValidationCallbackHandler(callbackHandler); - interceptor.afterPropertiesSet(); } + interceptor.setValidationCallbackHandler(callbackHandler); + interceptor.afterPropertiesSet(); replay(authenticationManager); return interceptor; } diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandlerTest.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandlerTest.java index 624de4d5..e7bfd4c7 100644 --- a/security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandlerTest.java +++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/KeyStoreCallbackHandlerTest.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2012 the original author or authors. * * Licensed 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 + * 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, @@ -35,14 +35,14 @@ public class KeyStoreCallbackHandlerTest { @Before public void setUp() throws Exception { callbackHandler = new KeyStoreCallbackHandler(); - callback = new WSPasswordCallback("secretkey", WSPasswordCallback.KEY_NAME); + callback = new WSPasswordCallback("secretkey", WSPasswordCallback.SECRET_KEY); KeyStoreFactoryBean factory = new KeyStoreFactoryBean(); factory.setLocation(new ClassPathResource("private.jks")); factory.setPassword("123456"); factory.setType("JCEKS"); factory.afterPropertiesSet(); - KeyStore keyStore = (KeyStore) factory.getObject(); + KeyStore keyStore = factory.getObject(); callbackHandler.setKeyStore(keyStore); callbackHandler.setSymmetricKeyPassword("123456"); } diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/SpringDigestPasswordValidationCallbackHandlerTest.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/SpringSecurityPasswordValidationCallbackHandlerTest.java similarity index 93% rename from security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/SpringDigestPasswordValidationCallbackHandlerTest.java rename to security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/SpringSecurityPasswordValidationCallbackHandlerTest.java index 9106e1ac..bdb01020 100644 --- a/security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/SpringDigestPasswordValidationCallbackHandlerTest.java +++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/callback/SpringSecurityPasswordValidationCallbackHandlerTest.java @@ -36,9 +36,9 @@ import org.junit.Test; import static org.easymock.EasyMock.*; /** @author tareq */ -public class SpringDigestPasswordValidationCallbackHandlerTest { +public class SpringSecurityPasswordValidationCallbackHandlerTest { - private SpringDigestPasswordValidationCallbackHandler callbackHandler; + private SpringSecurityPasswordValidationCallbackHandler callbackHandler; private SimpleGrantedAuthority grantedAuthority; @@ -48,7 +48,7 @@ public class SpringDigestPasswordValidationCallbackHandlerTest { @Before public void setUp() throws Exception { - callbackHandler = new SpringDigestPasswordValidationCallbackHandler(); + callbackHandler = new SpringSecurityPasswordValidationCallbackHandler(); grantedAuthority = new SimpleGrantedAuthority("ROLE_1"); user = new User("Ernie", "Bert", true, true, true, true, Collections.singleton(grantedAuthority));