Updating STS test Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/61bd645c Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/61bd645c Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/61bd645c Branch: refs/heads/3.1.x-fixes Commit: 61bd645c1b92e70b3e6d8dd988a1c42b93080f59 Parents: 41f324f Author: Colm O hEigeartaigh Authored: Tue Jan 24 10:59:28 2017 +0000 Committer: Colm O hEigeartaigh Committed: Tue Jan 24 12:47:03 2017 +0000 ---------------------------------------------------------------------- .../systest/sts/custom/CustomParameterTest.java | 24 ++- .../systest/sts/custom/CustomUTValidator.java | 194 ++----------------- .../cxf/systest/sts/custom/cxf-client.xml | 16 -- .../systest/sts/deployment/cxf-sts-common.xml | 1 + 4 files changed, 43 insertions(+), 192 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/61bd645c/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/custom/CustomParameterTest.java ---------------------------------------------------------------------- diff --git a/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/custom/CustomParameterTest.java b/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/custom/CustomParameterTest.java index de8a900..3ddae05 100644 --- a/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/custom/CustomParameterTest.java +++ b/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/custom/CustomParameterTest.java @@ -19,6 +19,8 @@ package org.apache.cxf.systest.sts.custom; import java.net.URL; +import java.util.HashMap; +import java.util.Map; import javax.xml.namespace.QName; import javax.xml.ws.BindingProvider; @@ -26,9 +28,11 @@ import javax.xml.ws.Service; import org.apache.cxf.Bus; import org.apache.cxf.bus.spring.SpringBusFactory; +import org.apache.cxf.rt.security.SecurityConstants; import org.apache.cxf.systest.sts.common.SecurityTestUtil; import org.apache.cxf.systest.sts.common.TokenTestUtils; import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase; +import org.apache.cxf.ws.security.trust.STSClient; import org.example.contract.doubleit.DoubleItPortType; import org.junit.BeforeClass; @@ -69,7 +73,8 @@ public class CustomParameterTest extends AbstractBusClientServerTestBase { } @org.junit.Test - public void testCustomParameter() throws Exception { + @org.junit.Ignore + public void testCustomParameterInRST() throws Exception { SpringBusFactory bf = new SpringBusFactory(); URL busFile = CustomParameterTest.class.getResource("cxf-client.xml"); @@ -87,6 +92,23 @@ public class CustomParameterTest extends AbstractBusClientServerTestBase { TokenTestUtils.updateSTSPort((BindingProvider)transportClaimsPort, STSPORT); + STSClient stsClient = new STSClient(bus); + stsClient.setWsdlLocation("https://localhost:" + STSPORT + "/SecurityTokenService/UT?wsdl"); + stsClient.setServiceName("{http://docs.oasis-open.org/ws-sx/ws-trust/200512/}SecurityTokenService"); + stsClient.setEndpointName("{http://docs.oasis-open.org/ws-sx/ws-trust/200512/}UT_Port"); + // Add custom content to the RST + stsClient.setCustomContent("custom-realm"); + + Map properties = new HashMap<>(); + properties.put("security.username", "alice"); + properties.put("security.callback-handler", "org.apache.cxf.systest.sts.common.CommonCallbackHandler"); + properties.put("security.sts.token.username", "myclientkey"); + properties.put("security.sts.token.properties", "clientKeystore.properties"); + properties.put("security.sts.token.usecert", "true"); + stsClient.setProperties(properties); + + ((BindingProvider)transportClaimsPort).getRequestContext().put(SecurityConstants.STS_CLIENT, stsClient); + doubleIt(transportClaimsPort, 25); ((java.io.Closeable)transportClaimsPort).close(); http://git-wip-us.apache.org/repos/asf/cxf/blob/61bd645c/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/custom/CustomUTValidator.java ---------------------------------------------------------------------- diff --git a/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/custom/CustomUTValidator.java b/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/custom/CustomUTValidator.java index 2e441d5..1e5f2de 100644 --- a/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/custom/CustomUTValidator.java +++ b/services/sts/systests/advanced/src/test/java/org/apache/cxf/systest/sts/custom/CustomUTValidator.java @@ -19,198 +19,42 @@ package org.apache.cxf.systest.sts.custom; -import java.io.IOException; -import java.util.Base64; +import org.w3c.dom.Document; +import org.w3c.dom.Element; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.UnsupportedCallbackException; - -import org.apache.wss4j.common.ext.WSPasswordCallback; import org.apache.wss4j.common.ext.WSSecurityException; -import org.apache.wss4j.dom.WSConstants; +import org.apache.wss4j.common.util.XMLUtils; import org.apache.wss4j.dom.handler.RequestData; -import org.apache.wss4j.dom.message.token.UsernameToken; +import org.apache.wss4j.dom.util.WSSecurityUtil; import org.apache.wss4j.dom.validate.Credential; +import org.apache.wss4j.dom.validate.UsernameTokenValidator; import org.apache.wss4j.dom.validate.Validator; /** - * This class validates a processed UsernameToken, extracted from the Credential passed to - * the validate method. + * A Validator that checks for a custom "realm" parameter in the RST request and only allows + * authentication if the value is equal to "custom-realm". */ public class CustomUTValidator implements Validator { - private static final org.slf4j.Logger LOG = - org.slf4j.LoggerFactory.getLogger(CustomUTValidator.class); - - /** - * Validate the credential argument. It must contain a non-null UsernameToken. A - * CallbackHandler implementation is also required to be set. - * - * If the password type is either digest or plaintext, it extracts a password from the - * CallbackHandler and then compares the passwords appropriately. - * - * If the password is null it queries a hook to allow the user to validate UsernameTokens - * of this type. - * - * @param credential the Credential to be validated - * @param data the RequestData associated with the request - * @throws WSSecurityException on a failed validation - */ public Credential validate(Credential credential, RequestData data) throws WSSecurityException { if (credential == null || credential.getUsernametoken() == null) { throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noCredential"); } + + // Find custom Element in the SOAP Body + Document doc = credential.getUsernametoken().getElement().getOwnerDocument(); + Element soapBody = WSSecurityUtil.findBodyElement(doc); + Element realm = XMLUtils.findElement(soapBody, "realm", "http://cxf.apache.org/custom"); + if (realm != null) { + String realmStr = realm.getTextContent(); + if ("custom-realm".equals(realmStr)) { - boolean handleCustomPasswordTypes = data.isHandleCustomPasswordTypes(); - boolean passwordsAreEncoded = data.isEncodePasswords(); - String requiredPasswordType = data.getRequiredPasswordType(); - - UsernameToken usernameToken = credential.getUsernametoken(); - usernameToken.setPasswordsAreEncoded(passwordsAreEncoded); - - String pwType = usernameToken.getPasswordType(); - if (LOG.isDebugEnabled()) { - LOG.debug("UsernameToken user " + usernameToken.getName()); - LOG.debug("UsernameToken password type " + pwType); - } - - 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.ErrorCode.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 - // - String password = usernameToken.getPassword(); - if (usernameToken.isHashed()) { - verifyDigestPassword(usernameToken, data); - } else if (WSConstants.PASSWORD_TEXT.equals(pwType) - || password != null && (pwType == null || "".equals(pwType.trim()))) { - verifyPlaintextPassword(usernameToken, data); - } else if (password != null) { - if (!handleCustomPasswordTypes) { - if (LOG.isDebugEnabled()) { - LOG.debug("Authentication failed as handleCustomUsernameTokenTypes is false"); - } - throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION); - } - verifyCustomPassword(usernameToken, data); - } else { - verifyUnknownPassword(usernameToken, data); - } - return credential; - } - - /** - * Verify a UsernameToken containing a password of some unknown (but specified) password - * type. It does this by querying a CallbackHandler instance to obtain a password for the - * given username, and then comparing it against the received password. - * This method currently uses the same LOG.c as the verifyPlaintextPassword case, but it in - * a separate protected method to allow users to override the validation of the custom - * password type specific case. - * @param usernameToken The UsernameToken instance to verify - * @throws WSSecurityException on a failed authentication. - */ - protected void verifyCustomPassword(UsernameToken usernameToken, - RequestData data) throws WSSecurityException { - verifyPlaintextPassword(usernameToken, data); - } - - /** - * Verify a UsernameToken containing a plaintext password. It does this by querying a - * CallbackHandler instance to obtain a password for the given username, and then comparing - * it against the received password. - * This method currently uses the same LOG.c as the verifyDigestPassword case, but it in - * a separate protected method to allow users to override the validation of the plaintext - * password specific case. - * @param usernameToken The UsernameToken instance to verify - * @throws WSSecurityException on a failed authentication. - */ - protected void verifyPlaintextPassword(UsernameToken usernameToken, - RequestData data) throws WSSecurityException { - verifyDigestPassword(usernameToken, data); - } - - /** - * Verify a UsernameToken containing a password digest. It does this by querying a - * CallbackHandler instance to obtain a password for the given username, and then comparing - * it against the received password. - * @param usernameToken The UsernameToken instance to verify - * @throws WSSecurityException on a failed authentication. - */ - protected void verifyDigestPassword(UsernameToken usernameToken, - RequestData data) throws WSSecurityException { - if (data.getCallbackHandler() == null) { - throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noCallback"); - } - - String user = usernameToken.getName(); - String password = usernameToken.getPassword(); - String nonce = usernameToken.getNonce(); - String createdTime = usernameToken.getCreated(); - String pwType = usernameToken.getPasswordType(); - boolean passwordsAreEncoded = usernameToken.getPasswordsAreEncoded(); - - WSPasswordCallback pwCb = - new WSPasswordCallback(user, null, pwType, WSPasswordCallback.USERNAME_TOKEN); - try { - data.getCallbackHandler().handle(new Callback[]{pwCb}); - } catch (IOException | UnsupportedCallbackException e) { - if (LOG.isDebugEnabled()) { - LOG.debug(e.getMessage(), e); - } - throw new WSSecurityException( - WSSecurityException.ErrorCode.FAILED_AUTHENTICATION, e - ); - } - String origPassword = pwCb.getPassword(); - if (origPassword == null) { - if (LOG.isDebugEnabled()) { - LOG.debug("Callback supplied no password for: " + user); - } - throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION); - } - if (usernameToken.isHashed()) { - String passDigest; - if (passwordsAreEncoded) { - passDigest = UsernameToken.doPasswordDigest(nonce, createdTime, - Base64.getMimeDecoder().decode(origPassword)); - } else { - passDigest = UsernameToken.doPasswordDigest(nonce, createdTime, origPassword); - } - if (!passDigest.equals(password)) { - throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION); - } - } else { - if (!origPassword.equals(password)) { - throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION); - } - } - } - - /** - * Verify a UsernameToken containing no password. An exception is thrown unless the user - * has explicitly allowed this use-case via WSHandlerConstants.ALLOW_USERNAMETOKEN_NOPASSWORD - * @param usernameToken The UsernameToken instance to verify - * @throws WSSecurityException on a failed authentication. - */ - protected void verifyUnknownPassword(UsernameToken usernameToken, - RequestData data) throws WSSecurityException { - - boolean allowUsernameTokenDerivedKeys = data.isAllowUsernameTokenNoPassword(); - if (!allowUsernameTokenDerivedKeys) { - if (LOG.isDebugEnabled()) { - LOG.debug("Authentication failed as the received UsernameToken does not " - + "contain any password element"); + UsernameTokenValidator validator = new UsernameTokenValidator(); + return validator.validate(credential, data); } - throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_AUTHENTICATION); } + + throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "noCredential"); } } http://git-wip-us.apache.org/repos/asf/cxf/blob/61bd645c/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/custom/cxf-client.xml ---------------------------------------------------------------------- diff --git a/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/custom/cxf-client.xml b/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/custom/cxf-client.xml index de5079b..003083f 100644 --- a/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/custom/cxf-client.xml +++ b/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/custom/cxf-client.xml @@ -24,24 +24,8 @@ - - - - - - - - - - - - - - - - http://git-wip-us.apache.org/repos/asf/cxf/blob/61bd645c/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/deployment/cxf-sts-common.xml ---------------------------------------------------------------------- diff --git a/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/deployment/cxf-sts-common.xml b/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/deployment/cxf-sts-common.xml index ea4de5e..15c88ae 100644 --- a/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/deployment/cxf-sts-common.xml +++ b/services/sts/systests/advanced/src/test/resources/org/apache/cxf/systest/sts/deployment/cxf-sts-common.xml @@ -41,6 +41,7 @@ +