Author: keith Date: Thu Jul 10 02:51:59 2008 New Revision: 19084 URL: http://wso2.org/svn/browse/wso2?view=rev&revision=19084
Log: Adding support for using keystores when calling secured services. With this un place we can talk to services that engage security scenario2 Added: trunk/mashup/java/modules/hostobjects/src/org/wso2/mashup/hostobjects/wsrequest/PasswordCallbackHandler.java Modified: trunk/mashup/java/modules/core/src/org/wso2/mashup/MashupConstants.java trunk/mashup/java/modules/hostobjects/src/org/wso2/mashup/hostobjects/wsrequest/WSRequestHostImpl.java Modified: trunk/mashup/java/modules/core/src/org/wso2/mashup/MashupConstants.java URL: http://wso2.org/svn/browse/wso2/trunk/mashup/java/modules/core/src/org/wso2/mashup/MashupConstants.java?rev=19084&r1=19083&r2=19084&view=diff ============================================================================== --- trunk/mashup/java/modules/core/src/org/wso2/mashup/MashupConstants.java (original) +++ trunk/mashup/java/modules/core/src/org/wso2/mashup/MashupConstants.java Thu Jul 10 02:51:59 2008 @@ -62,6 +62,7 @@ public static final String SECURITY_CONFIG_KEYSTORE_PASSWORD = "Password"; public static final String SECURITY_CONFIG_KEYSTORE_KEYALIAS = "KeyAlias"; public static final String SECURITY_CONFIG_KEYSTORE_KEYPASSWORD = "KeyPassword"; + public static final String SECURITY_CONFIG_KEYSTORE_KEYSTOREDIR = "KeyStoresDir"; public static final String EMAIL_RELAY_HOST = "email_relay_host"; public static final String WEBAPP_URL = "webapp_url"; Added: trunk/mashup/java/modules/hostobjects/src/org/wso2/mashup/hostobjects/wsrequest/PasswordCallbackHandler.java URL: http://wso2.org/svn/browse/wso2/trunk/mashup/java/modules/hostobjects/src/org/wso2/mashup/hostobjects/wsrequest/PasswordCallbackHandler.java?pathrev=19084 ============================================================================== --- (empty file) +++ trunk/mashup/java/modules/hostobjects/src/org/wso2/mashup/hostobjects/wsrequest/PasswordCallbackHandler.java Thu Jul 10 02:51:59 2008 @@ -0,0 +1,128 @@ +package org.wso2.mashup.hostobjects.wsrequest; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.ws.security.WSPasswordCallback; +import org.wso2.mashup.MashupConstants; +import org.wso2.utils.ServerConfiguration; +import org.wso2.utils.security.CryptoException; +import org.wso2.utils.security.CryptoUtil; +import org.wso2.wsas.persistence.PersistenceManager; +import org.wso2.wsas.persistence.dataobject.KeyStoreDO; +import org.wso2.wsas.persistence.dataobject.ServiceUserDO; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; +import java.io.File; +import java.io.IOException; + +public class PasswordCallbackHandler implements CallbackHandler { + + private static final Log log = LogFactory.getLog(PasswordCallbackHandler.class); + private String mashupUserName; + + public PasswordCallbackHandler(String mashupUserName) { + this.mashupUserName = mashupUserName; + } + + public void handle(Callback[] callbacks) throws IOException, + UnsupportedCallbackException { + for (int i = 0; i < callbacks.length; i++) { + if (callbacks[i] instanceof WSPasswordCallback) { + WSPasswordCallback passwordCallback = (WSPasswordCallback) callbacks[i]; + + String username = passwordCallback.getIdentifer(); + String storedPasswd = getPassword(username); + + switch (passwordCallback.getUsage()) { + + case WSPasswordCallback.SIGNATURE: + case WSPasswordCallback.DECRYPT: + passwordCallback.setPassword(this.getPrivateKeyPassword()); + break; + + case WSPasswordCallback.USERNAME_TOKEN_UNKNOWN: + + String receivedPasswd = passwordCallback.getPassword(); + boolean authneticated = receivedPasswd != null && + receivedPasswd.equals(storedPasswd); + if (!authneticated) { + throw new UnsupportedCallbackException(callbacks[i], + "check failed"); + } + + break; + default: + + /* + * When the password is null WS4J reports an error saying + * no password available for the user. But its better if we + * simply report authentication failure + * Therefore setting the password to be the empty string in this + * situation. + */ + if (storedPasswd == null) { + storedPasswd = ""; + } + passwordCallback.setPassword(storedPasswd); + break; + + } + + + } else { + throw new UnsupportedCallbackException(callbacks[i], + "Unrecognized Callback"); + } + } + } + + + private String getPrivateKeyPassword() throws IOException { + PersistenceManager pm = new PersistenceManager(); + KeyStoreDO ksDO = pm.getKeyStore(mashupUserName + MashupConstants.KEY_STORE_SUFFIX); + try { + ServerConfiguration config = ServerConfiguration.getInstance(); + CryptoUtil cryptoUtil = + new CryptoUtil(new File(config.getFirstProperty( + "Security.KeyStore.Location")).getAbsolutePath(), + config.getFirstProperty("Security.KeyStore.Password"), + config.getFirstProperty("Security.KeyStore.KeyAlias"), + config.getFirstProperty("Security.KeyStore.KeyPassword"), + config.getFirstProperty("Security.KeyStore.Type")); + return new String(cryptoUtil.base64DecodeAndDecrypt(ksDO.getPrivateKeyPassword())); + } catch (CryptoException e) { + throw new IOException(e.getMessage()); + } + } + + /** + * @param username The username of the user + * @return The password corresponding to the username + */ + private String getPassword(String username) { + PersistenceManager pm = new PersistenceManager(); + + ServiceUserDO serviceUser = pm.getUser(username); + if (serviceUser == null) { // user does not exist? + return null; + } + + String password = null; + try { + ServerConfiguration config = ServerConfiguration.getInstance(); + CryptoUtil cryptoUtil = + new CryptoUtil(new File(config.getFirstProperty( + "Security.KeyStore.Location")).getAbsolutePath(), + config.getFirstProperty("Security.KeyStore.Password"), + config.getFirstProperty("Security.KeyStore.KeyAlias"), + config.getFirstProperty("Security.KeyStore.KeyPassword"), + config.getFirstProperty("Security.KeyStore.Type")); + password = new String(cryptoUtil.base64DecodeAndDecrypt(serviceUser.getPassword())); + } catch (CryptoException e) { + log.error("Exception occurred while decrypting password", e); + } + return password; + } +} Modified: trunk/mashup/java/modules/hostobjects/src/org/wso2/mashup/hostobjects/wsrequest/WSRequestHostImpl.java URL: http://wso2.org/svn/browse/wso2/trunk/mashup/java/modules/hostobjects/src/org/wso2/mashup/hostobjects/wsrequest/WSRequestHostImpl.java?rev=19084&r1=19083&r2=19084&view=diff ============================================================================== --- trunk/mashup/java/modules/hostobjects/src/org/wso2/mashup/hostobjects/wsrequest/WSRequestHostImpl.java (original) +++ trunk/mashup/java/modules/hostobjects/src/org/wso2/mashup/hostobjects/wsrequest/WSRequestHostImpl.java Thu Jul 10 02:51:59 2008 @@ -29,11 +29,10 @@ import org.apache.axis2.client.async.AxisCallback; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.context.ConfigurationContextFactory; -import org.apache.axis2.description.AxisOperation; +import org.apache.axis2.context.MessageContext; import org.apache.axis2.description.WSDL2Constants; import org.apache.axis2.description.AxisService; import org.apache.axis2.description.AxisEndpoint; -import org.apache.axis2.description.AxisDescription; import org.apache.axis2.description.AxisBindingMessage; import org.apache.axis2.transport.http.HTTPConstants; import org.apache.axis2.transport.http.HttpTransportProperties; @@ -49,10 +48,10 @@ import org.apache.rampart.RampartMessageData; import org.apache.rampart.policy.RampartPolicyBuilder; import org.apache.rampart.policy.RampartPolicyData; +import org.apache.rampart.policy.model.RampartConfig; +import org.apache.rampart.policy.model.CryptoConfig; import org.apache.ws.secpolicy.WSSPolicyException; -import org.apache.ws.secpolicy.model.SupportingToken; -import org.apache.ws.secpolicy.model.Token; -import org.apache.ws.secpolicy.model.UsernameToken; +import org.apache.ws.security.handler.WSHandlerConstants; import org.mozilla.javascript.Context; import org.mozilla.javascript.Function; import org.mozilla.javascript.NativeArray; @@ -67,6 +66,7 @@ import org.wso2.mashup.utils.MashupUtils; import org.wso2.wsas.ServerManager; import org.wso2.wsas.ServerConstants; +import org.wso2.utils.ServerConfiguration; import javax.wsdl.Definition; import javax.wsdl.Port; @@ -91,6 +91,10 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Properties; +import java.util.Enumeration; +import java.security.KeyStore; +import java.security.KeyStoreException; /** * <p/> @@ -684,29 +688,26 @@ //Process policy and build policy data RampartPolicyData policyData = RampartPolicyBuilder.build(it); if (policyData != null) { - SupportingToken supportingTokens = - policyData.getSignedSupportingTokens(); - if (policyData.isTransportBinding()) { - if (supportingTokens != null && - supportingTokens.getTokens() != null && - supportingTokens.getTokens().size() > 0) { - ArrayList tokens = supportingTokens.getTokens(); - for (Iterator iter = tokens.iterator(); iter.hasNext();) { - - Token token = (Token) iter.next(); - if (token instanceof UsernameToken) { - needRampart = true; - } else { - throw new MashupFault( - "unsupportedSignedSupportingToken " + - "{" + token.getName() - .getNamespaceURI() - + "}" + token.getName() - .getLocalPart()); - } - } - } - } + if (policyData.isAsymmetricBinding() || + policyData.isSymmetricBinding() || + policyData.isTransportBinding()) { + needRampart = true; + Policy attchPolicy = new Policy(); + + MessageContext currentMessageContext = + MessageContext.getCurrentMessageContext(); + // In order to get the users keystore details we need his username. We stick the + // username as a parameter into the service at deployment time + String authorName = (String) currentMessageContext.getAxisService() + .getParameterValue(MashupConstants.MASHUP_AUTHOR_NAME); + + + axisService.addParameter(WSHandlerConstants.PW_CALLBACK_REF, + new PasswordCallbackHandler(authorName)); + attchPolicy.addAssertion( + wsRequest.getRampartConfig(wsRequest, authorName)); + axisService.getPolicySubject().attachPolicy(attchPolicy); + } } } if (needRampart) { @@ -1051,4 +1052,68 @@ options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, protocol); } } + + private RampartConfig getRampartConfig(WSRequestHostImpl wsRequest, String authorName) throws MashupFault { + System.out.println( + "In this demonstration, client will use client.jks and server should use\n" + + "service.jks."); + RampartConfig rc = new RampartConfig(); + + CryptoConfig sigCryptoConfig = new CryptoConfig(); + + sigCryptoConfig.setProvider("org.apache.ws.security.components.crypto.Merlin"); + + ServerConfiguration serverConfig = ServerConfiguration.getInstance(); + + String keyStorePass = + serverConfig.getFirstProperty(MashupConstants.SECURITY_CONFIG + "." + + MashupConstants.SECURITY_CONFIG_KEYSTORE + "." + MashupConstants + .SECURITY_CONFIG_KEYSTORE_PASSWORD); + + String KeyStoresDir = + serverConfig.getFirstProperty(MashupConstants.SECURITY_CONFIG + "." + + MashupConstants.SECURITY_CONFIG_KEYSTORE_KEYSTOREDIR); + + KeyStore keyStore = MashupUtils.getUserKeyStore(authorName); + Enumeration enumeration; + String user = null; + try { + enumeration = keyStore.aliases(); + while (enumeration.hasMoreElements()) { + String alias = (String) enumeration.nextElement(); + if (keyStore.isKeyEntry(alias)) { + user = alias; + break; + } + }} catch (KeyStoreException e) { + throw new MashupFault(e); + } + rc.setUser(user); + + String keystore = KeyStoresDir + File.separator + authorName + + MashupConstants.KEY_STORE_SUFFIX; + + Properties prop1 = new Properties(); + prop1.put("org.apache.ws.security.crypto.merlin.keystore.type", "JKS"); + prop1.put("org.apache.ws.security.crypto.merlin.file", keystore); + prop1.put("org.apache.ws.security.crypto.merlin.keystore.password", keyStorePass); + sigCryptoConfig.setProp(prop1); + + CryptoConfig encrCryptoConfig = new CryptoConfig(); + encrCryptoConfig.setProvider("org.apache.ws.security.components.crypto.Merlin"); + + Properties prop2 = new Properties(); + + prop2.put("org.apache.ws.security.crypto.merlin.keystore.type", "JKS"); + + + prop2.put("org.apache.ws.security.crypto.merlin.file", keystore); + prop2.put("org.apache.ws.security.crypto.merlin.keystore.password", keyStorePass); + encrCryptoConfig.setProp(prop2); + + rc.setSigCryptoConfig(sigCryptoConfig); + rc.setEncrCryptoConfig(encrCryptoConfig); + + return rc; + } } \ No newline at end of file _______________________________________________ Mashup-dev mailing list [email protected] http://wso2.org/cgi-bin/mailman/listinfo/mashup-dev
