This is an automated email from the ASF dual-hosted git repository. robertlazarski pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/axis-axis2-java-rampart.git
commit a41a08e0a38aeb8258404bd98b4aca40efccfb57 Author: Robert Lazarski <robertlazar...@gmail.com> AuthorDate: Tue Nov 5 09:10:16 2024 -1000 RAMPART-205, RAMPART-361, RAMPART-432, RAMPART-435 Add some customization to WSS4J RequestData via optional parameters in Options and RampartConfig --- .../java/org/apache/rampart/RampartEngine.java | 39 ++-- .../org/apache/rampart/RampartMessageData.java | 30 ++- .../rampart/handler/CertificateValidator.java | 40 +++- .../policy/builders/RampartConfigBuilder.java | 55 ++++++ .../apache/rampart/policy/model/RampartConfig.java | 201 +++++++++++++++++++-- .../apache/rampart/saml/SAML1AssertionHandler.java | 4 +- .../apache/rampart/saml/SAML2AssertionHandler.java | 5 +- .../apache/rampart/saml/SAMLAssertionHandler.java | 7 +- .../policy/builders/KerberosConfigBuilderTest.java | 2 +- .../rampart/policy/builders/kerberosConfig.policy | 12 +- .../main/java/org/apache/rahas/RahasConstants.java | 19 +- .../java/org/apache/rahas/client/STSClient.java | 60 +++++- .../org/apache/rahas/impl/util/CommonUtil.java | 40 +++- .../org/apache/rahas/impl/util/SAML2Utils.java | 11 +- .../org/apache/rahas/impl/util/CommonUtilTest.java | 3 +- 15 files changed, 465 insertions(+), 63 deletions(-) diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/RampartEngine.java b/modules/rampart-core/src/main/java/org/apache/rampart/RampartEngine.java index e5bee768..c9564ee5 100644 --- a/modules/rampart-core/src/main/java/org/apache/rampart/RampartEngine.java +++ b/modules/rampart-core/src/main/java/org/apache/rampart/RampartEngine.java @@ -115,6 +115,7 @@ public class RampartEngine { engine.setWssConfig(rmd.getConfig()); RampartConfig rampartConfig = rpd.getRampartConfig(); + RequestData requestData = new RequestData(); if (rampartConfig != null) { WSSConfig config = engine.getWssConfig(); @@ -194,7 +195,25 @@ public class RampartEngine { } engine.setWssConfig(config); - } + requestData.setTimeStampStrict(rampartConfig.isTimeStampStrict()); + requestData.setPrecisionInMilliSeconds(rampartConfig.isDefaultTimestampPrecisionInMs()); + // 1.8.0 and later + requestData.setDisableBSPEnforcement(rampartConfig.isDisableBSPEnforcement()); + requestData.setHandleCustomPasswordTypes(rampartConfig.isHandleCustomPasswordTypes()); + requestData.setAllowNamespaceQualifiedPasswordTypes(rampartConfig.isAllowNamespaceQualifiedPasswordTypes()); + // this is set below + // requestData.setAllowUsernameTokenNoPassword(rampartConfig.isAllowNamespaceQualifiedPasswordTypes()); + requestData.setValidateSamlSubjectConfirmation(rampartConfig.isValidateSamlSubjectConfirmation()); + requestData.setTimeStampFutureTTL(rampartConfig.getTimeStampFutureTTL()); + requestData.setUtTTL(rampartConfig.getUtTTL()); + requestData.setUtFutureTTL(rampartConfig.getUtFutureTTL()); + requestData.setAllowRSA15KeyTransportAlgorithm(rampartConfig.isAllowRSA15KeyTransportAlgorithm()); // backward compatibility as true + + } else { + requestData.setAllowRSA15KeyTransportAlgorithm(true); // backward compatibility + requestData.setValidateSamlSubjectConfirmation(false); // backward compatibility + requestData.setEncodePasswords(false); // default + } ValidatorData data = new ValidatorData(rmd); @@ -231,7 +250,7 @@ public class RampartEngine { Crypto decCrypto = RampartUtil.getEncryptionCrypto(rpd.getRampartConfig(), msgCtx.getAxisService().getClassLoader()); TokenCallbackHandler tokenCallbackHandler = new TokenCallbackHandler(rmd.getTokenStorage(), RampartUtil.getPasswordCB(rmd)); - WSHandlerResult result = processSecurityHeaderWithRSA15(rmd, secHeader, engine, signatureCrypto, decCrypto, tokenCallbackHandler); + WSHandlerResult result = processSecurityHeaderWithRSA15(rmd, secHeader, engine, signatureCrypto, decCrypto, tokenCallbackHandler, requestData); results = result.getResults(); if(rpd.isSymmetricBinding()) { @@ -276,7 +295,8 @@ public class RampartEngine { Date.from(samlAssertionHandler.getDateNotBefore()), Date.from(samlAssertionHandler.getDateNotOnOrAfter())); - token.setSecret(samlAssertionHandler.getAssertionKeyInfoSecret(signatureCrypto, tokenCallbackHandler, Boolean.parseBoolean(rampartConfig.getDisableBSPEnforcement()))); + // FIXME + token.setSecret(samlAssertionHandler.getAssertionKeyInfoSecret(signatureCrypto, tokenCallbackHandler, new RequestData())); store.add(token); } } catch (Exception e) { @@ -372,25 +392,18 @@ public class RampartEngine { } private WSHandlerResult processSecurityHeaderWithRSA15(RampartMessageData rmd, SOAPHeaderBlock secHeader, WSSecurityEngine engine, - Crypto signatureCrypto, Crypto decCrypto, TokenCallbackHandler tokenCallbackHandler) + Crypto signatureCrypto, Crypto decCrypto, TokenCallbackHandler tokenCallbackHandler, + RequestData requestData) throws WSSecurityException, RampartException { RampartPolicyData rpd = rmd.getPolicyData(); - RequestData requestData = new RequestData(); - requestData.setEncodePasswords(false); requestData.setActor(secHeader.getRole()); requestData.setDecCrypto(decCrypto); requestData.setSigVerCrypto(signatureCrypto); requestData.setCallbackHandler(tokenCallbackHandler); - requestData.setAllowRSA15KeyTransportAlgorithm(true); // backward compatibility - requestData.setValidateSamlSubjectConfirmation(false); // backward compatibility - RampartConfig rampartConfig = rpd.getRampartConfig(); - if (rampartConfig != null) { - requestData.setDisableBSPEnforcement(Boolean.parseBoolean(rampartConfig.getDisableBSPEnforcement())); // WSS4J - } - + //wss4j does not allow username tokens with no password per default, see https://issues.apache.org/jira/browse/WSS-420 //configure it to allow them explicitly if at least one username token assertion with no password requirement is found if (!rmd.isInitiator()) { diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/RampartMessageData.java b/modules/rampart-core/src/main/java/org/apache/rampart/RampartMessageData.java index 99eba6af..b19c654d 100644 --- a/modules/rampart-core/src/main/java/org/apache/rampart/RampartMessageData.java +++ b/modules/rampart-core/src/main/java/org/apache/rampart/RampartMessageData.java @@ -360,18 +360,34 @@ public class RampartMessageData { .getRampartConfig().isDefaultTimestampPrecisionInMs(); boolean timestampStrict = this.policyData.getRampartConfig().isTimeStampStrict(); - boolean disableBSPEnforcement = Boolean.parseBoolean(this.policyData.getRampartConfig().getDisableBSPEnforcement()); + // set some vars on WSS4J class RequestData via RamparConfig as desired in + // Jira issues RAMPART-205, RAMPART-361, RAMPART-432, RAMPART-435 + boolean disableBSPEnforcement = this.policyData.getRampartConfig().isDisableBSPEnforcement(); + boolean handleCustomPasswordTypes = this.policyData.getRampartConfig().isHandleCustomPasswordTypes(); + boolean allowNamespaceQualifiedPasswordTypes = this.policyData.getRampartConfig().isAllowNamespaceQualifiedPasswordTypes(); + boolean allowUsernameTokenNoPassword = this.policyData.getRampartConfig().isAllowUsernameTokenNoPassword(); + boolean allowRSA15KeyTransportAlgorithm = this.policyData.getRampartConfig().isAllowRSA15KeyTransportAlgorithm(); + int timeStampFutureTTL = this.policyData.getRampartConfig().getTimeStampFutureTTL(); + int utTTL = this.policyData.getRampartConfig().getUtTTL(); + int utFutureTTL = this.policyData.getRampartConfig().getUtFutureTTL(); // We do not need earlier logic as now WSS4J returns a new instance of WSSConfig, rather // than a singleton instance. Therefore modifying logic as follows, requestData.setTimeStampStrict(timestampStrict); requestData.setPrecisionInMilliSeconds(timestampPrecisionInMilliseconds); - requestData.setDisableBSPEnforcement(disableBSPEnforcement); // WSS4J - - } - - // To handle scenarios where password type is not set by default. - requestData.setHandleCustomPasswordTypes(true); + // 1.8.0 and later + requestData.setDisableBSPEnforcement(disableBSPEnforcement); + requestData.setHandleCustomPasswordTypes(handleCustomPasswordTypes); + requestData.setAllowNamespaceQualifiedPasswordTypes(allowNamespaceQualifiedPasswordTypes); + requestData.setAllowUsernameTokenNoPassword(allowUsernameTokenNoPassword); + requestData.setTimeStampFutureTTL(timeStampFutureTTL); + requestData.setUtTTL(utTTL); + requestData.setUtFutureTTL(utFutureTTL); + requestData.setAllowRSA15KeyTransportAlgorithm(allowRSA15KeyTransportAlgorithm); // backward compatibility as true + } else { + // To handle scenarios where password type is not set by default. + requestData.setHandleCustomPasswordTypes(true); + } if (axisService != null) { this.customClassLoader = axisService.getClassLoader(); diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/handler/CertificateValidator.java b/modules/rampart-core/src/main/java/org/apache/rampart/handler/CertificateValidator.java index 60cde2ee..040974fd 100644 --- a/modules/rampart-core/src/main/java/org/apache/rampart/handler/CertificateValidator.java +++ b/modules/rampart-core/src/main/java/org/apache/rampart/handler/CertificateValidator.java @@ -16,6 +16,9 @@ package org.apache.rampart.handler; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.crypto.Crypto; import org.apache.wss4j.dom.handler.RequestData; @@ -28,6 +31,8 @@ import java.security.cert.X509Certificate; */ public class CertificateValidator extends SignatureTrustValidator { + private static Log log = LogFactory.getLog(CertificateValidator.class); + CertificateValidator() { } @@ -36,17 +41,40 @@ public class CertificateValidator extends SignatureTrustValidator { * Checks the validity of the given certificate. For more info see SignatureTrustValidator.verifyTrustInCert. * @param certificate Certificate to be validated. * @param signatureCrypto Signature crypto instance. - * @param disableBSPEnforcement Disable WSS4J feature + * @param requestData Set optional WSS4J values and pass this Object in * @return true if certificate used in signature is valid. False if it is not valid. * @throws WSSecurityException If an error occurred while trying to access Crypto and Certificate properties. */ - boolean validateCertificate(X509Certificate certificate, Crypto signatureCrypto, boolean disableBSPEnforcement) throws WSSecurityException { + boolean validateCertificate(X509Certificate certificate, Crypto signatureCrypto, RequestData requestData) throws WSSecurityException { X509Certificate[] x509certs = new X509Certificate[1]; x509certs[0] = certificate; - RequestData requestData = new RequestData(); - requestData.setDisableBSPEnforcement(disableBSPEnforcement); // WSS4J - verifyTrustInCerts(x509certs, signatureCrypto, requestData, false); - return false; + try { + verifyTrustInCerts(x509certs, signatureCrypto, requestData, false); + } catch (Exception ex) { + log.error(ex.getMessage(), ex); + return false; + } + return true; } + /** + * Checks the validity of the given certificate. For more info see SignatureTrustValidator.verifyTrustInCert. This method has been deprecated - use the method that passes in org.apache.wss4j.dom.handler.RequestData + * @param certificate Certificate to be validated. + * @param signatureCrypto Signature crypto instance. + * @return true if certificate used in signature is valid. False if it is not valid. + * @throws WSSecurityException If an error occurred while trying to access Crypto and Certificate properties. + */ + @Deprecated + boolean validateCertificate(X509Certificate certificate, Crypto signatureCrypto) throws WSSecurityException { + X509Certificate[] x509certs = new X509Certificate[1]; + x509certs[0] = certificate; + RequestData requestData = new RequestData(); + try { + verifyTrustInCerts(x509certs, signatureCrypto, requestData, false); + } catch (Exception ex) { + log.error(ex.getMessage(), ex); + return false; + } + return true; + } } diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/policy/builders/RampartConfigBuilder.java b/modules/rampart-core/src/main/java/org/apache/rampart/policy/builders/RampartConfigBuilder.java index 627a684e..d2dac421 100644 --- a/modules/rampart-core/src/main/java/org/apache/rampart/policy/builders/RampartConfigBuilder.java +++ b/modules/rampart-core/src/main/java/org/apache/rampart/policy/builders/RampartConfigBuilder.java @@ -171,12 +171,67 @@ public class RampartConfigBuilder implements AssertionBuilder<OMElement> { rampartConfig.setTimeStampStrict(childElement.getText().trim()); } + // 1.8.0 and later childElement = element.getFirstChildWithName(new QName( RampartConfig.NS, RampartConfig.DISABLE_BSP_ENFORCEMENT_LN)); if (childElement != null) { rampartConfig.setDisableBSPEnforcement(childElement.getText().trim()); } + childElement = element.getFirstChildWithName(new QName( + RampartConfig.NS, RampartConfig.ALLOW_USERNAME_TOKEN_NO_PASSWORD_LN)); + if (childElement != null) { + rampartConfig.setAllowUsernameTokenNoPassword(childElement.getText().trim()); + } + + childElement = element.getFirstChildWithName(new QName( + RampartConfig.NS, RampartConfig.TIMESTAMP_FUTURE_TTL_LN)); + if (childElement != null) { + rampartConfig.setTimeStampFutureTTL(childElement.getText().trim()); + } + + childElement = element.getFirstChildWithName(new QName( + RampartConfig.NS, RampartConfig.UT_TTL_LN)); + if (childElement != null) { + rampartConfig.setUtTTL(childElement.getText().trim()); + } + + childElement = element.getFirstChildWithName(new QName( + RampartConfig.NS, RampartConfig.UT_FUTURE_TTL_LN)); + if (childElement != null) { + rampartConfig.setUtFutureTTL(childElement.getText().trim()); + } + + childElement = element.getFirstChildWithName(new QName( + RampartConfig.NS, RampartConfig.HANDLE_CUSTOM_PASSWORD_TYPES_LN)); + if (childElement != null) { + rampartConfig.setHandleCustomPasswordTypes(childElement.getText().trim()); + } + + childElement = element.getFirstChildWithName(new QName( + RampartConfig.NS, RampartConfig.ALLOW_NAMESPACE_QUALIFIED_PASSWORDTYPES_LN)); + if (childElement != null) { + rampartConfig.setAllowNamespaceQualifiedPasswordTypes(childElement.getText().trim()); + } + + childElement = element.getFirstChildWithName(new QName( + RampartConfig.NS, RampartConfig.ENCODE_PASSWORDS_LN)); + if (childElement != null) { + rampartConfig.setEncodePasswords(childElement.getText().trim()); + } + + childElement = element.getFirstChildWithName(new QName( + RampartConfig.NS, RampartConfig.VALIDATE_SAML_SUBJECT_CONFIRMATION_LN)); + if (childElement != null) { + rampartConfig.setValidateSamlSubjectConfirmation(childElement.getText().trim()); + } + + childElement = element.getFirstChildWithName(new QName( + RampartConfig.NS, RampartConfig.ALLOW_RSA15_KEY_TRANSPORT_ALGORITHM_LN)); + if (childElement != null) { + rampartConfig.setAllowRSA15KeyTransportAlgorithm(childElement.getText().trim()); + } + return rampartConfig; } diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/policy/model/RampartConfig.java b/modules/rampart-core/src/main/java/org/apache/rampart/policy/model/RampartConfig.java index 759d96cd..f65a09df 100644 --- a/modules/rampart-core/src/main/java/org/apache/rampart/policy/model/RampartConfig.java +++ b/modules/rampart-core/src/main/java/org/apache/rampart/policy/model/RampartConfig.java @@ -20,6 +20,8 @@ import org.apache.neethi.Assertion; import org.apache.neethi.Constants; import org.apache.neethi.PolicyComponent; +import org.apache.wss4j.dom.handler.RequestData; + import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; @@ -79,8 +81,6 @@ public class RampartConfig implements Assertion { public final static String USER_LN = "user"; - public final static String DISABLE_BSP_ENFORCEMENT_LN = "disableBSPEnforcement"; - public final static String USER_CERT_ALIAS_LN = "userCertAlias"; public final static String ENCRYPTION_USER_LN = "encryptionUser"; @@ -118,6 +118,26 @@ public class RampartConfig implements Assertion { public final static String SSL_CONFIG = "sslConfig"; public final static String KERBEROS_CONFIG = "kerberosConfig"; + + // These constants are 1.8.0 and after + public final static String DISABLE_BSP_ENFORCEMENT_LN = "disableBSPEnforcement"; + + public final static String ALLOW_USERNAME_TOKEN_NO_PASSWORD_LN = "allowUsernameTokenNoPassword"; + + public final static String TIMESTAMP_FUTURE_TTL_LN = "timeStampFutureTTL"; + + public final static String UT_TTL_LN = "utTTL"; + + public final static String UT_FUTURE_TTL_LN = "utFutureTTL"; + + public final static String HANDLE_CUSTOM_PASSWORD_TYPES_LN = "handleCustomPasswordTypes"; + + public final static String ALLOW_NAMESPACE_QUALIFIED_PASSWORDTYPES_LN = "allowNamespaceQualifiedPasswordTypes"; + public final static String ENCODE_PASSWORDS_LN = "encodePasswords"; + + public final static String VALIDATE_SAML_SUBJECT_CONFIRMATION_LN = "validateSamlSubjectConfirmation"; + + public final static String ALLOW_RSA15_KEY_TRANSPORT_ALGORITHM_LN = "allowRSA15KeyTransportAlgorithm"; private String user; @@ -133,8 +153,6 @@ public class RampartConfig implements Assertion { private String rampartConfigCbClass; - private String disableBSPEnforcement; - private CryptoConfig sigCryptoConfig; private CryptoConfig encrCryptoConfig; @@ -168,8 +186,30 @@ public class RampartConfig implements Assertion { this.kerberosConfig = kerberosConfig; } - /*To set timeStampStrict in WSSConfig through rampartConfig - default value is false*/ + /*To set timeStampStrict in WSS4J RequestData through rampartConfig - default value is false*/ private boolean timeStampStrict = false; + + /* As of 1.8.0, the following params can also be overridden to set on RequestData */ + private boolean disableBSPEnforcement = false; + + private boolean allowUsernameTokenNoPassword = false; + + private int timeStampFutureTTL = 60; + + private int utTTL = 300; + + private int utFutureTTL = 60; + + /* WSS4J sets this as false however before 1.8.0 this was hard-coded to true */ + private boolean handleCustomPasswordTypes = true; + + private boolean allowNamespaceQualifiedPasswordTypes = false; + + private boolean encodePasswords = false; + + private boolean validateSamlSubjectConfirmation = false; // backward compatibility + + private boolean allowRSA15KeyTransportAlgorithm = true; // backward compatibility public SSLConfig getSSLConfig() { return sslConfig; @@ -282,17 +322,6 @@ public class RampartConfig implements Assertion { this.userCertAlias = userCertAlias; } - public String getDisableBSPEnforcement() { - if (disableBSPEnforcement == null) { - return "false"; - } - return disableBSPEnforcement; - } - - public void setDisableBSPEnforcement(String disableBSPEnforcement) { - this.disableBSPEnforcement = disableBSPEnforcement; - } - public QName getName() { return new QName(NS, RAMPART_CONFIG_LN); } @@ -383,6 +412,46 @@ public class RampartConfig implements Assertion { writer.writeCharacters(Boolean.toString(isTimeStampStrict())); writer.writeEndElement(); + writer.writeStartElement(NS, TIMESTAMP_FUTURE_TTL_LN); + writer.writeCharacters(Integer.toString(getTimeStampFutureTTL())); + writer.writeEndElement(); + + writer.writeStartElement(NS, UT_TTL_LN); + writer.writeCharacters(Integer.toString(getUtTTL())); + writer.writeEndElement(); + + writer.writeStartElement(NS, UT_FUTURE_TTL_LN); + writer.writeCharacters(Integer.toString(getUtFutureTTL())); + writer.writeEndElement(); + + writer.writeStartElement(NS, DISABLE_BSP_ENFORCEMENT_LN); + writer.writeCharacters(Boolean.toString(isDisableBSPEnforcement())); + writer.writeEndElement(); + + writer.writeStartElement(NS, ALLOW_USERNAME_TOKEN_NO_PASSWORD_LN); + writer.writeCharacters(Boolean.toString(isAllowUsernameTokenNoPassword())); + writer.writeEndElement(); + + writer.writeStartElement(NS, HANDLE_CUSTOM_PASSWORD_TYPES_LN); + writer.writeCharacters(Boolean.toString(isHandleCustomPasswordTypes())); + writer.writeEndElement(); + + writer.writeStartElement(NS, ALLOW_NAMESPACE_QUALIFIED_PASSWORDTYPES_LN); + writer.writeCharacters(Boolean.toString(isAllowNamespaceQualifiedPasswordTypes())); + writer.writeEndElement(); + + writer.writeStartElement(NS, ENCODE_PASSWORDS_LN); + writer.writeCharacters(Boolean.toString(isEncodePasswords())); + writer.writeEndElement(); + + writer.writeStartElement(NS, VALIDATE_SAML_SUBJECT_CONFIRMATION_LN); + writer.writeCharacters(Boolean.toString(isValidateSamlSubjectConfirmation())); + writer.writeEndElement(); + + writer.writeStartElement(NS, ALLOW_RSA15_KEY_TRANSPORT_ALGORITHM_LN); + writer.writeCharacters(Boolean.toString(isAllowRSA15KeyTransportAlgorithm())); + writer.writeEndElement(); + if (getTokenStoreClass() != null) { writer.writeStartElement(NS, TOKEN_STORE_CLASS_LN); writer.writeCharacters(getTokenStoreClass()); @@ -522,4 +591,104 @@ public class RampartConfig implements Assertion { this.timeStampStrict = Boolean.valueOf(timeStampStrict); } + // The vars below are 1.8.0 and after + + public boolean isDisableBSPEnforcement() { + return disableBSPEnforcement; + } + + public void setDisableBSPEnforcement(String disableBSPEnforcement) { + this.disableBSPEnforcement = Boolean.valueOf(disableBSPEnforcement); + } + + public boolean isAllowUsernameTokenNoPassword() { + return allowUsernameTokenNoPassword; + } + + public void setAllowUsernameTokenNoPassword(String allowUsernameTokenNoPassword) { + this.allowUsernameTokenNoPassword = Boolean.valueOf(allowUsernameTokenNoPassword); + } + + public int getTimeStampFutureTTL() { + return timeStampFutureTTL; + } + + public void setTimeStampFutureTTL(String timeStampFutureTTL) { + this.timeStampFutureTTL = Integer.valueOf(timeStampFutureTTL); + } + + public int getUtTTL() { + return utTTL; + } + + public void setUtTTL(String utTTL) { + this.utTTL = Integer.valueOf(utTTL); + } + + public int getUtFutureTTL() { + return utFutureTTL; + } + + public void setUtFutureTTL(String utFutureTTL) { + this.utFutureTTL = Integer.valueOf(utFutureTTL); + } + + public boolean isHandleCustomPasswordTypes() { + return handleCustomPasswordTypes; + } + + public void setHandleCustomPasswordTypes(String handleCustomPasswordTypes) { + this.handleCustomPasswordTypes = Boolean.valueOf(handleCustomPasswordTypes); + } + + public boolean isAllowNamespaceQualifiedPasswordTypes() { + return allowNamespaceQualifiedPasswordTypes; + } + + public void setAllowNamespaceQualifiedPasswordTypes(String allowNamespaceQualifiedPasswordTypes) { + this.allowNamespaceQualifiedPasswordTypes = Boolean.valueOf(allowNamespaceQualifiedPasswordTypes); + } + + public boolean isEncodePasswords() { + return encodePasswords; + } + + public void setEncodePasswords(String encodePasswords) { + this.encodePasswords = Boolean.valueOf(encodePasswords); + } + + public boolean isValidateSamlSubjectConfirmation() { + return validateSamlSubjectConfirmation; + } + + public void setValidateSamlSubjectConfirmation(String validateSamlSubjectConfirmation) { + this.validateSamlSubjectConfirmation = Boolean.valueOf(validateSamlSubjectConfirmation); + } + + public boolean isAllowRSA15KeyTransportAlgorithm() { + return allowRSA15KeyTransportAlgorithm; + } + + public void setAllowRSA15KeyTransportAlgorithm(String allowRSA15KeyTransportAlgorithm) { + this.allowRSA15KeyTransportAlgorithm = Boolean.valueOf(allowRSA15KeyTransportAlgorithm); + } + + // set some vars on WSS4J class RequestData via RamparConfig as desired in + // Jira issues RAMPART-205, RAMPART-361, RAMPART-432, RAMPART-435 + /* + public RequestData getRequestData() { + RequestData requestData = new RequestData(); + requestData.setTimeStampStrict(timeStampStrict); + requestData.setPrecisionInMilliSeconds(isTimestampPrecisionInMs); + // 1.8.0 and later + requestData.setDisableBSPEnforcement(disableBSPEnforcement); + requestData.setHandleCustomPasswordTypes(handleCustomPasswordTypes); + requestData.setAllowNamespaceQualifiedPasswordTypes(allowNamespaceQualifiedPasswordTypes); + requestData.setAllowUsernameTokenNoPassword(allowUsernameTokenNoPassword); + requestData.setTimeStampFutureTTL(timeStampFutureTTL); + requestData.setUtTTL(utTTL); + requestData.setUtFutureTTL(utFutureTTL); + return requestData; + } + */ } diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/saml/SAML1AssertionHandler.java b/modules/rampart-core/src/main/java/org/apache/rampart/saml/SAML1AssertionHandler.java index f73466c0..ad5ba8d1 100644 --- a/modules/rampart-core/src/main/java/org/apache/rampart/saml/SAML1AssertionHandler.java +++ b/modules/rampart-core/src/main/java/org/apache/rampart/saml/SAML1AssertionHandler.java @@ -68,12 +68,10 @@ public class SAML1AssertionHandler extends SAMLAssertionHandler{ } @Override - public byte[] getAssertionKeyInfoSecret(Crypto signatureCrypto, TokenCallbackHandler tokenCallbackHandler, boolean disableBSPEnforcement) throws WSSecurityException { + public byte[] getAssertionKeyInfoSecret(Crypto signatureCrypto, TokenCallbackHandler tokenCallbackHandler, RequestData requestData) throws WSSecurityException { - RequestData requestData = new RequestData(); requestData.setCallbackHandler(tokenCallbackHandler); requestData.setSigVerCrypto(signatureCrypto); - requestData.setDisableBSPEnforcement(disableBSPEnforcement); // WSS4J WSDocInfo docInfo = new WSDocInfo(assertion.getDOM().getOwnerDocument()); // TODO Improve .. // TODO change this to use SAMLAssertion parameter once wss4j conversion is done .... diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/saml/SAML2AssertionHandler.java b/modules/rampart-core/src/main/java/org/apache/rampart/saml/SAML2AssertionHandler.java index 948ad7aa..1c532651 100644 --- a/modules/rampart-core/src/main/java/org/apache/rampart/saml/SAML2AssertionHandler.java +++ b/modules/rampart-core/src/main/java/org/apache/rampart/saml/SAML2AssertionHandler.java @@ -26,6 +26,7 @@ import org.apache.rahas.impl.util.SAML2Utils; import org.apache.rampart.TokenCallbackHandler; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.crypto.Crypto; +import org.apache.wss4j.dom.handler.RequestData; import org.opensaml.saml.saml2.core.Assertion; import org.opensaml.saml.saml2.core.Conditions; import org.opensaml.saml.saml2.core.Subject; @@ -88,10 +89,10 @@ public class SAML2AssertionHandler extends SAMLAssertionHandler{ } - public byte[] getAssertionKeyInfoSecret(Crypto signatureCrypto, TokenCallbackHandler tokenCallbackHandler, boolean disableBSPEnforcement) throws WSSecurityException { + public byte[] getAssertionKeyInfoSecret(Crypto signatureCrypto, TokenCallbackHandler tokenCallbackHandler, RequestData requestData) throws WSSecurityException { // TODO : SAML2KeyInfo element needs to be moved to WSS4J. SAML2KeyInfo saml2KeyInfo = SAML2Utils. - getSAML2KeyInfo(assertion, signatureCrypto, tokenCallbackHandler, disableBSPEnforcement); + getSAML2KeyInfo(assertion, signatureCrypto, tokenCallbackHandler, requestData); return saml2KeyInfo.getSecret(); } diff --git a/modules/rampart-core/src/main/java/org/apache/rampart/saml/SAMLAssertionHandler.java b/modules/rampart-core/src/main/java/org/apache/rampart/saml/SAMLAssertionHandler.java index eca67b43..dccbde66 100644 --- a/modules/rampart-core/src/main/java/org/apache/rampart/saml/SAMLAssertionHandler.java +++ b/modules/rampart-core/src/main/java/org/apache/rampart/saml/SAMLAssertionHandler.java @@ -24,6 +24,7 @@ import org.apache.rahas.TrustException; import org.apache.rampart.TokenCallbackHandler; import org.apache.wss4j.common.ext.WSSecurityException; import org.apache.wss4j.common.crypto.Crypto; +import org.apache.wss4j.dom.handler.RequestData; import java.time.Instant; @@ -76,12 +77,12 @@ public abstract class SAMLAssertionHandler { /** * Gets the secret in assertion. * @param signatureCrypto Signature crypto info, private,public keys. - * @param tokenCallbackHandler The token callback class. TODO Why ? - * @param disableBSPEnforcement Pass the value to WSS4J when creating RequestData + * @param tokenCallbackHandler The token callback class, required for WSS4J processing + * @param requestData Allow customization of the numerous optional WSS4J params * @return Secret as a byte array * @throws WSSecurityException If an error occurred while validating the signature. */ - public abstract byte[] getAssertionKeyInfoSecret(Crypto signatureCrypto, TokenCallbackHandler tokenCallbackHandler, boolean disableBSPEnforcement) + public abstract byte[] getAssertionKeyInfoSecret(Crypto signatureCrypto, TokenCallbackHandler tokenCallbackHandler, RequestData requestData) throws WSSecurityException; /** diff --git a/modules/rampart-core/src/test/java/org/apache/rampart/policy/builders/KerberosConfigBuilderTest.java b/modules/rampart-core/src/test/java/org/apache/rampart/policy/builders/KerberosConfigBuilderTest.java index b0addbfd..a8c12783 100644 --- a/modules/rampart-core/src/test/java/org/apache/rampart/policy/builders/KerberosConfigBuilderTest.java +++ b/modules/rampart-core/src/test/java/org/apache/rampart/policy/builders/KerberosConfigBuilderTest.java @@ -118,4 +118,4 @@ public class KerberosConfigBuilderTest extends TestCase { } } } -} \ No newline at end of file +} diff --git a/modules/rampart-core/src/test/resources/org/apache/rampart/policy/builders/kerberosConfig.policy b/modules/rampart-core/src/test/resources/org/apache/rampart/policy/builders/kerberosConfig.policy index f727eb65..d3ed14b9 100644 --- a/modules/rampart-core/src/test/resources/org/apache/rampart/policy/builders/kerberosConfig.policy +++ b/modules/rampart-core/src/test/resources/org/apache/rampart/policy/builders/kerberosConfig.policy @@ -6,6 +6,16 @@ <rampart:timestampTTL>300</rampart:timestampTTL> <rampart:timestampMaxSkew>300</rampart:timestampMaxSkew> <rampart:timestampStrict>false</rampart:timestampStrict> + <rampart:timeStampFutureTTL>60</rampart:timeStampFutureTTL> + <rampart:utTTL>300</rampart:utTTL> + <rampart:utFutureTTL>60</rampart:utFutureTTL> + <rampart:disableBSPEnforcement>false</rampart:disableBSPEnforcement> + <rampart:allowUsernameTokenNoPassword>false</rampart:allowUsernameTokenNoPassword> + <rampart:handleCustomPasswordTypes>true</rampart:handleCustomPasswordTypes> + <rampart:allowNamespaceQualifiedPasswordTypes>false</rampart:allowNamespaceQualifiedPasswordTypes> + <rampart:encodePasswords>false</rampart:encodePasswords> + <rampart:validateSamlSubjectConfirmation>false</rampart:validateSamlSubjectConfirmation> + <rampart:allowRSA15KeyTransportAlgorithm>true</rampart:allowRSA15KeyTransportAlgorithm> <rampart:nonceLifeTime>300</rampart:nonceLifeTime> <rampart:kerberosConfig> <rampart:jaasContext>alice</rampart:jaasContext> @@ -19,4 +29,4 @@ </rampart:RampartConfig> </wsp:All> </wsp:ExactlyOne> -</wsp:Policy> \ No newline at end of file +</wsp:Policy> diff --git a/modules/rampart-trust/src/main/java/org/apache/rahas/RahasConstants.java b/modules/rampart-trust/src/main/java/org/apache/rahas/RahasConstants.java index 3efead84..056d0402 100644 --- a/modules/rampart-trust/src/main/java/org/apache/rahas/RahasConstants.java +++ b/modules/rampart-trust/src/main/java/org/apache/rahas/RahasConstants.java @@ -145,6 +145,23 @@ public class RahasConstants { public static final String SAML_NS = "urn:oasis:names:tc:SAML:1.0:assertion"; public static final String AUTHENTICATION_METHOD_PASSWORD = "urn:oasis:names:tc:SAML:1.0:am:password"; - // WSS4J, see RAMPART-432 + // set some vars on WSS4J class RequestData via Rahas as desired in + // Jira issues RAMPART-205, RAMPART-361, RAMPART-432, RAMPART-435 public static final String DISABLE_BSP_ENFORCEMENT = "disableBSPEnforcement"; + public final static String ALLOW_USERNAME_TOKEN_NO_PASSWORD = "allowUsernameTokenNoPassword"; + + public final static String TIMESTAMP_FUTURE_TTL = "timeStampFutureTTL"; + + public final static String UT_TTL = "utTTL"; + + public final static String UT_FUTURE_TTL = "utFutureTTL"; + + public final static String HANDLE_CUSTOM_PASSWORD_TYPES = "handleCustomPasswordTypes"; + + public final static String ALLOW_NAMESPACE_QUALIFIED_PASSWORDTYPES = "allowNamespaceQualifiedPasswordTypes"; + public final static String ENCODE_PASSWORDS = "encodePasswords"; + + public final static String VALIDATE_SAML_SUBJECT_CONFIRMATION = "validateSamlSubjectConfirmation"; + + public final static String ALLOW_RSA15_KEY_TRANSPORT_ALGORITHM = "allowRSA15KeyTransportAlgorithm"; } diff --git a/modules/rampart-trust/src/main/java/org/apache/rahas/client/STSClient.java b/modules/rampart-trust/src/main/java/org/apache/rahas/client/STSClient.java index 84fe0a03..060e2cc8 100644 --- a/modules/rampart-trust/src/main/java/org/apache/rahas/client/STSClient.java +++ b/modules/rampart-trust/src/main/java/org/apache/rahas/client/STSClient.java @@ -47,6 +47,7 @@ import org.apache.ws.secpolicy.model.AlgorithmSuite; import org.apache.ws.secpolicy.model.Binding; import org.apache.ws.secpolicy.model.Trust10; import org.apache.ws.secpolicy.model.Trust13; +import org.apache.wss4j.dom.handler.RequestData; import org.apache.wss4j.dom.WSConstants; import org.apache.wss4j.common.ext.WSPasswordCallback; import org.apache.wss4j.common.ext.WSSecurityException; @@ -479,11 +480,68 @@ public class STSClient { child.getXMLStreamReader()).getDocumentElement(); try { + RequestData requestData = new RequestData(); boolean disableBSPEnforcement = false; if (this.options != null && this.options.getProperty(RahasConstants.DISABLE_BSP_ENFORCEMENT) != null) { disableBSPEnforcement = Boolean.parseBoolean((String) this.options.getProperty(RahasConstants.DISABLE_BSP_ENFORCEMENT)); + requestData.setDisableBSPEnforcement(disableBSPEnforcement); } - secret = CommonUtil.getDecryptedBytes(this.cbHandler, this.crypto, domChild, disableBSPEnforcement); + boolean allowUsernameTokenNoPassword = false; + if (this.options != null && this.options.getProperty(RahasConstants.ALLOW_USERNAME_TOKEN_NO_PASSWORD) != null) { + allowUsernameTokenNoPassword = Boolean.parseBoolean((String) this.options.getProperty(RahasConstants.ALLOW_USERNAME_TOKEN_NO_PASSWORD)); + requestData.setAllowUsernameTokenNoPassword(allowUsernameTokenNoPassword); + } + + int timeStampFutureTTL = 60; + if (this.options != null && this.options.getProperty(RahasConstants.TIMESTAMP_FUTURE_TTL) != null) { + timeStampFutureTTL = Integer.valueOf((String) this.options.getProperty(RahasConstants.TIMESTAMP_FUTURE_TTL)); + requestData.setTimeStampFutureTTL(timeStampFutureTTL); + } + + int utTTL = 300; + if (this.options != null && this.options.getProperty(RahasConstants.UT_TTL) != null) { + utTTL = Integer.valueOf((String) this.options.getProperty(RahasConstants.UT_TTL)); + requestData.setUtTTL(utTTL); + } + + int utFutureTTL = 60; + if (this.options != null && this.options.getProperty(RahasConstants.UT_FUTURE_TTL) != null) { + utFutureTTL = Integer.valueOf((String) this.options.getProperty(RahasConstants.UT_FUTURE_TTL)); + requestData.setUtFutureTTL(utFutureTTL); + } + + /* WSS4J sets this as false however before 1.8.0 this was hard-coded to true */ + boolean handleCustomPasswordTypes = true; + if (this.options != null && this.options.getProperty(RahasConstants.HANDLE_CUSTOM_PASSWORD_TYPES) != null) { + handleCustomPasswordTypes = Boolean.valueOf((String) this.options.getProperty(RahasConstants.HANDLE_CUSTOM_PASSWORD_TYPES)); + requestData.setHandleCustomPasswordTypes(handleCustomPasswordTypes); + } + + boolean allowNamespaceQualifiedPasswordTypes = false; + if (this.options != null && this.options.getProperty(RahasConstants.ALLOW_NAMESPACE_QUALIFIED_PASSWORDTYPES) != null) { + allowNamespaceQualifiedPasswordTypes = Boolean.valueOf((String) this.options.getProperty(RahasConstants.ALLOW_NAMESPACE_QUALIFIED_PASSWORDTYPES)); + requestData.setAllowNamespaceQualifiedPasswordTypes(allowNamespaceQualifiedPasswordTypes); + } + + boolean encodePasswords = false; + if (this.options != null && this.options.getProperty(RahasConstants.ENCODE_PASSWORDS) != null) { + encodePasswords = Boolean.valueOf((String) this.options.getProperty(RahasConstants.ENCODE_PASSWORDS)); + requestData.setEncodePasswords(encodePasswords); + } + + boolean validateSamlSubjectConfirmation = false; // backward compatibility + if (this.options != null && this.options.getProperty(RahasConstants.VALIDATE_SAML_SUBJECT_CONFIRMATION) != null) { + validateSamlSubjectConfirmation = Boolean.valueOf((String) this.options.getProperty(RahasConstants.VALIDATE_SAML_SUBJECT_CONFIRMATION)); + requestData.setValidateSamlSubjectConfirmation(validateSamlSubjectConfirmation); + } + + boolean allowRSA15KeyTransportAlgorithm = true; // backward compatibility + if (this.options != null && this.options.getProperty(RahasConstants.ALLOW_RSA15_KEY_TRANSPORT_ALGORITHM) != null) { + allowRSA15KeyTransportAlgorithm = Boolean.valueOf((String) this.options.getProperty(RahasConstants.ALLOW_RSA15_KEY_TRANSPORT_ALGORITHM)); + requestData.setAllowRSA15KeyTransportAlgorithm(allowRSA15KeyTransportAlgorithm); + } + + secret = CommonUtil.getDecryptedBytes(this.cbHandler, this.crypto, domChild, requestData); } catch (WSSecurityException e) { log.error("Error decrypting encrypted key element", e); throw new TrustException("errorInProcessingEncryptedKey", e); diff --git a/modules/rampart-trust/src/main/java/org/apache/rahas/impl/util/CommonUtil.java b/modules/rampart-trust/src/main/java/org/apache/rahas/impl/util/CommonUtil.java index 25b4d487..77f6bf7d 100644 --- a/modules/rampart-trust/src/main/java/org/apache/rahas/impl/util/CommonUtil.java +++ b/modules/rampart-trust/src/main/java/org/apache/rahas/impl/util/CommonUtil.java @@ -144,14 +144,49 @@ public class CommonUtil { } /** - * Decrypts the EncryptedKey element and returns the secret that was used. + * Decrypts the EncryptedKey element and returns the secret that was used. This method has been deprecated - use the method that + * passes in org.apache.wss4j.dom.handler.RequestData * @param callbackHandler Callback handler to pass to WSS4J framework. * @param crypto To get private key information. * @param encryptedKeyElement The encrypted Key element. + * @param requestData Set optional WSS4J values and pass this Object in * @return The secret as a byte stream. * @throws WSSecurityException If an error is occurred while decrypting the element. */ - public static byte[] getDecryptedBytes(CallbackHandler callbackHandler, Crypto crypto, Node encryptedKeyElement, boolean disableBSPEnforcement) + public static byte[] getDecryptedBytes(CallbackHandler callbackHandler, Crypto crypto, Node encryptedKeyElement, RequestData requestData) + throws WSSecurityException { + + EncryptedKeyProcessor encryptedKeyProcessor = new EncryptedKeyProcessor(); + + requestData.setCallbackHandler(callbackHandler); + requestData.setDecCrypto(crypto); + + final WSSConfig cfg = WSSConfig.getNewInstance(); + requestData.setWssConfig(cfg); + + WSDocInfo docInfo = new WSDocInfo(encryptedKeyElement.getOwnerDocument()); + docInfo.setCallbackLookup(new DOMCallbackLookup(encryptedKeyElement.getOwnerDocument())); + requestData.setWsDocInfo(docInfo); + + List<WSSecurityEngineResult> resultList; + + resultList = encryptedKeyProcessor.handleToken((Element) encryptedKeyElement, requestData); + + WSSecurityEngineResult wsSecurityEngineResult = resultList.get(0); + + return (byte[]) wsSecurityEngineResult.get(WSSecurityEngineResult.TAG_SECRET); + } + /** + * Decrypts the EncryptedKey element and returns the secret that was used. This method has been deprecated - use the method that + * passes in org.apache.wss4j.dom.handler.RequestData + * @param callbackHandler Callback handler to pass to WSS4J framework. + * @param crypto To get private key information. + * @param encryptedKeyElement The encrypted Key element. + * @return The secret as a byte stream. + * @throws WSSecurityException If an error is occurred while decrypting the element. + */ + @Deprecated + public static byte[] getDecryptedBytes(CallbackHandler callbackHandler, Crypto crypto, Node encryptedKeyElement) throws WSSecurityException { EncryptedKeyProcessor encryptedKeyProcessor = new EncryptedKeyProcessor(); @@ -159,7 +194,6 @@ public class CommonUtil { RequestData requestData = new RequestData(); requestData.setCallbackHandler(callbackHandler); requestData.setDecCrypto(crypto); - requestData.setDisableBSPEnforcement(disableBSPEnforcement); final WSSConfig cfg = WSSConfig.getNewInstance(); requestData.setWssConfig(cfg); diff --git a/modules/rampart-trust/src/main/java/org/apache/rahas/impl/util/SAML2Utils.java b/modules/rampart-trust/src/main/java/org/apache/rahas/impl/util/SAML2Utils.java index 6b89f300..9015ae59 100644 --- a/modules/rampart-trust/src/main/java/org/apache/rahas/impl/util/SAML2Utils.java +++ b/modules/rampart-trust/src/main/java/org/apache/rahas/impl/util/SAML2Utils.java @@ -25,8 +25,9 @@ import org.apache.rahas.RahasConstants; import org.apache.rahas.TrustException; import org.apache.wss4j.common.crypto.Crypto; import org.apache.wss4j.common.ext.WSPasswordCallback; -import org.apache.wss4j.dom.engine.WSSecurityEngine; import org.apache.wss4j.common.ext.WSSecurityException; +import org.apache.wss4j.dom.engine.WSSecurityEngine; +import org.apache.wss4j.dom.handler.RequestData; import org.apache.wss4j.dom.util.WSSecurityUtil; import org.apache.wss4j.dom.WSConstants; import org.apache.xml.security.exceptions.XMLSecurityException; @@ -103,7 +104,7 @@ public class SAML2Utils { * */ public static SAML2KeyInfo getSAML2KeyInfo(Element elem, Crypto crypto, - CallbackHandler cb, boolean disableBSPEnforcement) throws WSSecurityException { + CallbackHandler cb, RequestData requestData) throws WSSecurityException { Assertion assertion; //build the assertion by unmarhalling the DOM element. @@ -139,12 +140,12 @@ public class SAML2Utils { throw new WSSecurityException( WSSecurityException.ErrorCode.FAILURE, e, "Failure in unmarshelling the assertion"); } - return getSAML2KeyInfo(assertion, crypto, cb, disableBSPEnforcement); + return getSAML2KeyInfo(assertion, crypto, cb, requestData); } public static SAML2KeyInfo getSAML2KeyInfo(Assertion assertion, Crypto crypto, - CallbackHandler cb, boolean disableBSPEnforcement) throws WSSecurityException { + CallbackHandler cb, RequestData requestData) throws WSSecurityException { //First ask the cb whether it can provide the secret WSPasswordCallback pwcb = new WSPasswordCallback(assertion.getID(), WSPasswordCallback.CUSTOM_TOKEN); @@ -232,7 +233,7 @@ public class SAML2Utils { QName el = new QName(child.getNamespaceURI(), child.getLocalName()); if (el.equals(WSConstants.ENCRYPTED_KEY)) { - byte[] secret = CommonUtil.getDecryptedBytes(cb, crypto, child, disableBSPEnforcement); + byte[] secret = CommonUtil.getDecryptedBytes(cb, crypto, child, requestData); return new SAML2KeyInfo(assertion, secret); } else if (el.equals(new QName(WSConstants.WST_NS, "BinarySecret"))) { diff --git a/modules/rampart-trust/src/test/java/org/apache/rahas/impl/util/CommonUtilTest.java b/modules/rampart-trust/src/test/java/org/apache/rahas/impl/util/CommonUtilTest.java index 877f6b69..61746707 100644 --- a/modules/rampart-trust/src/test/java/org/apache/rahas/impl/util/CommonUtilTest.java +++ b/modules/rampart-trust/src/test/java/org/apache/rahas/impl/util/CommonUtilTest.java @@ -34,6 +34,7 @@ import org.apache.rahas.test.util.TestCallbackHandler; import org.apache.rahas.test.util.TestSAMLCallbackHandler; import org.apache.rahas.test.util.TestUtil; import org.apache.wss4j.dom.WSConstants; +import org.apache.wss4j.dom.handler.RequestData; import org.apache.wss4j.common.WSEncryptionPart; import org.apache.wss4j.common.crypto.Crypto; import org.apache.wss4j.common.util.KeyUtils; @@ -204,7 +205,7 @@ public class CommonUtilTest extends AbstractTestCase { Element element = builder.getEncryptedKeyElement(); - byte[] decryptedKey = CommonUtil.getDecryptedBytes(new TestCallbackHandler(), TestUtil.getCrypto(), element, false); + byte[] decryptedKey = CommonUtil.getDecryptedBytes(new TestCallbackHandler(), TestUtil.getCrypto(), element, new RequestData()); Assert.assertTrue(Arrays.equals(ephemeralKey, decryptedKey));