Repository: cxf Updated Branches: refs/heads/master 13d33c9ed -> 0252de53c
[CXF-5525] - Adding a JAX-WS property to disable client cert verification policy check + tests Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/0252de53 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/0252de53 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/0252de53 Branch: refs/heads/master Commit: 0252de53c8b2bd230544e7c9cffc9355741dc2f1 Parents: 13d33c9 Author: Colm O hEigeartaigh <cohei...@apache.org> Authored: Thu Mar 2 18:17:05 2017 +0000 Committer: Colm O hEigeartaigh <cohei...@apache.org> Committed: Thu Mar 2 18:17:54 2017 +0000 ---------------------------------------------------------------------- .../apache/cxf/transport/http/HTTPConduit.java | 7 ++- .../cxf/transport/http/MessageTrustDecider.java | 6 +-- .../cxf/ws/security/SecurityConstants.java | 11 ++++- .../HttpsTokenInterceptorProvider.java | 46 ++++++++++++-------- .../cxf/systest/ws/https/HttpsTokenTest.java | 44 +++++++++++++++++++ .../cxf/systest/ws/https/DoubleItHttps.wsdl | 6 +++ .../org/apache/cxf/systest/ws/https/client.xml | 26 +++++++++++ .../org/apache/cxf/systest/ws/https/server.xml | 14 ++++++ .../apache/cxf/systest/ws/https/stax-server.xml | 20 +++++++++ 9 files changed, 153 insertions(+), 27 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/0252de53/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java ---------------------------------------------------------------------- diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java index 8314c14..30798f7 100644 --- a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java +++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HTTPConduit.java @@ -1762,10 +1762,9 @@ public abstract class HTTPConduit // already connected. HttpsURLConnectionInfo info = getHttpsURLConnectionInfo(); if (trustDecider != null) { - trustDecider.establishTrust( - conduitName, - info, - outMessage); + trustDecider.establishTrust(conduitName, + info, + outMessage); if (LOG.isLoggable(Level.FINE)) { LOG.log(Level.FINE, "Trust Decider " + trustDecider.getLogicalName() http://git-wip-us.apache.org/repos/asf/cxf/blob/0252de53/rt/transports/http/src/main/java/org/apache/cxf/transport/http/MessageTrustDecider.java ---------------------------------------------------------------------- diff --git a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/MessageTrustDecider.java b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/MessageTrustDecider.java index ac3efb8..8cd2fff 100644 --- a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/MessageTrustDecider.java +++ b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/MessageTrustDecider.java @@ -29,9 +29,9 @@ import org.apache.cxf.message.Message; * java.net.URLConnection implementations. * * The HttpURLConnection will be set up and connected, but no data - * yet sent (at least according to the JDK 1.5 default implemenation), + * yet sent (at least according to the JDK 1.5 default implementation), * and in the case of an HttpsURLConnection (again with caveat on - * particular java.net.HttpsURLConnection implemenation), the TLS handshake + * particular java.net.HttpsURLConnection implementation), the TLS handshake * will be completed and certain TLS artifacts will be available. * <p> * Each MessageTrustDecider has a "logical" name that may be used in logging @@ -89,7 +89,7 @@ public abstract class MessageTrustDecider { * The HTTPConduit calls this message on every redirect, however, it is * impossible to tell where it has been redirected from. * - * TODO: What are the exising Message Properties at the point of this call? + * TODO: What are the existing Message Properties at the point of this call? * * @param conduitName This parameter contains the logical name * for the conduit that this trust decider http://git-wip-us.apache.org/repos/asf/cxf/blob/0252de53/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java index 7e91fc2..1784e6e 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/SecurityConstants.java @@ -145,6 +145,14 @@ public final class SecurityConstants extends org.apache.cxf.rt.security.Security * Signatures using WSConstants.C14N_EXCL_OMIT_COMMENTS. Default is "true". */ public static final String ADD_INCLUSIVE_PREFIXES = "ws-security.add.inclusive.prefixes"; + + /** + * Whether to disable the enforcement of the WS-SecurityPolicy 'RequireClientCertificate' policy. + * Default is "false". Some servers may not do client certificate verification at the start of the SSL + * handshake, and therefore the client certs may not be available to the WS-Security layer for policy + * verification at that time. + */ + public static final String DISABLE_REQ_CLIENT_CERT_CHECK = "ws-security.disable.require.client.cert.check"; // // Non-boolean WS-Security Configuration parameters @@ -416,7 +424,8 @@ public final class SecurityConstants extends org.apache.cxf.rt.security.Security CACHE_IDENTIFIER, DELEGATED_CREDENTIAL, KERBEROS_USE_CREDENTIAL_DELEGATION, KERBEROS_IS_USERNAME_IN_SERVICENAME_FORM, KERBEROS_REQUEST_CREDENTIAL_DELEGATION, POLICY_VALIDATOR_MAP, STORE_BYTES_IN_ATTACHMENT, USE_ATTACHMENT_ENCRYPTION_CONTENT_ONLY_TRANSFORM, - SYMMETRIC_SIGNATURE_ALGORITHM, SECURITY_CONTEXT_CREATOR, SECURITY_TOKEN_LIFETIME + SYMMETRIC_SIGNATURE_ALGORITHM, SECURITY_CONTEXT_CREATOR, SECURITY_TOKEN_LIFETIME, + DISABLE_REQ_CLIENT_CERT_CHECK })); for (String commonProperty : COMMON_PROPERTIES) { s.add(commonProperty); http://git-wip-us.apache.org/repos/asf/cxf/blob/0252de53/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/HttpsTokenInterceptorProvider.java ---------------------------------------------------------------------- diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/HttpsTokenInterceptorProvider.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/HttpsTokenInterceptorProvider.java index 2ff1ea6..b2c24f6 100644 --- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/HttpsTokenInterceptorProvider.java +++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/policy/interceptors/HttpsTokenInterceptorProvider.java @@ -36,6 +36,7 @@ import org.apache.cxf.configuration.security.AuthorizationPolicy; import org.apache.cxf.helpers.CastUtils; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.message.Message; +import org.apache.cxf.message.MessageUtils; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.apache.cxf.security.SecurityContext; @@ -48,6 +49,7 @@ import org.apache.cxf.ws.policy.AbstractPolicyInterceptorProvider; import org.apache.cxf.ws.policy.AssertionInfo; import org.apache.cxf.ws.policy.AssertionInfoMap; import org.apache.cxf.ws.policy.PolicyException; +import org.apache.cxf.ws.security.SecurityConstants; import org.apache.cxf.ws.security.policy.PolicyUtils; import org.apache.cxf.ws.security.wss4j.WSS4JStaxInInterceptor; import org.apache.wss4j.policy.SP11Constants; @@ -121,26 +123,32 @@ public class HttpsTokenInterceptorProvider extends AbstractPolicyInterceptorProv if ("https".equals(scheme)) { if (token.getAuthenticationType() == HttpsToken.AuthenticationType.RequireClientCertificate) { - final MessageTrustDecider orig = message.get(MessageTrustDecider.class); - MessageTrustDecider trust = new MessageTrustDecider() { - public void establishTrust(String conduitName, - URLConnectionInfo connectionInfo, - Message message) - throws UntrustedURLConnectionIOException { - if (orig != null) { - orig.establishTrust(conduitName, connectionInfo, message); + boolean disableClientCertCheck = + MessageUtils.getContextualBoolean(message, + SecurityConstants.DISABLE_REQ_CLIENT_CERT_CHECK, + false); + if (!disableClientCertCheck) { + final MessageTrustDecider orig = message.get(MessageTrustDecider.class); + MessageTrustDecider trust = new MessageTrustDecider() { + public void establishTrust(String conduitName, + URLConnectionInfo connectionInfo, + Message message) + throws UntrustedURLConnectionIOException { + if (orig != null) { + orig.establishTrust(conduitName, connectionInfo, message); + } + HttpsURLConnectionInfo info = (HttpsURLConnectionInfo)connectionInfo; + if (info.getLocalCertificates() == null + || info.getLocalCertificates().length == 0) { + throw new UntrustedURLConnectionIOException( + "RequireClientCertificate is set, " + + "but no local certificates were negotiated. Is" + + " the server set to ask for client authorization?"); + } } - HttpsURLConnectionInfo info = (HttpsURLConnectionInfo)connectionInfo; - if (info.getLocalCertificates() == null - || info.getLocalCertificates().length == 0) { - throw new UntrustedURLConnectionIOException( - "RequireClientCertificate is set, " - + "but no local certificates were negotiated. Is" - + " the server set to ask for client authorization?"); - } - } - }; - message.put(MessageTrustDecider.class, trust); + }; + message.put(MessageTrustDecider.class, trust); + } PolicyUtils.assertPolicy(aim, new QName(token.getName().getNamespaceURI(), SPConstants.REQUIRE_CLIENT_CERTIFICATE)); } http://git-wip-us.apache.org/repos/asf/cxf/blob/0252de53/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/https/HttpsTokenTest.java ---------------------------------------------------------------------- diff --git a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/https/HttpsTokenTest.java b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/https/HttpsTokenTest.java index 21a8123..2875780 100644 --- a/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/https/HttpsTokenTest.java +++ b/systests/ws-security/src/test/java/org/apache/cxf/systest/ws/https/HttpsTokenTest.java @@ -130,6 +130,50 @@ public class HttpsTokenTest extends AbstractBusClientServerTestBase { ((java.io.Closeable)port).close(); bus.shutdown(true); } + + @org.junit.Test + public void testNoClientCertRequirement() throws Exception { + + SpringBusFactory bf = new SpringBusFactory(); + URL busFile = HttpsTokenTest.class.getResource("client.xml"); + + Bus bus = bf.createBus(busFile.toString()); + SpringBusFactory.setDefaultBus(bus); + SpringBusFactory.setThreadDefaultBus(bus); + + URL wsdl = HttpsTokenTest.class.getResource("DoubleItHttps.wsdl"); + Service service = Service.create(wsdl, SERVICE_QNAME); + QName portQName = new QName(NAMESPACE, "DoubleItNoClientCertRequirementPort"); + DoubleItPortType port = + service.getPort(portQName, DoubleItPortType.class); + updateAddressPort(port, test.getPort()); + + if (test.isStreaming()) { + SecurityTestUtil.enableStreaming(port); + } + + try { + port.doubleIt(25); + fail("(Policy) Failure expected on not using a client cert"); + } catch (Exception ex) { + // expected + } + + // This should work, as we're disable the RequireClientCertificate check via a + // JAX-WS property + portQName = new QName(NAMESPACE, "DoubleItNoClientCertRequirementPort2"); + port = service.getPort(portQName, DoubleItPortType.class); + updateAddressPort(port, test.getPort()); + + if (test.isStreaming()) { + SecurityTestUtil.enableStreaming(port); + } + + port.doubleIt(25); + + ((java.io.Closeable)port).close(); + bus.shutdown(true); + } @org.junit.Test public void testBasicAuth() throws Exception { http://git-wip-us.apache.org/repos/asf/cxf/blob/0252de53/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/DoubleItHttps.wsdl ---------------------------------------------------------------------- diff --git a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/DoubleItHttps.wsdl b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/DoubleItHttps.wsdl index 3db601c..9def79d 100644 --- a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/DoubleItHttps.wsdl +++ b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/DoubleItHttps.wsdl @@ -41,6 +41,12 @@ <wsdl:port name="DoubleItRequireClientCertPort2" binding="tns:DoubleItInlinePolicyBinding"> <soap:address location="https://localhost:9009/DoubleItRequireClientCert2"/> </wsdl:port> + <wsdl:port name="DoubleItNoClientCertRequirementPort" binding="tns:DoubleItInlinePolicyBinding"> + <soap:address location="https://localhost:9009/DoubleItNoClientCertRequirement"/> + </wsdl:port> + <wsdl:port name="DoubleItNoClientCertRequirementPort2" binding="tns:DoubleItInlinePolicyBinding"> + <soap:address location="https://localhost:9009/DoubleItNoClientCertRequirement2"/> + </wsdl:port> <wsdl:port name="DoubleItBasicAuthPort" binding="tns:DoubleItInlinePolicyBinding"> <soap:address location="https://localhost:9009/DoubleItBasicAuth"/> </wsdl:port> http://git-wip-us.apache.org/repos/asf/cxf/blob/0252de53/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/client.xml ---------------------------------------------------------------------- diff --git a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/client.xml b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/client.xml index 2ef7540..6572805 100644 --- a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/client.xml +++ b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/client.xml @@ -34,6 +34,13 @@ </sec:trustManagers> </http:tlsClientParameters> </http:conduit> + <http:conduit name="https://localhost:.*/DoubleItNoClientCertRequirement.*"> + <http:tlsClientParameters disableCNCheck="true"> + <sec:trustManagers> + <sec:keyStore type="jks" password="password" resource="keys/Truststore.jks"/> + </sec:trustManagers> + </http:tlsClientParameters> + </http:conduit> <jaxws:client name="{http://www.example.org/contract/DoubleIt}DoubleItRequireClientCertPort" createdFromAPI="true"> <jaxws:properties> </jaxws:properties> @@ -59,6 +66,25 @@ </p:policies> </jaxws:features> </jaxws:client> + <jaxws:client name="{http://www.example.org/contract/DoubleIt}DoubleItNoClientCertRequirementPort" createdFromAPI="true"> + <jaxws:properties> + </jaxws:properties> + <jaxws:features> + <p:policies> + <wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy" URI="classpath:/org/apache/cxf/systest/ws/https/req-client-cert-policy.xml"/> + </p:policies> + </jaxws:features> + </jaxws:client> + <jaxws:client name="{http://www.example.org/contract/DoubleIt}DoubleItNoClientCertRequirementPort2" createdFromAPI="true"> + <jaxws:properties> + <entry key="ws-security.disable.require.client.cert.check" value="true"/> + </jaxws:properties> + <jaxws:features> + <p:policies> + <wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy" URI="classpath:/org/apache/cxf/systest/ws/https/req-client-cert-policy.xml"/> + </p:policies> + </jaxws:features> + </jaxws:client> <http:conduit name="https://localhost:.*/DoubleItBasicAuth"> <http:tlsClientParameters disableCNCheck="true"> <sec:trustManagers> http://git-wip-us.apache.org/repos/asf/cxf/blob/0252de53/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/server.xml ---------------------------------------------------------------------- diff --git a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/server.xml b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/server.xml index 89ba4b9..e0a11b4 100644 --- a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/server.xml +++ b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/server.xml @@ -56,6 +56,20 @@ </p:policies> </jaxws:features> </jaxws:endpoint> + <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt" id="NoClientCertRequirement" address="https://localhost:${testutil.ports.https.Server}/DoubleItNoClientCertRequirement" serviceName="s:DoubleItService" endpointName="s:DoubleItNoClientCertRequirementPort" implementor="org.apache.cxf.systest.ws.common.DoubleItImpl" wsdlLocation="org/apache/cxf/systest/ws/https/DoubleItHttps.wsdl" depends-on="tls-settings"> + <jaxws:features> + <p:policies> + <wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy" URI="classpath:/org/apache/cxf/systest/ws/https/clean-policy.xml"/> + </p:policies> + </jaxws:features> + </jaxws:endpoint> + <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt" id="NoClientCertRequirement2" address="https://localhost:${testutil.ports.https.Server}/DoubleItNoClientCertRequirement2" serviceName="s:DoubleItService" endpointName="s:DoubleItNoClientCertRequirementPort2" implementor="org.apache.cxf.systest.ws.common.DoubleItImpl" wsdlLocation="org/apache/cxf/systest/ws/https/DoubleItHttps.wsdl" depends-on="tls-settings"> + <jaxws:features> + <p:policies> + <wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy" URI="classpath:/org/apache/cxf/systest/ws/https/clean-policy.xml"/> + </p:policies> + </jaxws:features> + </jaxws:endpoint> <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt" id="BasicAuth" address="https://localhost:${testutil.ports.https.Server}/DoubleItBasicAuth" serviceName="s:DoubleItService" endpointName="s:DoubleItBasicAuthPort" implementor="org.apache.cxf.systest.ws.common.DoubleItImpl" wsdlLocation="org/apache/cxf/systest/ws/https/DoubleItHttps.wsdl" depends-on="tls-settings"> <jaxws:features> <p:policies> http://git-wip-us.apache.org/repos/asf/cxf/blob/0252de53/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/stax-server.xml ---------------------------------------------------------------------- diff --git a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/stax-server.xml b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/stax-server.xml index 75e48f0..3e4a239 100644 --- a/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/stax-server.xml +++ b/systests/ws-security/src/test/resources/org/apache/cxf/systest/ws/https/stax-server.xml @@ -62,6 +62,26 @@ <entry key="ws-security.enable.streaming" value="true"/> </jaxws:properties> </jaxws:endpoint> + <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt" id="NoClientCertRequirement" address="https://localhost:${testutil.ports.https.StaxServer}/DoubleItNoClientCertRequirement" serviceName="s:DoubleItService" endpointName="s:DoubleItNoClientCertRequirementPort" implementor="org.apache.cxf.systest.ws.common.DoubleItImpl" wsdlLocation="org/apache/cxf/systest/ws/https/DoubleItHttps.wsdl" depends-on="tls-settings"> + <jaxws:features> + <p:policies> + <wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy" URI="classpath:/org/apache/cxf/systest/ws/https/clean-policy.xml"/> + </p:policies> + </jaxws:features> + <jaxws:properties> + <entry key="ws-security.enable.streaming" value="true"/> + </jaxws:properties> + </jaxws:endpoint> + <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt" id="NoClientCertRequirement2" address="https://localhost:${testutil.ports.https.StaxServer}/DoubleItNoClientCertRequirement2" serviceName="s:DoubleItService" endpointName="s:DoubleItNoClientCertRequirementPort2" implementor="org.apache.cxf.systest.ws.common.DoubleItImpl" wsdlLocation="org/apache/cxf/systest/ws/https/DoubleItHttps.wsdl" depends-on="tls-settings"> + <jaxws:features> + <p:policies> + <wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy" URI="classpath:/org/apache/cxf/systest/ws/https/clean-policy.xml"/> + </p:policies> + </jaxws:features> + <jaxws:properties> + <entry key="ws-security.enable.streaming" value="true"/> + </jaxws:properties> + </jaxws:endpoint> <jaxws:endpoint xmlns:s="http://www.example.org/contract/DoubleIt" id="BasicAuth" address="https://localhost:${testutil.ports.https.StaxServer}/DoubleItBasicAuth" serviceName="s:DoubleItService" endpointName="s:DoubleItBasicAuthPort" implementor="org.apache.cxf.systest.ws.common.DoubleItImpl" wsdlLocation="org/apache/cxf/systest/ws/https/DoubleItHttps.wsdl" depends-on="tls-settings"> <jaxws:features> <p:policies>