Index: container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PortInfo.java =================================================================== --- container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PortInfo.java (revision 756243) +++ container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/PortInfo.java (working copy) @@ -20,6 +20,7 @@ import javax.xml.namespace.QName; import java.util.List; import java.util.ArrayList; +import java.util.Properties; public class PortInfo extends InfoObject { public String serviceId; @@ -44,4 +45,5 @@ public String realmName; public String transportGuarantee; public String securityRealmName; + public Properties properties; } Index: container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/WsBuilder.java =================================================================== --- container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/WsBuilder.java (revision 756243) +++ container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/WsBuilder.java (working copy) @@ -50,6 +50,9 @@ portData.setLocation(port.location); portData.setSecure("WS-SECURITY".equals(port.authMethod)); + if (portData.isSecure()) { + portData.setSecurityProperties(port.properties); + } return portData; } Index: container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java =================================================================== --- container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java (revision 767479) +++ container/openejb-core/src/main/java/org/apache/openejb/config/AppInfoBuilder.java (working copy) @@ -242,53 +242,6 @@ } - /* - * left package-local for a unit test - */ - void configureWebserviceSecurity(EjbJarInfo ejbJarInfo, EjbModule ejbModule) { - Object altDD = ejbModule.getAltDDs().get("openejb-jar.xml"); - if (altDD == null || (! (altDD instanceof OpenejbJarType))) return; - - OpenejbJarType openejbJarType = (OpenejbJarType) altDD; - - - Map beans = new HashMap(); - for (org.apache.openejb.jee.oejb2.EnterpriseBean enterpriseBean : openejbJarType.getEnterpriseBeans()) { - beans.put(enterpriseBean.getEjbName(), enterpriseBean); - } - - List infoList = ejbJarInfo.portInfos; - for (PortInfo portInfo : infoList) { - - org.apache.openejb.jee.oejb2.EnterpriseBean bean = beans.get(portInfo.serviceLink); - - if (bean == null) continue; /* TODO: throw something? */ - if (!(bean instanceof SessionBeanType)) continue; /* TODO: throw something? */ - - SessionBeanType sessionBean = (SessionBeanType) bean; - WebServiceSecurityType webServiceSecurityType = sessionBean.getWebServiceSecurity(); - - if (webServiceSecurityType == null) { - //TODO: this ok? - continue; - } - - portInfo.realmName = webServiceSecurityType.getRealmName(); - portInfo.securityRealmName = webServiceSecurityType.getSecurityRealmName(); - if (webServiceSecurityType.getTransportGuarantee() != null) { - portInfo.transportGuarantee = webServiceSecurityType.getTransportGuarantee().value(); - } else { - portInfo.transportGuarantee = "NONE"; - } - - if (webServiceSecurityType.getAuthMethod() != null) { - portInfo.authMethod = webServiceSecurityType.getAuthMethod().value(); - } else { - portInfo.authMethod = "NONE"; - } - } - } - private void buildClientModules(AppModule appModule, AppInfo appInfo, JndiEncInfoBuilder jndiEncInfoBuilder) throws OpenEJBException { for (ClientModule clientModule : appModule.getClientModules()) { ApplicationClient applicationClient = clientModule.getApplicationClient(); @@ -322,6 +275,7 @@ webAppInfo.jndiEnc = jndiEncInfoBuilder.build(webApp, webModule.getJarLocation(), webAppInfo.moduleId); webAppInfo.portInfos.addAll(configureWebservices(webModule.getWebservices())); + configureWebserviceSecurity(webAppInfo, webModule); for (Servlet servlet : webModule.getWebApp().getServlet()) { ServletInfo servletInfo = new ServletInfo(); @@ -672,6 +626,67 @@ return portMap; } + void configureWebserviceSecurity(WebAppInfo info, WebModule module) { + Object altDD = module.getAltDDs().get("openejb-jar.xml"); + List infoList = info.portInfos; + + configureWebserviceScurity(infoList, altDD); + } + + /* + * left package-local for a unit test + */ + void configureWebserviceSecurity(EjbJarInfo ejbJarInfo, EjbModule ejbModule) { + Object altDD = ejbModule.getAltDDs().get("openejb-jar.xml"); + List infoList = ejbJarInfo.portInfos; + + configureWebserviceScurity(infoList, altDD); + } + + private void configureWebserviceScurity(List infoList, Object altDD) { + if (altDD == null || (! (altDD instanceof OpenejbJarType))) return; + + OpenejbJarType openejbJarType = (OpenejbJarType) altDD; + + Map beans = new HashMap(); + for (org.apache.openejb.jee.oejb2.EnterpriseBean enterpriseBean : openejbJarType.getEnterpriseBeans()) { + beans.put(enterpriseBean.getEjbName(), enterpriseBean); + } + + for (PortInfo portInfo : infoList) { + + org.apache.openejb.jee.oejb2.EnterpriseBean bean = beans.get(portInfo.serviceLink); + + if (bean == null) continue; /* TODO: throw something? */ + if (!(bean instanceof SessionBeanType)) continue; /* TODO: throw something? */ + + SessionBeanType sessionBean = (SessionBeanType) bean; + WebServiceSecurityType webServiceSecurityType = sessionBean.getWebServiceSecurity(); + + if (webServiceSecurityType == null) { + //TODO: this ok? + continue; + } + + portInfo.realmName = webServiceSecurityType.getRealmName(); + portInfo.securityRealmName = webServiceSecurityType.getSecurityRealmName(); + if (webServiceSecurityType.getTransportGuarantee() != null) { + portInfo.transportGuarantee = webServiceSecurityType.getTransportGuarantee().value(); + } else { + portInfo.transportGuarantee = "NONE"; + } + + if (webServiceSecurityType.getAuthMethod() != null) { + portInfo.authMethod = webServiceSecurityType.getAuthMethod().value(); + } else { + portInfo.authMethod = "NONE"; + } + portInfo.properties = webServiceSecurityType.getProperties(); + + } + + } + private static boolean skipMdb(EnterpriseBeanInfo bean) { return bean instanceof MessageDrivenBeanInfo && System.getProperty("duct tape") != null; } Index: container/openejb-core/src/main/java/org/apache/openejb/config/WsDeployer.java =================================================================== --- container/openejb-core/src/main/java/org/apache/openejb/config/WsDeployer.java (revision 756243) +++ container/openejb-core/src/main/java/org/apache/openejb/config/WsDeployer.java (working copy) @@ -269,6 +269,8 @@ webservices = new Webservices(); ejbModule.setWebservices(webservices); } + + webserviceDescription = webservices.getWebserviceDescriptionMap().get(JaxWsUtils.getServiceName(ejbClass)); if (webserviceDescription == null) { webserviceDescription = new WebserviceDescription(); if (JaxWsUtils.isWebService(ejbClass)) { @@ -283,11 +285,15 @@ PortComponent portComponent = portMap.get(sessionBean.getEjbName()); if (portComponent == null) { portComponent = new PortComponent(); - if (ejbClass.isAnnotationPresent(WebServiceProvider.class)) { - portComponent.setPortComponentName(ejbClass.getName()); - } else { - portComponent.setPortComponentName(ejbClass.getSimpleName()); - } + if (webserviceDescription.getPortComponentMap().containsKey(JaxWsUtils.getPortQName(ejbClass).getLocalPart())) { + // when to webservices.xml is defined and when we want to + // publish more than one port for the same implementation by configuration + portComponent.setPortComponentName(sessionBean.getEjbName()); + + } else { // JAX-WS Metadata specification default + portComponent.setPortComponentName(JaxWsUtils.getPortQName(ejbClass).getLocalPart()); + + } webserviceDescription.getPortComponent().add(portComponent); ServiceImplBean serviceImplBean = new ServiceImplBean(); Index: container/openejb-core/src/main/java/org/apache/openejb/core/webservices/JaxWsUtils.java =================================================================== --- container/openejb-core/src/main/java/org/apache/openejb/core/webservices/JaxWsUtils.java (revision 756243) +++ container/openejb-core/src/main/java/org/apache/openejb/core/webservices/JaxWsUtils.java (working copy) @@ -47,7 +47,7 @@ if (webService != null) { String localName = webService.name(); if (localName == null || localName.length() == 0) { - localName = seiClass.getName(); + localName = seiClass.getSimpleName(); } String namespace = webService.targetNamespace(); return new QName(getNamespace(seiClass, namespace), localName); Index: container/openejb-core/src/main/java/org/apache/openejb/core/webservices/PortData.java =================================================================== --- container/openejb-core/src/main/java/org/apache/openejb/core/webservices/PortData.java (revision 756243) +++ container/openejb-core/src/main/java/org/apache/openejb/core/webservices/PortData.java (working copy) @@ -23,6 +23,7 @@ import javax.xml.ws.handler.PortInfo; import java.util.List; import java.util.ArrayList; +import java.util.Properties; import java.net.URL; public class PortData implements PortInfo { @@ -39,6 +40,7 @@ private QName wsdlService; private String location; private boolean secure; + private Properties securityProperties; public String getPortId() { return portId; @@ -127,4 +129,14 @@ public boolean isSecure() { return secure; } + + public Properties getSecurityProperties() { + return securityProperties; + } + + public void setSecurityProperties(Properties securityProperties) { + this.securityProperties = securityProperties; + } + + } Index: container/openejb-core/src/test/java/org/apache/openejb/config/AppInfoBuilderTest.java =================================================================== --- container/openejb-core/src/test/java/org/apache/openejb/config/AppInfoBuilderTest.java (revision 767343) +++ container/openejb-core/src/test/java/org/apache/openejb/config/AppInfoBuilderTest.java (working copy) @@ -25,6 +25,7 @@ import org.apache.openejb.jee.oejb3.OpenejbJar; import java.util.List; +import java.util.Properties; public class AppInfoBuilderTest extends TestCase { public void testShouldAddSecurityDetailsToPortInfo() throws Exception { @@ -44,6 +45,11 @@ serviceSecurityType.setRealmName("MyRealm"); serviceSecurityType.setSecurityRealmName("MySecurityRealm"); serviceSecurityType.setTransportGuarantee(TransportGuaranteeType.NONE); + + Properties props = new Properties(); + props.put("wss4j.in.action", "Timestamp"); + props.put("wss4j.out.action", "Timestamp"); + serviceSecurityType.setProperties(props); openejbSessionBean.setWebServiceSecurity(serviceSecurityType); openejbJarType.getEnterpriseBeans().add(openejbSessionBean); @@ -65,6 +71,8 @@ assertEquals("MySecurityRealm", info.securityRealmName); assertEquals("BASIC", info.authMethod); assertEquals("NONE", info.transportGuarantee); + assertEquals("Timestamp", portInfo.properties.getProperty("wss4j.in.action")); + assertEquals("Timestamp", portInfo.properties.getProperty("wss4j.out.action")); } public void testShouldUseDefaultsIfSettingIsNull() throws Exception { @@ -84,6 +92,7 @@ serviceSecurityType.setRealmName(null); serviceSecurityType.setSecurityRealmName(null); serviceSecurityType.setTransportGuarantee(null); + serviceSecurityType.setProperties(null); openejbSessionBean.setWebServiceSecurity(serviceSecurityType); openejbJarType.getEnterpriseBeans().add(openejbSessionBean); @@ -105,9 +114,10 @@ assertEquals(null, info.securityRealmName); assertEquals("NONE", info.authMethod); assertEquals("NONE", info.transportGuarantee); + assertTrue(portInfo.properties.isEmpty()); } - public void testShouldIngorePortInfoThatDontMatchTheEjb() throws Exception { + public void testShouldIgnorePortInfoThatDontMatchTheEjb() throws Exception { EjbJar ejbJar = new EjbJar(); SessionBean sessionBean = new SessionBean(); sessionBean.setEjbName("MySessionBean"); @@ -124,6 +134,7 @@ serviceSecurityType.setRealmName(null); serviceSecurityType.setSecurityRealmName(null); serviceSecurityType.setTransportGuarantee(null); + serviceSecurityType.setProperties(null); openejbSessionBean.setWebServiceSecurity(serviceSecurityType); openejbJarType.getEnterpriseBeans().add(openejbSessionBean); @@ -138,6 +149,10 @@ portInfo.securityRealmName = ""; portInfo.transportGuarantee = "CONFIDENTIAL"; portInfo.serviceLink = "DifferentInfo"; + Properties props = new Properties(); + props.put("wss4j.in.action", "Timestamp"); + props.put("wss4j.out.action", "Timestamp"); + portInfo.properties = props; ejbJarInfo.portInfos.add(portInfo); new AppInfoBuilder(null).configureWebserviceSecurity(ejbJarInfo, ejbModule); @@ -149,5 +164,7 @@ assertEquals("", info.securityRealmName); assertEquals("DIGEST", info.authMethod); assertEquals("CONFIDENTIAL", info.transportGuarantee); + assertEquals("Timestamp", portInfo.properties.getProperty("wss4j.in.action")); + assertEquals("Timestamp", portInfo.properties.getProperty("wss4j.out.action")); } } Index: container/openejb-jee/src/main/java/org/apache/openejb/jee/oejb2/WebServiceSecurityType.java =================================================================== --- container/openejb-jee/src/main/java/org/apache/openejb/jee/oejb2/WebServiceSecurityType.java (revision 738353) +++ container/openejb-jee/src/main/java/org/apache/openejb/jee/oejb2/WebServiceSecurityType.java (working copy) @@ -19,11 +19,16 @@ import java.util.ArrayList; import java.util.List; +import java.util.Properties; + import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import org.apache.openejb.jee.oejb3.PropertiesAdapter; + /** *

Java class for web-service-securityType complex type. @@ -54,7 +59,8 @@ "realmName", "transportGuarantee", "authMethod", - "httpMethod" + "httpMethod", + "properties" }) public class WebServiceSecurityType { @@ -68,6 +74,9 @@ protected AuthMethodType authMethod; @XmlElement(name = "http-method") protected List httpMethod; + @XmlElement(name = "properties", required = false) + @XmlJavaTypeAdapter(PropertiesAdapter.class) + protected Properties properties; /** * Gets the value of the securityRealmName property. @@ -194,4 +203,16 @@ return this.httpMethod; } + public Properties getProperties() { + if (null == properties) { + properties = new Properties(); + } + return properties; + } + + public void setProperties(Properties properties) { + this.properties = properties; + } + + } Index: examples/webservice-ws-security/keys/ReadME.txt =================================================================== --- examples/webservice-ws-security/keys/ReadME.txt (revision 0) +++ examples/webservice-ws-security/keys/ReadME.txt (revision 0) @@ -0,0 +1,4 @@ +These scripts generate keys used for encryption and digital signature. +clientStore contains client private key ( alias : clientalias ) and server public key ( alias : serveralias ). +serverStore contains server private key ( alias : serveralias ) and client public key ( alias : clientalias ). +After generation copy serverStore.jks and clientStore.jks to the right directory. \ No newline at end of file Index: examples/webservice-ws-security/keys/generateKeyPair.bat =================================================================== --- examples/webservice-ws-security/keys/generateKeyPair.bat (revision 0) +++ examples/webservice-ws-security/keys/generateKeyPair.bat (revision 0) @@ -0,0 +1,11 @@ +rem @echo off +echo alias %1 +echo keypass %2 +echo keystoreName %3 +echo KeyStorePass %4 +echo keyName %5 + +echo keyName %5 +keytool -genkey -alias %1 -keypass %2 -keystore %3 -storepass %4 -dname "cn=%1" -keyalg RSA +keytool -selfcert -alias %1 -keystore %3 -storepass %4 -keypass %2 +keytool -export -alias %1 -file %5 -keystore %3 -storepass %4 Index: examples/webservice-ws-security/keys/generateServerKey.bat =================================================================== --- examples/webservice-ws-security/keys/generateServerKey.bat (revision 0) +++ examples/webservice-ws-security/keys/generateServerKey.bat (revision 0) @@ -0,0 +1,4 @@ +call generateKeyPair.bat serveralias serverPassword serverStore.jks keystorePass serverKey.rsa +call generateKeyPair.bat clientalias clientPassword clientStore.jks keystorePass clientKey.rsa +keytool -import -alias serveralias -file serverKey.rsa -keystore clientStore.jks -storepass keystorePass -noprompt +keytool -import -alias clientalias -file clientKey.rsa -keystore serverStore.jks -storepass keystorePass -noprompt \ No newline at end of file Index: examples/webservice-ws-security/src/main/java/org/superbiz/calculator/CalculatorImpl.java =================================================================== --- examples/webservice-ws-security/src/main/java/org/superbiz/calculator/CalculatorImpl.java (revision 756285) +++ examples/webservice-ws-security/src/main/java/org/superbiz/calculator/CalculatorImpl.java (working copy) @@ -42,7 +42,6 @@ return add1 + add2; } - @RolesAllowed(value={"Administrator"}) public int multiply(int mul1, int mul2) { return mul1 * mul2; } Index: examples/webservice-ws-security/src/main/resources/META-INF/CalculatorImplSign-server.properties =================================================================== --- examples/webservice-ws-security/src/main/resources/META-INF/CalculatorImplSign-server.properties (revision 0) +++ examples/webservice-ws-security/src/main/resources/META-INF/CalculatorImplSign-server.properties (revision 0) @@ -0,0 +1,5 @@ +org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin +org.apache.ws.security.crypto.merlin.keystore.type=jks +org.apache.ws.security.crypto.merlin.keystore.password=keystorePass +org.apache.ws.security.crypto.merlin.keystore.alias=serveralias +org.apache.ws.security.crypto.merlin.file=META-INF/serverStore.jks Index: examples/webservice-ws-security/src/main/resources/META-INF/CalculatorImplUsernameTokenPlainPasswordEncrypt-server.properties =================================================================== --- examples/webservice-ws-security/src/main/resources/META-INF/CalculatorImplUsernameTokenPlainPasswordEncrypt-server.properties (revision 0) +++ examples/webservice-ws-security/src/main/resources/META-INF/CalculatorImplUsernameTokenPlainPasswordEncrypt-server.properties (revision 0) @@ -0,0 +1,5 @@ +org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin +org.apache.ws.security.crypto.merlin.keystore.type=jks +org.apache.ws.security.crypto.merlin.keystore.password=keystorePass +org.apache.ws.security.crypto.merlin.keystore.alias=serveralias +org.apache.ws.security.crypto.merlin.file=META-INF/serverStore.jks Index: examples/webservice-ws-security/src/main/resources/META-INF/ejb-jar.xml =================================================================== --- examples/webservice-ws-security/src/main/resources/META-INF/ejb-jar.xml (revision 756285) +++ examples/webservice-ws-security/src/main/resources/META-INF/ejb-jar.xml (working copy) @@ -1 +1,64 @@ - \ No newline at end of file + + + + + + + CalculatorImplTimestamp1way + org.superbiz.calculator.CalculatorWs + org.superbiz.calculator.CalculatorImpl + + + + CalculatorImplTimestamp2ways + org.superbiz.calculator.CalculatorWs + org.superbiz.calculator.CalculatorImpl + + + + CalculatorImplUsernameTokenPlainPassword + org.superbiz.calculator.CalculatorWs + org.superbiz.calculator.CalculatorImpl + + + + CalculatorImplUsernameTokenHashedPassword + org.superbiz.calculator.CalculatorWs + org.superbiz.calculator.CalculatorImpl + + + + CalculatorImplUsernameTokenPlainPasswordEncrypt + org.superbiz.calculator.CalculatorWs + org.superbiz.calculator.CalculatorImpl + + + + CalculatorImplSign + org.superbiz.calculator.CalculatorWs + org.superbiz.calculator.CalculatorImpl + + + + CalculatorImplEncrypt2ways + org.superbiz.calculator.CalculatorWs + org.superbiz.calculator.CalculatorImpl + + + + CalculatorImplSign2ways + org.superbiz.calculator.CalculatorWs + org.superbiz.calculator.CalculatorImpl + + + + CalculatorImplEncryptAndSign2ways + org.superbiz.calculator.CalculatorWs + org.superbiz.calculator.CalculatorImpl + + + + + Index: examples/webservice-ws-security/src/main/resources/META-INF/openejb-jar.xml =================================================================== --- examples/webservice-ws-security/src/main/resources/META-INF/openejb-jar.xml (revision 756285) +++ examples/webservice-ws-security/src/main/resources/META-INF/openejb-jar.xml (working copy) @@ -6,6 +6,91 @@ NONE WS-SECURITY + + wss4j.in.action = UsernameToken + wss4j.in.passwordType = PasswordText + + + + + + CalculatorImplTimestamp1way + + + NONE + WS-SECURITY + + wss4j.in.action = Timestamp + + + + + + CalculatorImplTimestamp2ways + + + NONE + WS-SECURITY + + wss4j.in.action = Timestamp + wss4j.out.action = Timestamp + + + + + + CalculatorImplUsernameTokenPlainPassword + + + NONE + WS-SECURITY + + wss4j.in.action = UsernameToken + wss4j.in.passwordType = PasswordText + + + + + + CalculatorImplUsernameTokenHashedPassword + + + NONE + WS-SECURITY + + wss4j.in.action = UsernameToken + wss4j.in.passwordType = PasswordDigest + wss4j.in.passwordCallbackClass=org.superbiz.calculator.CustomPasswordHandler + + + + + + CalculatorImplUsernameTokenPlainPasswordEncrypt + + + NONE + WS-SECURITY + + wss4j.in.action = UsernameToken Encrypt + wss4j.in.passwordType = PasswordText + wss4j.in.passwordCallbackClass=org.superbiz.calculator.CustomPasswordHandler + wss4j.in.decryptionPropFile = META-INF/CalculatorImplUsernameTokenPlainPasswordEncrypt-server.properties + + + + + + CalculatorImplSign + + + NONE + WS-SECURITY + + wss4j.in.action = Signature + wss4j.in.passwordCallbackClass=org.superbiz.calculator.CustomPasswordHandler + wss4j.in.signaturePropFile = META-INF/CalculatorImplSign-server.properties + Index: examples/webservice-ws-security/src/main/resources/META-INF/webservices.xml =================================================================== --- examples/webservice-ws-security/src/main/resources/META-INF/webservices.xml (revision 0) +++ examples/webservice-ws-security/src/main/resources/META-INF/webservices.xml (revision 0) @@ -0,0 +1,51 @@ + + + + + CalculatorWsService + + CalculatorImplTimestamp1way + CalculatorImplTimestamp1way + org.superbiz.calculator.CalculatorWs + + CalculatorImplTimestamp1way + + + + CalculatorImplTimestamp2ways + CalculatorImplTimestamp2ways + org.superbiz.calculator.CalculatorWs + + CalculatorImplTimestamp2ways + + + + CalculatorImplUsernameTokenPlainPassword + CalculatorImplUsernameTokenPlainPassword + org.superbiz.calculator.CalculatorWs + + CalculatorImplUsernameTokenPlainPassword + + + + CalculatorImplUsernameTokenHashedPassword + CalculatorImplUsernameTokenHashedPassword + org.superbiz.calculator.CalculatorWs + + CalculatorImplUsernameTokenHashedPassword + + + + CalculatorImplUsernameTokenPlainPasswordEncrypt + CalculatorImplUsernameTokenPlainPasswordEncrypt + org.superbiz.calculator.CalculatorWs + + CalculatorImplUsernameTokenPlainPasswordEncrypt + + + + + \ No newline at end of file Index: examples/webservice-ws-security/src/test/java/org/superbiz/calculator/CalculatorTest.java =================================================================== --- examples/webservice-ws-security/src/test/java/org/superbiz/calculator/CalculatorTest.java (revision 756285) +++ examples/webservice-ws-security/src/test/java/org/superbiz/calculator/CalculatorTest.java (working copy) @@ -20,6 +20,7 @@ import org.apache.cxf.endpoint.Client; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.frontend.ClientProxy; +import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor; import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor; import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor; import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor; @@ -32,7 +33,12 @@ import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; +import javax.xml.namespace.QName; +import javax.xml.ws.Binding; +import javax.xml.ws.BindingType; import javax.xml.ws.Service; +import javax.xml.ws.soap.SOAPBinding; + import java.io.IOException; import java.net.URL; import java.util.HashMap; @@ -60,9 +66,110 @@ */ //START SNIPPET: webservice public void testCalculatorViaWsInterface() throws Exception { - Service calcService = Service.create(new URL("http://127.0.0.1:4204/CalculatorImpl?wsdl"), null); + Service calcService = Service.create(new URL("http://127.0.0.1:4204/CalculatorImpl?wsdl"), + new QName("http://superbiz.org/wsdl", "CalculatorWsService")); + assertNotNull(calcService); + + CalculatorWs calc = calcService.getPort(CalculatorWs.class); + + Client client = ClientProxy.getClient(calc); + Endpoint endpoint = client.getEndpoint(); + endpoint.getOutInterceptors().add(new SAAJOutInterceptor()); + + Map outProps = new HashMap(); + outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); + outProps.put(WSHandlerConstants.USER, "jane"); + outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); + outProps.put(WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() { + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; + pc.setPassword("waterfall"); + } + }); + + WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); + endpoint.getOutInterceptors().add(wssOut); + + assertEquals(10, calc.sum(4,6)); + } + + public void testCalculatorViaWsInterfaceWithTimestamp1way() throws Exception { + Service calcService = Service.create(new URL("http://127.0.0.1:4204/CalculatorImplTimestamp1way?wsdl"), + new QName("http://superbiz.org/wsdl", "CalculatorWsService")); + assertNotNull(calcService); + + // for debugging (ie. TCPMon) + calcService.addPort(new QName("http://superbiz.org/wsdl", + "CalculatorWsService2"), SOAPBinding.SOAP12HTTP_BINDING, + "http://127.0.0.1:8204/CalculatorImplTimestamp1way"); + +// CalculatorWs calc = calcService.getPort( +// new QName("http://superbiz.org/wsdl", "CalculatorWsService2"), +// CalculatorWs.class); + + CalculatorWs calc = calcService.getPort(CalculatorWs.class); + + Client client = ClientProxy.getClient(calc); + Endpoint endpoint = client.getEndpoint(); + endpoint.getOutInterceptors().add(new SAAJOutInterceptor()); + + Map outProps = new HashMap(); + outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP); + WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); + endpoint.getOutInterceptors().add(wssOut); + + assertEquals(12, calc.multiply(3,4)); + } + + public void testCalculatorViaWsInterfaceWithTimestamp2ways() throws Exception { + Service calcService = Service.create(new URL("http://127.0.0.1:4204/CalculatorImplTimestamp2ways?wsdl"), + new QName("http://superbiz.org/wsdl", "CalculatorWsService")); + assertNotNull(calcService); + + // for debugging (ie. TCPMon) + calcService.addPort(new QName("http://superbiz.org/wsdl", + "CalculatorWsService2"), SOAPBinding.SOAP12HTTP_BINDING, + "http://127.0.0.1:8204/CalculatorImplTimestamp2ways"); + +// CalculatorWs calc = calcService.getPort( +// new QName("http://superbiz.org/wsdl", "CalculatorWsService2"), +// CalculatorWs.class); + + CalculatorWs calc = calcService.getPort(CalculatorWs.class); + + Client client = ClientProxy.getClient(calc); + Endpoint endpoint = client.getEndpoint(); + endpoint.getOutInterceptors().add(new SAAJOutInterceptor()); + endpoint.getInInterceptors().add(new SAAJInInterceptor()); + + Map outProps = new HashMap(); + outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP); + WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); + endpoint.getOutInterceptors().add(wssOut); + + Map inProps = new HashMap(); + inProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP); + WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps); + endpoint.getInInterceptors().add(wssIn); + + assertEquals(12, calc.multiply(3,4)); + } + + public void testCalculatorViaWsInterfaceWithUsernameTokenPlainPassword() throws Exception { + Service calcService = Service.create(new URL("http://127.0.0.1:4204/CalculatorImplUsernameTokenPlainPassword?wsdl"), + new QName("http://superbiz.org/wsdl", "CalculatorWsService")); assertNotNull(calcService); + // for debugging (ie. TCPMon) + calcService.addPort(new QName("http://superbiz.org/wsdl", + "CalculatorWsService2"), SOAPBinding.SOAP12HTTP_BINDING, + "http://127.0.0.1:8204/CalculatorImplUsernameTokenPlainPassword"); + +// CalculatorWs calc = calcService.getPort( +// new QName("http://superbiz.org/wsdl", "CalculatorWsService2"), +// CalculatorWs.class); + CalculatorWs calc = calcService.getPort(CalculatorWs.class); Client client = ClientProxy.getClient(calc); @@ -85,7 +192,124 @@ endpoint.getOutInterceptors().add(wssOut); assertEquals(10, calc.sum(4,6)); - assertEquals(12, calc.multiply(3,4)); + } + + public void testCalculatorViaWsInterfaceWithUsernameTokenHashedPassword() throws Exception { + Service calcService = Service.create(new URL("http://127.0.0.1:4204/CalculatorImplUsernameTokenHashedPassword?wsdl"), + new QName("http://superbiz.org/wsdl", "CalculatorWsService")); + assertNotNull(calcService); + + // for debugging (ie. TCPMon) + calcService.addPort(new QName("http://superbiz.org/wsdl", + "CalculatorWsService2"), SOAPBinding.SOAP12HTTP_BINDING, + "http://127.0.0.1:8204/CalculatorImplUsernameTokenHashedPassword"); + +// CalculatorWs calc = calcService.getPort( +// new QName("http://superbiz.org/wsdl", "CalculatorWsService2"), +// CalculatorWs.class); + + CalculatorWs calc = calcService.getPort(CalculatorWs.class); + + Client client = ClientProxy.getClient(calc); + Endpoint endpoint = client.getEndpoint(); + endpoint.getOutInterceptors().add(new SAAJOutInterceptor()); + + Map outProps = new HashMap(); + outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); + outProps.put(WSHandlerConstants.USER, "jane"); + outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST); + outProps.put(WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() { + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; + pc.setPassword("waterfall"); + } + }); + + WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); + endpoint.getOutInterceptors().add(wssOut); + + assertEquals(10, calc.sum(4,6)); + } + + public void testCalculatorViaWsInterfaceWithUsernameTokenPlainPasswordEncrypt() throws Exception { + Service calcService = Service.create(new URL("http://127.0.0.1:4204/CalculatorImplUsernameTokenPlainPasswordEncrypt?wsdl"), + new QName("http://superbiz.org/wsdl", "CalculatorWsService")); + assertNotNull(calcService); + + // for debugging (ie. TCPMon) + calcService.addPort(new QName("http://superbiz.org/wsdl", + "CalculatorWsService2"), SOAPBinding.SOAP12HTTP_BINDING, + "http://127.0.0.1:8204/CalculatorImplUsernameTokenPlainPasswordEncrypt"); + +// CalculatorWs calc = calcService.getPort( +// new QName("http://superbiz.org/wsdl", "CalculatorWsService2"), +// CalculatorWs.class); + + CalculatorWs calc = calcService.getPort(CalculatorWs.class); + + Client client = ClientProxy.getClient(calc); + Endpoint endpoint = client.getEndpoint(); + endpoint.getOutInterceptors().add(new SAAJOutInterceptor()); + + Map outProps = new HashMap(); + outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN + + " " + WSHandlerConstants.ENCRYPT); + outProps.put(WSHandlerConstants.USER, "jane"); + outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); + outProps.put(WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() { + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; + pc.setPassword("waterfall"); + } + }); + outProps.put(WSHandlerConstants.ENC_PROP_FILE, "META-INF/CalculatorImplUsernameTokenPlainPasswordEncrypt-client.properties"); + outProps.put(WSHandlerConstants.ENCRYPTION_USER, "serveralias"); + + WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); + endpoint.getOutInterceptors().add(wssOut); + + assertEquals(10, calc.sum(4,6)); + } + + public void testCalculatorViaWsInterfaceWithSign() throws Exception { + Service calcService = Service.create(new URL("http://127.0.0.1:4204/CalculatorImplSign?wsdl"), + new QName("http://superbiz.org/wsdl", "CalculatorWsService")); + assertNotNull(calcService); + + // for debugging (ie. TCPMon) + calcService.addPort(new QName("http://superbiz.org/wsdl", + "CalculatorWsService2"), SOAPBinding.SOAP12HTTP_BINDING, + "http://127.0.0.1:8204/CalculatorImplSign"); + +// CalculatorWs calc = calcService.getPort( +// new QName("http://superbiz.org/wsdl", "CalculatorWsService2"), +// CalculatorWs.class); + + CalculatorWs calc = calcService.getPort(CalculatorWs.class); + + Client client = ClientProxy.getClient(calc); + Endpoint endpoint = client.getEndpoint(); + endpoint.getOutInterceptors().add(new SAAJOutInterceptor()); + + Map outProps = new HashMap(); + outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.SIGNATURE); + outProps.put(WSHandlerConstants.USER, "clientalias"); + outProps.put(WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() { + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; + pc.setPassword("clientPassword"); + } + }); + outProps.put(WSHandlerConstants.SIG_PROP_FILE, "META-INF/CalculatorImplSign-client.properties"); + outProps.put(WSHandlerConstants.SIG_KEY_ID, "IssuerSerial"); + + WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); + endpoint.getOutInterceptors().add(wssOut); + + assertEquals(24, calc.multiply(4,6)); } //END SNIPPET: webservice Index: examples/webservice-ws-security/src/test/java/org/superbiz/calculator/CustomPasswordHandler.java =================================================================== --- examples/webservice-ws-security/src/test/java/org/superbiz/calculator/CustomPasswordHandler.java (revision 0) +++ examples/webservice-ws-security/src/test/java/org/superbiz/calculator/CustomPasswordHandler.java (revision 0) @@ -0,0 +1,67 @@ +/** + * 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 org.superbiz.calculator; + +import org.apache.ws.security.WSPasswordCallback; +import org.apache.openejb.loader.SystemInstance; +import org.apache.openejb.spi.SecurityService; + +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.auth.login.LoginException; +import java.io.IOException; + +public class CustomPasswordHandler implements CallbackHandler { + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { + WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]; + + if(pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN) { + // TODO get the password from the users.properties if possible + pc.setPassword("waterfall"); + + } else if(pc.getUsage() == WSPasswordCallback.DECRYPT) { + pc.setPassword("serverPassword"); + + } else if(pc.getUsage() == WSPasswordCallback.SIGNATURE) { + pc.setPassword("serverPassword"); + + } + + if ((pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN) + || (pc.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN)) { + + SecurityService securityService = SystemInstance.get() + .getComponent(SecurityService.class); + Object token = null; + try { + securityService.disassociate(); + + token = securityService.login(pc.getIdentifer(), pc.getPassword()); + securityService.associate(token); + + } catch (LoginException e) { + e.printStackTrace(); + throw new SecurityException("wrong password"); + } finally { + } + } + + + } +} Index: examples/webservice-ws-security/src/test/resources/META-INF/CalculatorImplSign-client.properties =================================================================== --- examples/webservice-ws-security/src/test/resources/META-INF/CalculatorImplSign-client.properties (revision 0) +++ examples/webservice-ws-security/src/test/resources/META-INF/CalculatorImplSign-client.properties (revision 0) @@ -0,0 +1,5 @@ +org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin +org.apache.ws.security.crypto.merlin.keystore.type=jks +org.apache.ws.security.crypto.merlin.keystore.password=keystorePass +org.apache.ws.security.crypto.merlin.keystore.alias=clientalias +org.apache.ws.security.crypto.merlin.file=META-INF/clientStore.jks Index: examples/webservice-ws-security/src/test/resources/META-INF/CalculatorImplUsernameTokenPlainPasswordEncrypt-client.properties =================================================================== --- examples/webservice-ws-security/src/test/resources/META-INF/CalculatorImplUsernameTokenPlainPasswordEncrypt-client.properties (revision 0) +++ examples/webservice-ws-security/src/test/resources/META-INF/CalculatorImplUsernameTokenPlainPasswordEncrypt-client.properties (revision 0) @@ -0,0 +1,5 @@ +org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin +org.apache.ws.security.crypto.merlin.keystore.type=jks +org.apache.ws.security.crypto.merlin.keystore.password=keystorePass +org.apache.ws.security.crypto.merlin.keystore.alias=clientalias +org.apache.ws.security.crypto.merlin.file=META-INF/clientStore.jks Index: examples/webservice-ws-security/pom.xml =================================================================== --- examples/webservice-ws-security/pom.xml (revision 756285) +++ examples/webservice-ws-security/pom.xml (working copy) @@ -1,107 +1,237 @@ - - 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. ---> + - + + 4.0.0 + org.superbiz + webservice-ws-security + jar + 1.1-SNAPSHOT + OpenEJB :: Web Examples :: EJB WebService with WS-Security + + + org.apache.openejb + javaee-api + 5.0-1 + provided + + + org.apache.openejb + openejb-client + 3.1.1-SNAPSHOT + provided + + + org.apache.openejb + openejb-core + 3.1.1-SNAPSHOT + provided + + + org.apache.openejb + openejb-cxf + 3.1.1-SNAPSHOT + test + + + junit + junit + 4.4 + test + + + xalan + xalan + 2.6.0 + test + + + + install - - 4.0.0 - org.superbiz - webservice-ws-security - jar - 1.1-SNAPSHOT - OpenEJB :: Web Examples :: EJB WebService with WS-Security - - - org.apache.openejb - javaee-api - 5.0-1 - provided - - - org.apache.openejb - openejb-client - 3.1.1-SNAPSHOT - provided - - - org.apache.openejb - openejb-core - 3.1.1-SNAPSHOT - provided - - - org.apache.openejb - openejb-cxf - 3.1.1-SNAPSHOT - test - - - junit - junit - 4.4 - test - - - - install + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.2 + + + - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.2 - - - + + + maven-compiler-plugin + + 1.5 + 1.5 + + + + org.apache.maven.plugins + maven-clover-plugin + + 1.5 + + **/package-info.java + + + + + site + pre-site + + instrument + aggregate + save-history + + + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.3 + + + generate-keys + process-test-resources + + run + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - maven-compiler-plugin - - 1.5 - 1.5 - - - - org.apache.maven.plugins - maven-clover-plugin - - 1.5 - - **/package-info.java - - - - - site - pre-site - - instrument - aggregate - save-history - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - Index: server/openejb-cxf/src/main/java/org/apache/openejb/server/cxf/ejb/EjbEndpoint.java =================================================================== --- server/openejb-cxf/src/main/java/org/apache/openejb/server/cxf/ejb/EjbEndpoint.java (revision 751297) +++ server/openejb-cxf/src/main/java/org/apache/openejb/server/cxf/ejb/EjbEndpoint.java (working copy) @@ -30,6 +30,7 @@ import org.apache.openejb.DeploymentInfo; import org.apache.openejb.core.webservices.JaxWsUtils; import org.apache.openejb.core.webservices.PortData; +import org.apache.openejb.server.cxf.ConfigureCxfSecurity; import org.apache.openejb.server.cxf.CxfEndpoint; import org.apache.openejb.server.cxf.CxfServiceConfiguration; import org.apache.openejb.server.cxf.JaxWsImplementorInfoImpl; @@ -95,13 +96,7 @@ // Install WSS4J interceptor if (port.isSecure()) { - Map inProps = new HashMap(); - inProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); - inProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); - inProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ServerPasswordHandler.class.getName()); - - WSS4JInInterceptor wssIn = new WSS4JInInterceptor(inProps); - endpoint.getInInterceptors().add(wssIn); + ConfigureCxfSecurity.configure(endpoint, port.getSecurityProperties()); } } Index: server/openejb-cxf/src/main/java/org/apache/openejb/server/cxf/ConfigureCxfSecurity.java =================================================================== --- server/openejb-cxf/src/main/java/org/apache/openejb/server/cxf/ConfigureCxfSecurity.java (revision 0) +++ server/openejb-cxf/src/main/java/org/apache/openejb/server/cxf/ConfigureCxfSecurity.java (revision 0) @@ -0,0 +1,65 @@ +package org.apache.openejb.server.cxf; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.apache.cxf.binding.soap.saaj.SAAJInInterceptor; +import org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor; +import org.apache.cxf.endpoint.Endpoint; +import org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor; +import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor; +import org.apache.ws.security.handler.WSHandlerConstants; + +/** + * Helper class to extract WSS4J properties from a set of properties. More over, + * it configures In and Out interceptor to manage WS6Security. + * + */ +public class ConfigureCxfSecurity { + + public static final void setupWSS4JChain(Endpoint endpoint, Properties inProps) { + + Map in = getPropsFromProperties(inProps, "wss4j.in."); + Map out = getPropsFromProperties(inProps, "wss4j.out."); + setupWSS4JChain(endpoint, in, out); + } + + public static Map getPropsFromProperties(Properties inProps, String pattern) { + String key, val; + + Map props = new HashMap(); + for (Map.Entry entry : inProps.entrySet()) { + key = String.valueOf(entry.getKey()); + val = String.valueOf(entry.getValue()).trim(); + if (key.startsWith(pattern)) { + props.put(key.substring(pattern.length()), val); + } + } + if (!props.isEmpty()) { + // WSHandler first look for a property PW_CALLBACK_CLASS + // if not found, it gets the PW_CALLBACK_REF + props.put(WSHandlerConstants.PW_CALLBACK_REF, new ServerPasswordHandler()); + } + return props; + } + + public static final void setupWSS4JChain(Endpoint endpoint, Map inProps, Map outProps) { + + if (null != inProps && !inProps.isEmpty()) { + endpoint.getInInterceptors().add(new SAAJInInterceptor()); + endpoint.getInInterceptors().add(new WSS4JInInterceptor(inProps)); + } + + if (null != outProps && !outProps.isEmpty()) { + endpoint.getOutInterceptors().add(new SAAJOutInterceptor()); + endpoint.getOutInterceptors().add(new WSS4JOutInterceptor(outProps)); + } + + } + + public static final void configure(Endpoint endpoint, Properties p) { + setupWSS4JChain(endpoint, p); + } + +} Index: server/openejb-cxf/pom.xml =================================================================== --- server/openejb-cxf/pom.xml (revision 767485) +++ server/openejb-cxf/pom.xml (working copy) @@ -24,7 +24,7 @@ server org.apache.openejb 3.1.1-SNAPSHOT - + 4.0.0 openejb-cxf jar @@ -78,7 +78,7 @@ org.apache.cxf cxf-bundle - 2.0.4-incubator + 2.0.9 aopalliance @@ -209,6 +209,10 @@ velocity + wss4j + wss4j + + xalan xalan @@ -217,6 +221,10 @@ xml-apis + xml-security + xmlsec + + xmlbeans xbean