You are viewing a plain text version of this content. The canonical link for it is here.
Posted to wss4j-dev@ws.apache.org by co...@apache.org on 2009/05/06 11:59:46 UTC
svn commit: r772125 - in /webservices/wss4j/trunk:
src/org/apache/ws/security/ src/org/apache/ws/security/action/
src/org/apache/ws/security/message/ src/org/apache/ws/security/message/token/
src/org/apache/ws/security/processor/ test/wssec/
Author: coheigea
Date: Wed May 6 09:59:44 2009
New Revision: 772125
URL: http://svn.apache.org/viewvc?rev=772125&view=rev
Log:
[WSS-183] - Change the UsernameTokenProcessor to validate plaintext passwords
- Note that Callbacks must still throw an exception for cases other than USERNAME_TOKEN to avoid security holes.
Modified:
webservices/wss4j/trunk/src/org/apache/ws/security/WSPasswordCallback.java
webservices/wss4j/trunk/src/org/apache/ws/security/action/UsernameTokenAction.java
webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecUsernameToken.java
webservices/wss4j/trunk/src/org/apache/ws/security/message/token/UsernameToken.java
webservices/wss4j/trunk/src/org/apache/ws/security/processor/UsernameTokenProcessor.java
webservices/wss4j/trunk/test/wssec/TestWSSecurityNew5.java
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/WSPasswordCallback.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/WSPasswordCallback.java?rev=772125&r1=772124&r2=772125&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/WSPasswordCallback.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/WSPasswordCallback.java Wed May 6 09:59:44 2009
@@ -53,12 +53,11 @@
* 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}).</li>
- * <li><code>USERNAME_TOKEN_UNKNOWN</code> - either an not specified
- * password type or a password type passwordText. In these both cases <b>only</b>
- * the password variable is <b>set</b>. The callback class now may check if
- * the username and password match. If they don't match the callback class must
- * throw an exception. The exception can be a UnsupportedCallbackException or
- * an IOException.</li>
+ * <li><code>USERNAME_TOKEN_UNKNOWN</code> - A not specified password type.
+ * In this case <b>only</b> the password variable is <b>set</b>. The callback
+ * class now may check if the username and password match. If they don't match
+ * the callback class must throw an exception. The exception can be a
+ * UnsupportedCallbackException or an IOException.</li>
* <li><code>SECURITY_CONTEXT_TOKEN</code> - need the key to to be associated
* with a <code>wsc:SecurityContextToken</code>.</li>
* </ul>
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/action/UsernameTokenAction.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/action/UsernameTokenAction.java?rev=772125&r1=772124&r2=772125&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/action/UsernameTokenAction.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/action/UsernameTokenAction.java Wed May 6 09:59:44 2009
@@ -28,16 +28,19 @@
import org.w3c.dom.Document;
public class UsernameTokenAction implements Action {
+
public void execute(WSHandler handler, int actionToDo, Document doc, RequestData reqData)
- throws WSSecurityException {
-
- // Always call the callback for the username. We mis-use the configured password callback class and callback methods for this.
- String providedUsername = reqData.getUsername();
- WSPasswordCallback callbackData = handler.getPassword(reqData.getUsername(),
- actionToDo,
- WSHandlerConstants.PW_CALLBACK_CLASS,
- WSHandlerConstants.PW_CALLBACK_REF, reqData);
- providedUsername = callbackData.getIdentifier();
+ throws WSSecurityException {
+
+ WSPasswordCallback callbackData =
+ handler.getPassword(
+ reqData.getUsername(),
+ actionToDo,
+ WSHandlerConstants.PW_CALLBACK_CLASS,
+ WSHandlerConstants.PW_CALLBACK_REF,
+ reqData
+ );
+ String providedUsername = callbackData.getIdentifier();
String password = callbackData.getPassword();
WSSecUsernameToken builder = new WSSecUsernameToken();
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecUsernameToken.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecUsernameToken.java?rev=772125&r1=772124&r2=772125&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecUsernameToken.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSSecUsernameToken.java Wed May 6 09:59:44 2009
@@ -35,7 +35,6 @@
*
* @author Werner Dittmann (werner@apache.org).
*/
-
public class WSSecUsernameToken extends WSSecBase {
private static Log log = LogFactory.getLog(WSSecUsernameToken.class.getName());
@@ -48,11 +47,6 @@
private byte[] saltValue;
private int iteration = UsernameToken.DEFAULT_ITERATION;
- /**
- * Constructor.
- */
- public WSSecUsernameToken() {
- }
/**
* Defines how to construct the password element of the
@@ -241,6 +235,6 @@
* @return the Username Token element
*/
public Element getUsernameTokenElement() {
- return this.ut.getElement();
+ return ut.getElement();
}
}
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/token/UsernameToken.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/message/token/UsernameToken.java?rev=772125&r1=772124&r2=772125&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/token/UsernameToken.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/token/UsernameToken.java Wed May 6 09:59:44 2009
@@ -203,12 +203,12 @@
elementPassword.appendChild(doc.createTextNode(""));
element.appendChild(elementPassword);
- hashed = false;
passwordType = pwType;
if (passwordType.equals(WSConstants.PASSWORD_DIGEST)) {
- hashed = true;
addNonce(doc);
addCreated(milliseconds, doc);
+ } else {
+ hashed = false;
}
}
}
@@ -287,7 +287,7 @@
doc.createElementNS(
WSConstants.WSSE11_NS, WSConstants.WSSE11_PREFIX + ":" + WSConstants.SALT_LN
);
- WSSecurityUtil.setNamespace(this.element, WSConstants.WSSE11_NS, WSConstants.WSSE11_PREFIX);
+ WSSecurityUtil.setNamespace(element, WSConstants.WSSE11_NS, WSConstants.WSSE11_PREFIX);
elementSalt.appendChild(doc.createTextNode(Base64.encode(saltValue)));
element.appendChild(elementSalt);
return saltValue;
@@ -303,7 +303,7 @@
WSConstants.WSSE11_NS, WSConstants.WSSE11_PREFIX + ":" + WSConstants.ITERATION_LN
);
WSSecurityUtil.setNamespace(element, WSConstants.WSSE11_NS, WSConstants.WSSE11_PREFIX);
- this.elementIteration.appendChild(doc.createTextNode(text));
+ elementIteration.appendChild(doc.createTextNode(text));
element.appendChild(elementIteration);
}
@@ -424,12 +424,13 @@
rawPassword = pwd; // enhancement by Alberto coletti
Text node = getFirstNode(elementPassword);
try {
- if (!hashed) {
- node.setData(pwd);
- elementPassword.setAttribute("Type", WSConstants.PASSWORD_TEXT);
- } else {
+ if (hashed) {
node.setData(doPasswordDigest(getNonce(), getCreated(), pwd));
- elementPassword.setAttribute("Type", WSConstants.PASSWORD_DIGEST);
+ } else {
+ node.setData(pwd);
+ }
+ if (passwordType != null) {
+ elementPassword.setAttribute("Type", passwordType);
}
} catch (Exception e) {
if (DO_DEBUG) {
@@ -491,7 +492,7 @@
*/
private Text getFirstNode(Element e) {
Node node = e.getFirstChild();
- return ((node != null) && node instanceof Text) ? (Text) node : null;
+ return (node instanceof Text) ? (Text) node : null;
}
/**
@@ -527,7 +528,7 @@
* @return a XML string representation
*/
public String toString() {
- return DOM2Writer.nodeToString((Node) this.element);
+ return DOM2Writer.nodeToString((Node)element);
}
/**
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/processor/UsernameTokenProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/processor/UsernameTokenProcessor.java?rev=772125&r1=772124&r2=772125&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/processor/UsernameTokenProcessor.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/processor/UsernameTokenProcessor.java Wed May 6 09:59:44 2009
@@ -53,7 +53,7 @@
}
handleCustomPasswordTypes = wsc.getHandleCustomPasswordTypes();
- Principal lastPrincipalFound = handleUsernameToken((Element) elem, cb);
+ Principal lastPrincipalFound = handleUsernameToken(elem, cb);
returnResults.add(
0,
new WSSecurityEngineResult(WSConstants.UT, lastPrincipalFound, null, null, null)
@@ -62,17 +62,16 @@
}
/**
- * Check the UsernameToken element. Depending on the password type
- * contained in the element the processing differs. If the password type
- * is digested, then retrieve a password from the callback handler and
- * authenticate the UsernameToken here.
+ * Check the UsernameToken element. If the password type is plaintext or digested,
+ * then retrieve a password from the callback handler and authenticate the UsernameToken
+ * here.
* <p/>
- * If the password is in plaintext or any other yet unknown password type
- * then delegate the password validation to the callback class. Note that for unknown
- * password types an exception is thrown if WSSConfig.getHandleCustomPasswordTypes()
- * is set to false (as it is by default). The security engine hands over all necessary
- * data to the callback class via the WSPasswordCallback object. The usage parameter of
- * WSPasswordCallback is set to <code>USERNAME_TOKEN_UNKNOWN</code>.
+ * If the password is any other yet unknown password type then delegate the password
+ * validation to the callback class. Note that for unknown password types an exception
+ * is thrown if WSSConfig.getHandleCustomPasswordTypes() is set to false (as it is
+ * by default). The security engine hands over all necessary data to the callback class
+ * via the WSPasswordCallback object. The usage parameter of WSPasswordCallback is set to
+ * <code>USERNAME_TOKEN_UNKNOWN</code>.
*
* @param token the DOM element that contains the UsernameToken
* @param cb the reference to the callback object
@@ -98,21 +97,17 @@
log.debug("UsernameToken user " + user);
log.debug("UsernameToken password " + password);
}
-
- Callback[] callbacks = new Callback[1];
- String origPassword = null;
-
//
- // If the UsernameToken is hashed, then retrieve the password from the callback handler
- // and compare directly. If the UsernameToken is in plaintext or of some unknown type,
+ // 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()) {
+ if (ut.isHashed() || WSConstants.PASSWORD_TEXT.equals(pwType)
+ || (password != null && pwType == null)) {
WSPasswordCallback pwCb =
- new WSPasswordCallback(user, WSPasswordCallback.USERNAME_TOKEN);
- callbacks[0] = pwCb;
+ new WSPasswordCallback(user, null, pwType, WSPasswordCallback.USERNAME_TOKEN);
try {
- cb.handle(callbacks);
+ cb.handle(new Callback[]{pwCb});
} catch (IOException e) {
if (log.isDebugEnabled()) {
log.debug(e);
@@ -128,7 +123,7 @@
WSSecurityException.FAILED_AUTHENTICATION, null, null, e
);
}
- origPassword = pwCb.getPassword();
+ String origPassword = pwCb.getPassword();
if (log.isDebugEnabled()) {
log.debug("UsernameToken callback password " + origPassword);
}
@@ -138,16 +133,20 @@
}
throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
}
- String passDigest = UsernameToken.doPasswordDigest(nonce, createdTime, origPassword);
- if (!passDigest.equals(password)) {
- throw new WSSecurityException(WSSecurityException.FAILED_AUTHENTICATION);
+ if (ut.isHashed()) {
+ String 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 (!WSConstants.PASSWORD_TEXT.equals(pwType)
- && pwType != null
- && !handleCustomPasswordTypes
- ) {
+ if (pwType != null && !handleCustomPasswordTypes) {
if (log.isDebugEnabled()) {
log.debug("Authentication failed as handleCustomUsernameTokenTypes is false");
}
@@ -155,9 +154,8 @@
}
WSPasswordCallback pwCb = new WSPasswordCallback(user, password,
pwType, WSPasswordCallback.USERNAME_TOKEN_UNKNOWN);
- callbacks[0] = pwCb;
try {
- cb.handle(callbacks);
+ cb.handle(new Callback[]{pwCb});
} catch (IOException e) {
if (log.isDebugEnabled()) {
log.debug(e);
@@ -173,7 +171,7 @@
WSSecurityException.FAILED_AUTHENTICATION, null, null, e
);
}
- origPassword = pwCb.getPassword();
+ String origPassword = pwCb.getPassword();
ut.setRawPassword(origPassword);
}
WSUsernameTokenPrincipal principal = new WSUsernameTokenPrincipal(user, ut.isHashed());
Modified: webservices/wss4j/trunk/test/wssec/TestWSSecurityNew5.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/wssec/TestWSSecurityNew5.java?rev=772125&r1=772124&r2=772125&view=diff
==============================================================================
--- webservices/wss4j/trunk/test/wssec/TestWSSecurityNew5.java (original)
+++ webservices/wss4j/trunk/test/wssec/TestWSSecurityNew5.java Wed May 6 09:59:44 2009
@@ -366,13 +366,42 @@
}
/**
- * Test with a null password type. This will pass as the WSSConfig is configured to
+ * Test with a non-standard token type. This will fail as the default is to reject custom
+ * token types.
+ */
+ public void testUsernameTokenCustomFail2() throws Exception {
+ WSSecUsernameToken builder = new WSSecUsernameToken();
+ builder.setPasswordType("RandomType");
+ builder.setUserInfo("customUser", "randomPass");
+
+ Document doc = unsignedEnvelope.getAsDocument();
+ WSSecHeader secHeader = new WSSecHeader();
+ secHeader.insertSecurityHeader(doc);
+ Document signedDoc = builder.build(doc, secHeader);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Message with UserNameToken PW Text:");
+ String outputString =
+ org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
+ LOG.debug(outputString);
+ }
+ try {
+ verify(signedDoc);
+ throw new Exception("Custom token types are not permitted");
+ } catch (WSSecurityException ex) {
+ assertTrue(ex.getErrorCode() == WSSecurityException.FAILED_AUTHENTICATION);
+ // expected
+ }
+ }
+
+ /**
+ * Test with a non-standard password type. This will pass as the WSSConfig is configured to
* handle custom token types.
*/
public void testUsernameTokenCustomPass() throws Exception {
WSSecUsernameToken builder = new WSSecUsernameToken();
- builder.setPasswordType(null);
- builder.setUserInfo("customUser", null);
+ builder.setPasswordType("RandomType");
+ builder.setUserInfo("customUser", "randomPass");
Document doc = unsignedEnvelope.getAsDocument();
WSSecHeader secHeader = new WSSecHeader();
@@ -380,7 +409,7 @@
Document signedDoc = builder.build(doc, secHeader);
if (LOG.isDebugEnabled()) {
- LOG.debug("Message with UserNameToken PW Text:");
+ LOG.debug("Message with UserNameToken PW custom type:");
String outputString =
org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
LOG.debug(outputString);
@@ -525,10 +554,7 @@
} else if (
pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN
) {
- if ("wernerd".equals(pc.getIdentifier())
- && "verySecret".equals(pc.getPassword())) {
- return;
- } else if ("customUser".equals(pc.getIdentifier())) {
+ if ("customUser".equals(pc.getIdentifier())) {
return;
} else {
throw new IOException("Authentication failed");
---------------------------------------------------------------------
To unsubscribe, e-mail: wss4j-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: wss4j-dev-help@ws.apache.org