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 2010/11/30 13:37:27 UTC
svn commit: r1040493 - in /webservices/wss4j/trunk: ./
src/org/apache/ws/security/ src/org/apache/ws/security/handler/
src/org/apache/ws/security/processor/ test/wssec/ xdocs/
Author: coheigea
Date: Tue Nov 30 12:37:26 2010
New Revision: 1040493
URL: http://svn.apache.org/viewvc?rev=1040493&view=rev
Log:
[WSS-255] - Add support for enforcing a Username Token password type
- This can be done by setting WSHandlerConstants.PASSWORD_TYPE_STRICT to "true. - The default value is false.
Added:
webservices/wss4j/trunk/test/wssec/PasswordTypeTest.java
Modified:
webservices/wss4j/trunk/ChangeLog.txt
webservices/wss4j/trunk/pom.xml
webservices/wss4j/trunk/src/org/apache/ws/security/WSSConfig.java
webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java
webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java
webservices/wss4j/trunk/src/org/apache/ws/security/processor/UsernameTokenProcessor.java
webservices/wss4j/trunk/test/wssec/PackageTests.java
webservices/wss4j/trunk/xdocs/index.xml
Modified: webservices/wss4j/trunk/ChangeLog.txt
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/ChangeLog.txt?rev=1040493&r1=1040492&r2=1040493&view=diff
==============================================================================
--- webservices/wss4j/trunk/ChangeLog.txt (original)
+++ webservices/wss4j/trunk/ChangeLog.txt Tue Nov 30 12:37:26 2010
@@ -5,6 +5,21 @@ for a given release.
Portions of this report were generated using the ReleaseNotes facility
in Jira.
+Release 1.5.10
+=============
+
+** Bug
+
+ * [WSS-40] - WSSecurityEngine does not support chained certificates
+
+** Improvement
+
+ * [WSS-238] - Switch to wsse:KeyIdentifier instead of wsse:Reference for SAML references within SOAP:body EncryptedData elements.
+ * [WSS-239] - Need ability to handle password "equivalent" between WSPasswordCallback and UsernameToken when it's binary data
+ * [WSS-247] - Upgrade to XML Security 1.4.4
+ * [WSS-253] - UsernameTokenProcessor logs the password to the log
+
+
Release 1.5.9
=============
Modified: webservices/wss4j/trunk/pom.xml
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/pom.xml?rev=1040493&r1=1040492&r2=1040493&view=diff
==============================================================================
--- webservices/wss4j/trunk/pom.xml (original)
+++ webservices/wss4j/trunk/pom.xml Tue Nov 30 12:37:26 2010
@@ -134,14 +134,14 @@
<Implementation-Title>Apache WSS4J</Implementation-Title>
<Implementation-Vendor>The Apache Software Foundation</Implementation-Vendor>
<Implementation-Vendor-Id>org.apache</Implementation-Vendor-Id>
- <Implementation-Version>${pom.version}</Implementation-Version>
+ <Implementation-Version>${project.version}</Implementation-Version>
<Specification-Title>Apache WSS4J</Specification-Title>
<Specification-Vendor>The Apache Software Foundation</Specification-Vendor>
- <Specification-Version>${pom.version}</Specification-Version>
+ <Specification-Version>${project.version}</Specification-Version>
<Export-Package>
- org.apache.ws.security.*;version="${pom.version}",
- org.apache.ws.axis.security.*;version="${pom.version}",
+ org.apache.ws.security.*;version="${project.version}",
+ org.apache.ws.axis.security.*;version="${project.version}",
</Export-Package>
<Import-Package>
!org.apache.ws.security.*,
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/WSSConfig.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/WSSConfig.java?rev=1040493&r1=1040492&r2=1040493&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/WSSConfig.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/WSSConfig.java Tue Nov 30 12:37:26 2010
@@ -192,6 +192,12 @@ public class WSSConfig {
protected boolean timeStampStrict = true;
/**
+ * If this value is not null, then username token handling will throw an
+ * exception if the password type of the Username Token does not match this value
+ */
+ protected String requiredPasswordType = null;
+
+ /**
* The time in seconds between creation and expiry for a Timestamp. The default
* is 300 seconds (5 minutes).
*/
@@ -439,6 +445,21 @@ public class WSSConfig {
}
/**
+ * @return the required password type when processing a UsernameToken
+ */
+ public String getRequiredPasswordType() {
+ return requiredPasswordType;
+ }
+
+ /**
+ * @param requiredPasswordType The required password type when processing
+ * a Username Token.
+ */
+ public void setRequiredPasswordType(String requiredPasswordType) {
+ this.requiredPasswordType = requiredPasswordType;
+ }
+
+ /**
* @return Returns the TTL of a Timestamp in seconds
*/
public int getTimeStampTTL() {
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java?rev=1040493&r1=1040492&r2=1040493&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandler.java Tue Nov 30 12:37:26 2010
@@ -242,8 +242,6 @@ public abstract class WSHandler {
}
}
-
-
protected void doReceiverAction(int doAction, RequestData reqData)
throws WSSecurityException {
@@ -256,6 +254,10 @@ public abstract class WSHandler {
enableSigConf || ((doAction & WSConstants.SC) != 0)
);
wssConfig.setTimeStampStrict(decodeTimestampStrict(reqData));
+ if (decodePasswordTypeStrict(reqData)) {
+ String passwordType = decodePasswordType(reqData);
+ wssConfig.setRequiredPasswordType(passwordType);
+ }
wssConfig.setTimeStampTTL(decodeTimeToLive(reqData));
wssConfig.setHandleCustomPasswordTypes(decodeCustomPasswordTypes(reqData));
wssConfig.setPasswordsAreEncoded(decodeUseEncodedPasswords(reqData));
@@ -504,7 +506,7 @@ public abstract class WSHandler {
protected void decodeUTParameter(RequestData reqData)
throws WSSecurityException {
Object mc = reqData.getMsgContext();
-
+
String type = getString(WSHandlerConstants.PASSWORD_TYPE, mc);
if (type != null) {
if (WSConstants.PW_TEXT.equals(type)) {
@@ -512,13 +514,12 @@ public abstract class WSHandler {
} else if (WSConstants.PW_DIGEST.equals(type)) {
reqData.setPwType(WSConstants.PASSWORD_DIGEST);
} else if (WSConstants.PW_NONE.equals(type)) {
- // No password requested.
reqData.setPwType(null);
} else {
throw new WSSecurityException("Unknown password type encoding: " + type);
}
}
-
+
String add = getString(WSHandlerConstants.ADD_UT_ELEMENTS, mc);
if (add != null) {
reqData.setUtElements(StringUtil.split(add, ' '));
@@ -678,6 +679,18 @@ public abstract class WSHandler {
return ttl_i;
}
+ protected String decodePasswordType(RequestData reqData) throws WSSecurityException {
+ String type = getString(WSHandlerConstants.PASSWORD_TYPE, reqData.getMsgContext());
+ if (type != null) {
+ if (WSConstants.PW_TEXT.equals(type)) {
+ return WSConstants.PASSWORD_TEXT;
+ } else if (WSConstants.PW_DIGEST.equals(type)) {
+ return WSConstants.PASSWORD_DIGEST;
+ }
+ }
+ return null;
+ }
+
protected boolean decodeMustUnderstand(RequestData reqData)
throws WSSecurityException {
return decodeBooleanConfigValue(
@@ -730,6 +743,13 @@ public abstract class WSHandler {
);
}
+ protected boolean decodePasswordTypeStrict(RequestData reqData)
+ throws WSSecurityException {
+ return decodeBooleanConfigValue(
+ reqData, WSHandlerConstants.PASSWORD_TYPE_STRICT, false
+ );
+ }
+
protected boolean decodeUseSingleCertificate(RequestData reqData)
throws WSSecurityException {
return decodeBooleanConfigValue(
Modified: webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java?rev=1040493&r1=1040492&r2=1040493&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/handler/WSHandlerConstants.java Tue Nov 30 12:37:26 2010
@@ -499,6 +499,15 @@ public class WSHandlerConstants {
public static final String HANDLE_CUSTOM_PASSWORD_TYPES = "handleCustomPasswordTypes";
/**
+ * Set the value of this parameter to true to enable strict Username Token password type
+ * handling (default is false).
+ *
+ * If this parameter is set to true, it throws an exception if the password type of
+ * the Username Token does not match that of the configured PASSWORD_TYPE parameter.
+ */
+ public static final String PASSWORD_TYPE_STRICT = "passwordTypeStrict";
+
+ /**
* This variable controls whether (wsse) namespace qualified password types are
* accepted when processing UsernameTokens.
*
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=1040493&r1=1040492&r2=1040493&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 Tue Nov 30 12:37:26 2010
@@ -48,6 +48,7 @@ public class UsernameTokenProcessor impl
private boolean handleCustomPasswordTypes;
private boolean allowNamespaceQualifiedPasswordTypes;
private boolean passwordsAreEncoded;
+ private WSSConfig wssConfig;
public void handleToken(Element elem, Crypto crypto, Crypto decCrypto, CallbackHandler cb,
WSDocInfo wsDocInfo, List<WSSecurityEngineResult> returnResults, WSSConfig wsc) throws WSSecurityException {
@@ -57,6 +58,7 @@ public class UsernameTokenProcessor impl
handleCustomPasswordTypes = wsc.getHandleCustomPasswordTypes();
allowNamespaceQualifiedPasswordTypes = wsc.getAllowNamespaceQualifiedPasswordTypes();
passwordsAreEncoded = wsc.getPasswordsAreEncoded();
+ wssConfig = wsc;
Principal lastPrincipalFound = handleUsernameToken(elem, cb);
returnResults.add(
@@ -103,6 +105,15 @@ public class UsernameTokenProcessor impl
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,
Modified: webservices/wss4j/trunk/test/wssec/PackageTests.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/wssec/PackageTests.java?rev=1040493&r1=1040492&r2=1040493&view=diff
==============================================================================
--- webservices/wss4j/trunk/test/wssec/PackageTests.java (original)
+++ webservices/wss4j/trunk/test/wssec/PackageTests.java Tue Nov 30 12:37:26 2010
@@ -79,6 +79,7 @@ public class PackageTests extends TestCa
suite.addTestSuite(TestWSSecurityWSS199.class);
suite.addTestSuite(TestWSSecurityWSS234.class);
suite.addTestSuite(TestWSSecurityWSS245.class);
+ suite.addTestSuite(PasswordTypeTest.class);
return suite;
}
Added: webservices/wss4j/trunk/test/wssec/PasswordTypeTest.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/test/wssec/PasswordTypeTest.java?rev=1040493&view=auto
==============================================================================
--- webservices/wss4j/trunk/test/wssec/PasswordTypeTest.java (added)
+++ webservices/wss4j/trunk/test/wssec/PasswordTypeTest.java Tue Nov 30 12:37:26 2010
@@ -0,0 +1,247 @@
+/**
+ * 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 wssec;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSSConfig;
+import org.apache.ws.security.handler.RequestData;
+import org.apache.ws.security.handler.WSHandlerConstants;
+import org.apache.ws.security.message.WSSecUsernameToken;
+import org.apache.ws.security.message.WSSecHeader;
+import org.w3c.dom.Document;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import java.io.IOException;
+
+/**
+ * This is a test for processing a Username Token to enforce either a plaintext or digest
+ * password type. See WSS-255.
+ */
+public class PasswordTypeTest extends TestCase implements CallbackHandler {
+ private static final Log LOG = LogFactory.getLog(PasswordTypeTest.class);
+ private static final String SOAPMSG =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ + "<SOAP-ENV:Envelope "
+ + "xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" "
+ + "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "
+ + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+ + "<SOAP-ENV:Body>"
+ + "<add xmlns=\"http://ws.apache.org/counter/counter_port_type\">"
+ + "<value xmlns=\"\">15</value>"
+ + "</add>"
+ + "</SOAP-ENV:Body>"
+ + "</SOAP-ENV:Envelope>";
+
+ /**
+ * TestWSSecurity constructor
+ *
+ * @param name name of the test
+ */
+ public PasswordTypeTest(String name) {
+ super(name);
+ }
+
+ /**
+ * JUnit suite
+ *
+ * @return a junit test suite
+ */
+ public static Test suite() {
+ return new TestSuite(PasswordTypeTest.class);
+ }
+
+
+ /**
+ * Test that adds a UserNameToken with password Digest to a WS-Security envelope
+ */
+ public void testPasswordDigest() throws Exception {
+ WSSecUsernameToken builder = new WSSecUsernameToken();
+ builder.setUserInfo("wernerd", "verySecret");
+ Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
+ WSSecHeader secHeader = new WSSecHeader();
+ secHeader.insertSecurityHeader(doc);
+ Document signedDoc = builder.build(doc, secHeader);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Message with UserNameToken PW Digest:");
+ String outputString =
+ org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
+ LOG.debug(outputString);
+ }
+ WSSecurityEngine secEngine = new WSSecurityEngine();
+ WSSConfig wssConfig = WSSConfig.getNewInstance();
+
+ //
+ // It should pass with PASSWORD_DIGEST
+ //
+ wssConfig.setRequiredPasswordType(WSConstants.PASSWORD_DIGEST);
+ secEngine.setWssConfig(wssConfig);
+ secEngine.processSecurityHeader(doc, null, this, null);
+
+ //
+ // It should pass with null
+ //
+ wssConfig.setRequiredPasswordType(null);
+ secEngine.setWssConfig(wssConfig);
+ secEngine.processSecurityHeader(doc, null, this, null);
+
+ //
+ // It should fail with PASSWORD_TEXT
+ //
+ try {
+ wssConfig.setRequiredPasswordType(WSConstants.PASSWORD_TEXT);
+ secEngine.setWssConfig(wssConfig);
+ secEngine.processSecurityHeader(doc, null, this, null);
+ fail("Expected failure on the wrong password type");
+ } catch (WSSecurityException ex) {
+ assertTrue(ex.getErrorCode() == WSSecurityException.FAILED_AUTHENTICATION);
+ // expected
+ }
+ }
+
+ /**
+ * Test that adds a UserNameToken with password text to a WS-Security envelope
+ */
+ public void testUsernameTokenText() throws Exception {
+ WSSecUsernameToken builder = new WSSecUsernameToken();
+ builder.setPasswordType(WSConstants.PASSWORD_TEXT);
+ builder.setUserInfo("wernerd", "verySecret");
+ Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
+ 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);
+ }
+ WSSecurityEngine secEngine = new WSSecurityEngine();
+ WSSConfig wssConfig = WSSConfig.getNewInstance();
+
+ //
+ // It should pass with PASSWORD_TEXT
+ //
+ wssConfig.setRequiredPasswordType(WSConstants.PASSWORD_TEXT);
+ secEngine.setWssConfig(wssConfig);
+ secEngine.processSecurityHeader(doc, null, this, null);
+
+ //
+ // It should pass with null
+ //
+ wssConfig.setRequiredPasswordType(null);
+ secEngine.setWssConfig(wssConfig);
+ secEngine.processSecurityHeader(doc, null, this, null);
+
+ //
+ // It should fail with PASSWORD_DIGEST
+ //
+ try {
+ wssConfig.setRequiredPasswordType(WSConstants.PASSWORD_DIGEST);
+ secEngine.setWssConfig(wssConfig);
+ secEngine.processSecurityHeader(doc, null, this, null);
+ fail("Expected failure on the wrong password type");
+ } catch (WSSecurityException ex) {
+ assertTrue(ex.getErrorCode() == WSSecurityException.FAILED_AUTHENTICATION);
+ // expected
+ }
+
+ }
+
+ /**
+ * Test that adds a UserNameToken via WSHandler
+ */
+ public void testUsernameTokenWSHandler() throws Exception {
+ MyHandler handler = new MyHandler();
+ Document doc = SOAPUtil.toSOAPPart(SOAPMSG);
+
+ RequestData reqData = new RequestData();
+ java.util.Map<String, Object> config = new java.util.TreeMap<String, Object>();
+ config.put("password", "verySecret");
+ config.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
+ reqData.setUsername("wernerd");
+ reqData.setMsgContext(config);
+
+ java.util.List<Integer> actions = new java.util.Vector<Integer>();
+ actions.add(new Integer(WSConstants.UT));
+
+ handler.send(WSConstants.UT, doc, reqData, actions, true);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Username Token via WSHandler");
+ String outputString =
+ org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
+ LOG.debug(outputString);
+ }
+
+ //
+ // It should pass even on a different password type, as we haven't set the
+ // processing to be strict
+ //
+ config.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST);
+ reqData.setMsgContext(config);
+ handler.receive(WSConstants.UT, reqData);
+ WSSecurityEngine secEngine = new WSSecurityEngine();
+ secEngine.setWssConfig(reqData.getWssConfig());
+ secEngine.processSecurityHeader(doc, null, this, null);
+
+ //
+ // It should fail on strict password type processing
+ //
+ config.put(WSHandlerConstants.PASSWORD_TYPE_STRICT, "true");
+ reqData.setMsgContext(config);
+ handler.receive(WSConstants.UT, reqData);
+ try {
+ secEngine.processSecurityHeader(doc, null, this, null);
+ fail("Expected failure on the wrong password type");
+ } catch (WSSecurityException ex) {
+ // expected
+ }
+ }
+
+
+ public void handle(Callback[] callbacks)
+ throws IOException, UnsupportedCallbackException {
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof WSPasswordCallback) {
+ WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
+ if (pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN
+ && "wernerd".equals(pc.getIdentifier())) {
+ pc.setPassword("verySecret");
+ } else {
+ throw new IOException("Authentication failed");
+ }
+ } else {
+ throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
+ }
+ }
+ }
+}
Modified: webservices/wss4j/trunk/xdocs/index.xml
URL: http://svn.apache.org/viewvc/webservices/wss4j/trunk/xdocs/index.xml?rev=1040493&r1=1040492&r2=1040493&view=diff
==============================================================================
--- webservices/wss4j/trunk/xdocs/index.xml (original)
+++ webservices/wss4j/trunk/xdocs/index.xml Tue Nov 30 12:37:26 2010
@@ -59,7 +59,7 @@ Certificate Token Profile 1.1</a>
<p style="margin-left: 40px;">You can download the latest version of WSS4J at the following URL:<br/>
<a href="http://www.apache.org/dyn/closer.cgi/ws/wss4j/">http://www.apache.org/dyn/closer.cgi/ws/wss4j/</a>
</p>
- <p style="margin-left: 40px;">The latest release of WSS4J is version 1.5.9.
+ <p style="margin-left: 40px;">The latest release of WSS4J is version 1.5.10.
</p>
</subsection>
<subsection name="WS-Security Features">