You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fx-dev@ws.apache.org by di...@apache.org on 2004/06/19 22:29:55 UTC
cvs commit: ws-fx/wss4j/src/org/apache/ws/security WSSecurityEngine.java
dims 2004/06/19 13:29:55
Modified: wss4j build.xml
wss4j/src/org/apache/ws/security/conversation
ConversationUtil.java
DerivedKeyCallbackHandler.java
wss4j/src/org/apache/ws/security/conversation/message/token
DerivedKeyToken.java RequestedProofToken.java
wss4j/src/org/apache/ws/security WSSecurityEngine.java
Added: wss4j/test/secconv build.xml Client_deploy.wsdd ping.wsdl
WSConvScenario1.java
wss4j/src/org/apache/ws/security/conversation
ConversationClientHandler.java
ConversationServerHandler.java
wss4j/test/secconv/ping deploy.wsdd PingBindingImpl.java
Log:
Checking in updates from Dimuthu et al.
Notes:
- separate test harness at test/secconv
Revision Changes Path
1.14 +6 -0 ws-fx/wss4j/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/build.xml,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- build.xml 30 May 2004 09:27:48 -0000 1.13
+++ build.xml 19 Jun 2004 20:29:55 -0000 1.14
@@ -347,9 +347,15 @@
<target name="compile.tests"
depends="compile.interops"
if="junit.present">
+ <ant dir="${dir.test}/secconv"
+ antfile="build.xml"
+ target="compile"
+ inheritAll="false">
+ </ant>
<!-- Compile the java code from ${dir.src} into ${build.classes} -->
<javac srcdir="${dir.test}" destdir="${build.classes}" debug="on">
<classpath refid="classpath.test"/>
+ <exclude name="**/secconv/*.java"/>
</javac>
<!-- Copy Property files -->
<copy todir="${build.classes}">
1.1 ws-fx/wss4j/test/secconv/build.xml
Index: build.xml
===================================================================
<project name="Axis_Secure_Conversation" default="compile">
<description>
generate files from WSDL description, also target to deploy
the service in a runing Axis (probably in Tomcat or alike)
</description>
<!-- The following setting assumes that all necessary libs (jars)
are located in a lib directory directly under wss4j. First set
a reference to the wss4j relative to this working directory -->
<property name="dir.wss4j" value="${basedir}/../.."/>
<property name="dir.secconv" value="${dir.wss4j}/test/secconv"/>
<property name="dir.work" value="${dir.wss4j}/build/work"/>
<property name="dir.classes" value="${dir.wss4j}/build/classes"/>
<property name="dir.libs" value="${dir.wss4j}/lib"/>
<property name="server" value="ping"/>
<property name="client" value=""/>
<path id="classpath.libraries" description=" 3rd party and Axis libs">
<fileset dir="${dir.libs}">
<include name="**/*.jar"/>
</fileset>
</path>
<taskdef resource="axis-tasks.properties" classpathref="classpath.libraries"/>
<target name="clientdeploy">
<java classname="org.apache.axis.utils.Admin" fork="true">
<classpath refid="classpath.libraries"/>
<arg value="client"/>
<arg file="${dir.work}/${client}/Client_deploy.wsdd"/>
</java>
</target>
<target name="serverdeploy">
<java classname="org.apache.axis.client.AdminClient" fork="true">
<classpath refid="classpath.libraries"/>
<arg file="${dir.work}/${server}/deploy.wsdd"/>
</java>
</target>
<target name="serverundeploy">
<java classname="org.apache.axis.client.AdminClient" fork="true">
<classpath refid="classpath.libraries"/>
<arg file="${dir.work}/${server}/undeploy.wsdd"/>
</java>
</target>
<target name="compile">
<mkdir dir="${dir.work}"/>
<axis-wsdl2java
output="${dir.work}"
serverSide="yes"
testcase="no"
verbose="no"
url="${dir.secconv}/ping.wsdl">
<mapping
namespace="http://xmlsoap.org/Ping"
package="secconv"/>
</axis-wsdl2java>
<copy todir="${dir.work}/${server}" overwrite="yes">
<fileset dir="${dir.secconv}/${server}">
<include name="*.java"/>
<include name="*.wsdd"/>
</fileset>
</copy>
<copy todir="${dir.work}/${client}" overwrite="yes">
<fileset dir="${dir.secconv}/${client}">
<include name="*.java"/>
<include name="*.wsdd"/>
</fileset>
</copy>
<javac srcdir="${dir.work}"
destdir="${dir.classes}"
debug="true">
<classpath refid="classpath.libraries" />
<include name="${server}/*.java" />
<include name="${client}/*.java" />
</javac>
</target>
<target name="clean"
description="clean up">
<delete dir="${dir.work}/${server}"/>
<delete dir="${dir.classes}/${server}"/>
<delete dir="${dir.work}/${client}"/>
<delete dir="${dir.classes}/${client}"/>
</target>
</project>
1.1 ws-fx/wss4j/test/secconv/Client_deploy.wsdd
Index: Client_deploy.wsdd
===================================================================
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="WSConvScenario1">
<requestFlow>
<handler type="java:org.apache.ws.axis.security.conversation.ConversationClientHandler" />
</requestFlow>
<responseFlow>
<handler type="java:org.apache.ws.axis.security.conversation.ConversationClientHandler" />
</responseFlow>
</service>
<transport name="java" pivot="java:org.apache.axis.transport.java.JavaSender"/>
<transport name="http" pivot="java:org.apache.axis.transport.http.CommonsHTTPSender"/>
<transport name="local" pivot="java:org.apache.axis.transport.local.LocalSender"/>
</deployment>
1.1 ws-fx/wss4j/test/secconv/ping.wsdl
Index: ping.wsdl
===================================================================
<definitions xmlns:s1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://xmlsoap.org/Ping"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
targetNamespace="http://xmlsoap.org/Ping"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<s:schema elementFormDefault="qualified" targetNamespace="http://xmlsoap.org/Ping">
<s:import namespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"/>
<s:element name="Ping" nillable="true" type="tns:ping"/>
<s:complexType name="ping">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="ticket" type="tns:ticketType"/>
<s:element minOccurs="1" maxOccurs="1" name="text" nillable="true" type="s:string"/>
</s:sequence>
</s:complexType>
<s:complexType name="ticketType">
<s:simpleContent>
<s:extension base="s:string">
<s:attribute ref="s1:Id"/>
</s:extension>
</s:simpleContent>
</s:complexType>
<s:element name="PingResponse" nillable="true" type="tns:pingResponse"/>
<s:complexType name="pingResponse">
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="text" nillable="true" type="s:string"/>
</s:sequence>
</s:complexType>
</s:schema>
<s:schema elementFormDefault="qualified" targetNamespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:attribute name="Id" type="s:string"/>
</s:schema>
</types>
<message name="PingRequest">
<part name="ping" element="tns:Ping"/>
</message>
<message name="PingResponse">
<part name="pingResponse" element="tns:PingResponse"/>
</message>
<portType name="PingPort">
<operation name="Ping">
<input message="tns:PingRequest"/>
<output message="tns:PingResponse"/>
</operation>
</portType>
<binding name="PingBinding" type="tns:PingPort">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="Ping">
<soap:operation soapAction="Ping" style="document"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="PingService">
<port name="Ping1" binding="tns:PingBinding">
<soap:address location="http://localhost:9080/pingservice/Ping1"/>
</port>
<port name="Ping2" binding="tns:PingBinding">
<soap:address location="http://localhost:9080/pingservice/Ping2"/>
</port>
<port name="Ping3" binding="tns:PingBinding">
<soap:address location="http://localhost:9080/pingservice/Ping3"/>
</port>
<port name="Ping4" binding="tns:PingBinding">
<soap:address location="http://localhost:9080/pingservice/Ping4"/>
</port>
<port name="Ping5" binding="tns:PingBinding">
<soap:address location="http://localhost:9080/pingservice/Ping5"/>
</port>
<port name="Ping6" binding="tns:PingBinding">
<soap:address location="http://localhost:9080/pingservice/Ping6"/>
</port>
<port name="Ping7" binding="tns:PingBinding">
<soap:address location="http://localhost:9080/pingservice/Ping7"/>
</port>
<port name="STPing1" binding="tns:PingBinding">
<soap:address location="http://localhost:9080/pingservice/STPing1"/>
</port>
<port name="STPing3" binding="tns:PingBinding">
<soap:address location="http://localhost:9080/pingservice/STPing3"/>
</port>
<port name="STPing4" binding="tns:PingBinding">
<soap:address location="http://localhost:9080/pingservice/STPing4"/>
</port>
<port name="WSConvScenario1" binding="tns:PingBinding">
<soap:address location="http://localhost:9080/pingservice/WSConvScenario1"/>
</port>
</service>
</definitions>
1.1 ws-fx/wss4j/test/secconv/WSConvScenario1.java
Index: WSConvScenario1.java
===================================================================
/*
* Copyright 2003-2004 The Apache Software Foundation.
*
* Licensed 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 secconv;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.holders.StringHolder;
import org.apache.axis.utils.Options;
import secconv.PingPort;
import secconv.PingServiceLocator;
/**
* @author Dimuthu
*
*/
public class WSConvScenario1 {
private static final java.lang.String address =
"http://localhost:9080/axis/services/WSConvScenario1";
public static void main(String[] args) throws Exception {
Options opts = new Options(args);
opts.setDefaultURL(address);
PingServiceLocator service = new PingServiceLocator();
URL endpoint;
try {
endpoint = new URL(opts.getURL());
} catch (MalformedURLException e) {
throw new ServiceException(e);
}
PingPort port = (PingPort) service.getWSConvScenario1(endpoint);
/*
* Performin several calls to show secure conversaton.
*/
StringHolder text =
new StringHolder("SecureConversation - The first call");
for (int i = 0; i < 2; i++) {
text.value = "SecureConversation - Call number " + i;
port.ping(
new secconv.TicketType("SecureZoneType"),
text);
System.out.println(text.value + " is sucessful.");
}
}
}
1.2 +3 -4 ws-fx/wss4j/src/org/apache/ws/security/conversation/ConversationUtil.java
Index: ConversationUtil.java
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/conversation/ConversationUtil.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ConversationUtil.java 18 Jun 2004 11:33:03 -0000 1.1
+++ ConversationUtil.java 19 Jun 2004 20:29:55 -0000 1.2
@@ -119,10 +119,9 @@
*/
public static String genericID() {
try {
- SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
- byte[] genIDValue = new byte[6];
- random.nextBytes(genIDValue);
- return new String(genIDValue);
+ SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
+ int i = random.nextInt(2367);
+ return String.valueOf(i);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
1.2 +11 -9 ws-fx/wss4j/src/org/apache/ws/security/conversation/DerivedKeyCallbackHandler.java
Index: DerivedKeyCallbackHandler.java
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/conversation/DerivedKeyCallbackHandler.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DerivedKeyCallbackHandler.java 18 Jun 2004 11:33:03 -0000 1.1
+++ DerivedKeyCallbackHandler.java 19 Jun 2004 20:29:55 -0000 1.2
@@ -68,8 +68,10 @@
* The receiver should decrypt the message with that derived key. Therefore if the session is expired
* that fact will be only evident at this point where, the derived key is being added into the relevant session.
*/
- public void addDerivedKey(String uuid, DerivedKeyInfo dkInfo)
+ public void addDerivedKey(String identifier, DerivedKeyInfo dkInfo)
throws ConversationException {
+ String[] arr = ConversationUtil.getUuidAndDerivedKeyTokenId(identifier);
+ String uuid = arr[0];
ConversationSession convSess =
(ConversationSession) this.conversationSessionTable.get(uuid);
if (convSess != null) {
@@ -97,14 +99,14 @@
String keyId = pc.getIdentifer();
// This will not be kept static
- KeyDerivator kd = new KeyDerivator(true, 16);
- try {
- kd.generateKey(this.conversationSessionTable, keyId);
- } catch (ConversationException ex1) {
- } catch (WSSecurityException ex1) {
- }
-
- // KeyDerivator.generateKey(this.conversationSessionTable, keyId);
+// KeyDerivator kd = new KeyDerivator(true, 16);
+// try {
+// kd.generateKey(this.conversationSessionTable, keyId);
+// } catch (ConversationException ex1) {
+// } catch (WSSecurityException ex1) {
+// }
+//
+// // KeyDerivator.generateKey(this.conversationSessionTable, keyId);
pc.setPassword("security");
/** Field key */
1.1 ws-fx/wss4j/src/org/apache/ws/security/conversation/ConversationClientHandler.java
Index: ConversationClientHandler.java
===================================================================
/*
* Copyright 2003-2004 The Apache Software Foundation.
*
* Licensed 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.apache.ws.axis.security.conversation;
import java.io.ByteArrayOutputStream;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import org.apache.axis.AxisFault;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.SOAPPart;
import org.apache.axis.handlers.BasicHandler;
import org.apache.ws.axis.security.WSDoAllConstants;
import org.apache.ws.axis.security.WSDoAllSender;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityEngine;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
import org.apache.ws.security.conversation.ConversationManager;
import org.apache.ws.security.conversation.ConversationUtil;
import org.apache.ws.security.conversation.DerivedKeyCallbackHandler;
import org.apache.ws.security.conversation.message.info.SecurityContextInfo;
import org.apache.ws.security.conversation.message.token.DerivedKeyToken;
import org
.apache
.ws
.security
.conversation
.message
.token
.RequestSecurityTokenResponse;
import org.apache.ws.security.conversation.message.token.RequestedProofToken;
import org.apache.ws.security.conversation.message.token.SecurityContextToken;
import org.apache.ws.security.message.token.Reference;
import org.apache.ws.security.message.token.SecurityTokenReference;
import org.apache.ws.security.util.WSSecurityUtil;
import org.apache.xml.security.utils.XMLUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
/**
* @author Dimuthu, Kau
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class ConversationClientHandler extends BasicHandler {
private boolean isTokenInMemory = false;
private int requestCount = 0;
private RequestSecurityTokenResponse stRes;
private DerivedKeyCallbackHandler dkcbHandler;
private int frequency = 2;
private WSSecurityEngine secEng = null;
private String uuid = null;
public ConversationClientHandler() {
System.out.println("ConversationClientHandler :: created");
dkcbHandler = new DerivedKeyCallbackHandler();
}
public void invoke(MessageContext msg) throws AxisFault {
System.out.println("ConversationClientHandler :: invoked");
if (msg.getPastPivot())
doResponse(msg);
else
doRequest(msg);
}
/**
* Do request method behaves in two different was according to the fact that
* <li>the Token is in memory</li>
* <li>the Token is not in memory</li>
*
* <b>If Token is in memory </b> then conversation carried out using it
* <b>If Token is not in memory </b> then message is signed using clients public key and enrypted using server's public key
* @param msg
* @throws AxisFault
*/
private void doRequest(MessageContext msg) throws AxisFault {
org.apache.xml.security.Init.init();
Integer tempInt;
int frequency;
SOAPHeader sHeader = null;
Message sm = msg.getCurrentMessage();
SOAPPart sPart = (org.apache.axis.SOAPPart) sm.getSOAPPart();
Document doc = null;
try {
//take the SOAP message as document
doc =
((org.apache.axis.message.SOAPEnvelope) sPart.getEnvelope())
.getAsDocument();
//check whether the token is in memory
if (isTokenInMemory) {
System.out.println("Token in memory .");
//add DerivedKeyTokens
String genID = ConversationUtil.genericID();
ConversationManager conMan = new ConversationManager();
conMan.addDerivedKeyToken(doc, uuid, dkcbHandler, genID);
//add the SCT with just identifier
Element securityHeader =
WSSecurityUtil.findWsseSecurityHeaderBlock(
doc,
doc.getDocumentElement(),
false);
WSSecurityUtil.appendChildElement(
doc,
securityHeader,
(new SecurityContextToken(doc, uuid)).getElement());
//set the SOAP message with DKTOkens as the current message
ByteArrayOutputStream os = new ByteArrayOutputStream();
XMLUtils.outputDOM(doc, os, true);
String osStr = os.toString();
sPart.setCurrentMessage(osStr, SOAPPart.FORM_STRING);
//create a securitytokenReference pointing to the derived key
Reference ref = new Reference(doc);
ref.setURI("#" + genID);
ref.setValueType("DerivedKeyToken");
SecurityTokenReference stRef = new SecurityTokenReference(doc);
stRef.setReference(ref);
//set mesage properties
msg.setProperty(
WSDoAllConstants.ENC_PROP_FILE,
"crypto.properties");
msg.setProperty(WSDoAllConstants.ENC_KEY_ID, "EmbeddedKeyName");
msg.setProperty(
WSDoAllConstants.ENC_KEY_NAME,
stRef.toString());
msg.setUsername(
ConversationUtil.generateIdentifier(uuid, genID));
msg.setProperty(
WSDoAllConstants.ENC_CALLBACK_REF,
this.dkcbHandler);
msg.setProperty(WSDoAllConstants.ACTION, "Encrypt");
WSDoAllSender wsd = new WSDoAllSender();
wsd.invoke(msg);
} else { //Token is not in memory
this.stRes = new RequestSecurityTokenResponse(doc);
/*SCT is now created.
* 1)Store the identifier in identifier
* 2)SCTInfo in dkcbHandler
*/
uuid =
stRes
.getRequestedSecurityToken()
.getSecurityContextToken()
.getIdentifier();
isTokenInMemory = true;
stRes.build(doc);
//Now encrypting with the base token
RequestedProofToken reqProof = stRes.getRequestedProofToken();
reqProof.doEncryptProof(doc);
SecurityContextInfo info =
new SecurityContextInfo(
stRes
.getRequestedSecurityToken()
.getSecurityContextToken(),
reqProof,
1);
dkcbHandler.addSecurtiyContext(uuid, info);
ByteArrayOutputStream os = new ByteArrayOutputStream();
XMLUtils.outputDOM(doc, os, true);
String osStr = os.toString();
sPart.setCurrentMessage(osStr, SOAPPart.FORM_STRING);
}
} catch (AxisFault e) {
e.printStackTrace();
} catch (WSSecurityException e) {
e.printStackTrace();
} catch (SOAPException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
} //do request
/**
* Called in the response. Since this is handler is suppose to carry out secure conversation
* if Security Context Token (SCT) is not in the message then it should throw a fault.
*
* @param msgContext
* @throws AxisFault
*/
private void doResponse(MessageContext msgContext)
throws AxisFault { //for incoming message
Document doc = null;
Message message = msgContext.getCurrentMessage();
//TODO :: Check ........
secEng = new WSSecurityEngine();
SOAPPart sPart = (org.apache.axis.SOAPPart) message.getSOAPPart();
try {
doc =
((org.apache.axis.message.SOAPEnvelope) sPart.getEnvelope())
.getAsDocument();
} catch (Exception e) {
throw new AxisFault(
"WSDoAllSender: cannot get SOAP envlope from message" + e);
}
/*Get the derved key tokens.
*Add them to the convSession.
*
*/
try {
NodeList ndList =
doc.getElementsByTagNameNS(
WSConstants.WSSE_NS,
"DerivedKeyToken");
Element tmpE;
DerivedKeyToken tmpDKT;
String tmpID;
for (int i = 0; i < ndList.getLength(); i++) {
tmpE = (Element) ndList.item(i);
tmpDKT = new DerivedKeyToken(tmpE);
tmpID = tmpDKT.getID();
//Add to the conv Session .... :-)
}
secEng.processSecurityHeader(doc, "", this.dkcbHandler, null);
} catch (WSSecurityException e1) {
e1.printStackTrace();
throw new AxisFault("Error !!!! " + e1.getMessage());
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
XMLUtils.outputDOM(doc, os, true);
sPart.setCurrentMessage(os.toByteArray(), SOAPPart.FORM_BYTES);
} //do response done
/**
* This is a convienience mehtod that return a SOAP message as document.
*
* @param msgContext
* @return
* @throws AxisFault
*/
private Crypto loadEncryptionCrypto() throws AxisFault {
Crypto crypto = null;
String encPropFile = "crypto.properties";
crypto = CryptoFactory.getInstance(encPropFile);
return crypto;
}
}
1.1 ws-fx/wss4j/src/org/apache/ws/security/conversation/ConversationServerHandler.java
Index: ConversationServerHandler.java
===================================================================
/*
* Copyright 2003-2004 The Apache Software Foundation.
*
* Licensed 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.apache.ws.axis.security.conversation;
import java.io.ByteArrayOutputStream;
import java.util.Iterator;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
import org.apache.axis.AxisFault;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.SOAPPart;
import org.apache.axis.handlers.BasicHandler;
import org.apache.ws.axis.security.WSDoAllConstants;
import org.apache.ws.axis.security.WSDoAllSender;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityEngine;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
import org.apache.ws.security.conversation.ConversationException;
import org.apache.ws.security.conversation.ConversationManager;
import org.apache.ws.security.conversation.ConversationUtil;
import org.apache.ws.security.conversation.DerivedKeyCallbackHandler;
import org.apache.ws.security.conversation.message.info.SecurityContextInfo;
import org.apache.ws.security.conversation.message.token.DerivedKeyToken;
import org
.apache
.ws
.security
.conversation
.message
.token
.RequestSecurityTokenResponse;
import org.apache.ws.security.conversation.message.token.RequestedProofToken;
import org.apache.ws.security.conversation.message.token.SecurityContextToken;
import org.apache.ws.security.message.token.Reference;
import org.apache.ws.security.message.token.SecurityTokenReference;
import org.apache.ws.security.trust.TrustConstants;
import org.apache.ws.security.util.WSSecurityUtil;
import org.apache.xml.security.utils.XMLUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Serverside handler that implements WS-Secure Conversation for Axis.
*
* @author Dimuthu
*
* Each application has a set of policies on how it should be accessed.
* This handler facilitates one of the following two types of base tokens for a service
* 1) username token.
* 2) X509 certificates.
*/
public class ConversationServerHandler extends BasicHandler {
private static DerivedKeyCallbackHandler dkcbHandler;
/**
* Contains the set of SecurityContextTokens of clients that access the service at this moment.
*
*/
public ConversationServerHandler() {
System.out.println("ConversationServerHandler :: created");
dkcbHandler = new DerivedKeyCallbackHandler();
}
public void invoke(MessageContext msg) throws AxisFault {
System.out.println("ConversationServerHandler :: invoked");
if (msg.getPastPivot())
doResponse(msg);
else
doRequest(msg);
}
/**
* Method looks for a SCT in the SOAP envelope,
* <li> Case 1 :: if it is available then this is the first round.<\li>
* <li> Case 2 :: if it is not available check for derived keys<\li>
*
* Case 1 :: Creating a new conversation session and add it to the <code>DerivedKeyCallBackHandler</code>
*
* Case 2 :: Then call a method <></code> derived key decryption.
* @param msg
* @throws AxisFault
*/
private void doRequest(MessageContext msg) throws AxisFault {
try {
Document doc = null;
Message message = msg.getCurrentMessage();
RequestSecurityTokenResponse stRes;
// Code to get the soap message as a Docuemnt
SOAPPart sPart = (org.apache.axis.SOAPPart) message.getSOAPPart();
doc =
((org.apache.axis.message.SOAPEnvelope) sPart.getEnvelope())
.getAsDocument();
//Now search for a SCT in the Security header.
NodeList list =
doc.getElementsByTagNameNS(
WSConstants.WSSE_NS,
TrustConstants.SECURITY_CONTEXT_TOKEN_RESPONSE_LN);
int len = list.getLength();
if (len == 0) { // No SCT is found
// TODO:: Look for derived keys and do the decryption
try {
NodeList ndList =
doc.getElementsByTagNameNS(
WSConstants.WSSE_NS,
"DerivedKeyToken");
Element tmpE;
DerivedKeyToken tmpDKT;
String tmpID;
for (int i = 0; i < ndList.getLength(); i++) {
tmpE = (Element) ndList.item(i);
tmpDKT = new DerivedKeyToken(tmpE);
tmpID = tmpDKT.getID();
//Add to the conv Session .... :-)
}
WSSecurityEngine secEng = new WSSecurityEngine();
secEng.processSecurityHeader(
doc,
"",
dkcbHandler,
null);
} catch (WSSecurityException e1) {
e1.printStackTrace();
throw new AxisFault("Error !!!! " + e1.getMessage());
}
} else {
Element elem = (Element) list.item(0);
stRes = new RequestSecurityTokenResponse(elem);
System.out.println(
"SecurityTokenResponse Found :: " + stRes.toString());
// get securityContextToken, requestedProofToken
SecurityContextToken SCT =
stRes.getRequestedSecurityToken().getSecurityContextToken();
RequestedProofToken proofToken = stRes.getRequestedProfToken();
//TODO:: romove the hard coded decryption
proofToken.doDecryption(
"org.apache.ws.axis.oasis.PWCallback",
loadEncryptionCrypto());
SecurityContextInfo scInfo =
new SecurityContextInfo(SCT, proofToken, 1);
scInfo.setSharedSecret(proofToken.getSharedSecret());
dkcbHandler.addSecurtiyContext("uuid:secureZone", scInfo);
//Set the stuff in msgContext.
msg.setProperty("WSSecureConversation.ID", SCT.getIdentifier());
}
// Replace sPart with the new sPart.
ByteArrayOutputStream os = new ByteArrayOutputStream();
XMLUtils.outputDOM(doc, os, true);
String osStr = os.toString();
sPart.setCurrentMessage(osStr, SOAPPart.FORM_STRING);
//Following sets the headers as processed.
SOAPHeader sHeader = null;
try {
sHeader = message.getSOAPEnvelope().getHeader();
} catch (Exception ex) {
throw new AxisFault(
"WSDoAllReceiver: cannot get SOAP header after security processing",
ex);
}
String actor = null;
Iterator headers = sHeader.examineHeaderElements(actor);
SOAPHeaderElement headerElement = null;
while (headers.hasNext()) {
SOAPHeaderElement hE = (SOAPHeaderElement) headers.next();
if (hE.getLocalName().equals(WSConstants.WSSE_LN)
&& hE.getNamespaceURI().equals(WSConstants.WSSE_NS)) {
headerElement = hE;
break;
}
}
(
(
org
.apache
.axis
.message
.SOAPHeaderElement) headerElement)
.setProcessed(
true);
} catch (AxisFault e) {
e.printStackTrace();
} catch (WSSecurityException e) {
e.printStackTrace();
} catch (SOAPException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
} //do request
private void doResponse(MessageContext msg) throws AxisFault {
System.out.println("Doing response .... ");
Document doc = null;
Message message = msg.getCurrentMessage();
String uuid, identifier;
// Code to get the soap message as a Docuemnt
SOAPPart sPart = (org.apache.axis.SOAPPart) message.getSOAPPart();
try {
doc =
((org.apache.axis.message.SOAPEnvelope) sPart.getEnvelope())
.getAsDocument();
//get the uuid
uuid = (String) msg.getProperty("WSSecureConversation.ID");
// Derrive the token
ConversationManager manager = new ConversationManager();
String genID = ConversationUtil.genericID();
manager.addDerivedKeyToken(doc, uuid, dkcbHandler, genID);
//add the relavent SCT
Element securityHeader =
WSSecurityUtil.findWsseSecurityHeaderBlock(
doc,
doc.getDocumentElement(),
false);
WSSecurityUtil.appendChildElement(
doc,
securityHeader,
(new SecurityContextToken(doc, uuid)).getElement());
org.apache.xml.security.Init.init();
//set it as current message
ByteArrayOutputStream os = new ByteArrayOutputStream();
XMLUtils.outputDOM(doc, os, true);
String osStr = os.toString();
sPart.setCurrentMessage(osStr, SOAPPart.FORM_STRING);
//Creating wsse:Reference
Reference ref = new Reference(doc);
ref.setURI("#" + genID);
ref.setValueType("DerivedKeyToken");
SecurityTokenReference stRef = new SecurityTokenReference(doc);
stRef.setReference(ref);
//set mesage properties
msg.setProperty(
WSDoAllConstants.ENC_PROP_FILE,
"crypto.properties");
msg.setProperty(WSDoAllConstants.ENC_KEY_ID, "EmbeddedKeyName");
msg.setProperty(WSDoAllConstants.ENC_KEY_NAME, stRef.toString());
msg.setUsername(ConversationUtil.generateIdentifier(uuid, genID));
msg.setProperty(
WSDoAllConstants.ENC_CALLBACK_REF,
dkcbHandler);
msg.setProperty(WSDoAllConstants.ACTION, "Encrypt");
WSDoAllSender wsd = new WSDoAllSender();
wsd.invoke(msg);
} catch (AxisFault e) {
e.printStackTrace();
} catch (SOAPException e) {
e.printStackTrace();
} catch (ConversationException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
} //doResponse
//TODO :: Remove this. Temporary method.
private Crypto loadEncryptionCrypto() throws AxisFault {
Crypto crypto = null;
String encPropFile = "crypto.properties";
crypto = CryptoFactory.getInstance(encPropFile);
return crypto;
}
}
1.1 ws-fx/wss4j/test/secconv/ping/deploy.wsdd
Index: deploy.wsdd
===================================================================
<!-- Use this file to deploy some handlers/chains and services -->
<!-- Two ways to do this: -->
<!-- java org.apache.axis.client.AdminClient deploy.wsdd -->
<!-- after the axis server is running -->
<!-- or -->
<!-- java org.apache.axis.utils.Admin client|server deploy.wsdd -->
<!-- from the same directory that the Axis engine runs -->
<deployment
xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="WSConvScenario1" provider="java:RPC" style="wrapped" use="literal">
<parameter name="wsdlTargetNamespace" value="http://xmlsoap.org/Ping"/>
<parameter name="wsdlServiceElement" value="PingService"/>
<parameter name="wsdlServicePort" value="WSConvScenario1"/>
<parameter name="className" value="secconv.PingBindingImpl"/>
<parameter name="wsdlPortType" value="PingPort"/>
<operation name="ping" qname="operNS:Ping" xmlns:operNS="http://xmlsoap.org/Ping" >
<parameter qname="pns:ticket" xmlns:pns="http://xmlsoap.org/Ping" type="tns:ticketType" xmlns:tns="http://xmlsoap.org/Ping"/>
<parameter qname="pns:text" xmlns:pns="http://xmlsoap.org/Ping" type="tns:string" xmlns:tns="http://www.w3.org/2001/XMLSchema" mode="INOUT"/>
</operation>
<parameter name="allowedMethods" value="ping"/>
<typeMapping
xmlns:ns="http://xmlsoap.org/Ping"
qname="ns:ticketType"
type="java:secconv.TicketType"
serializer="org.apache.axis.encoding.ser.SimpleSerializerFactory"
deserializer="org.apache.axis.encoding.ser.SimpleDeserializerFactory"
encodingStyle=""
/>
<requestFlow>
<handler type="java:org.apache.ws.axis.security.conversation.ConversationServerHandler" />
</requestFlow>
<responseFlow>
<handler type="java:org.apache.ws.axis.security.conversation.ConversationServerHandler" />
</responseFlow>
</service>
</deployment>
1.1 ws-fx/wss4j/test/secconv/ping/PingBindingImpl.java
Index: PingBindingImpl.java
===================================================================
/*
* Copyright 2003-2004 The Apache Software Foundation.
*
* Licensed 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.
*
*/
/**
* PingBindingImpl.java
*
* This file was auto-generated from WSDL
* by the Apache Axis 1.2dev Oct 27, 2003 (02:34:09 EST) WSDL2Java emitter.
*/
package secconv;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.ws.axis.security.WSDoAllConstants;
import org.apache.ws.axis.security.WSDoAllReceiverResult;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityEngineResult;
import javax.xml.rpc.holders.StringHolder;
import java.util.Vector;
public class PingBindingImpl
implements secconv.PingPort {
public void ping(
secconv.TicketType pingTicket,
StringHolder text)
throws java.rmi.RemoteException {
MessageContext msgContext = MessageContext.getCurrentContext();
Message reqMsg = msgContext.getRequestMessage();
Vector results = null;
if ((results =
(Vector) msgContext.getProperty(WSDoAllConstants.RECV_RESULTS))
== null) {
System.out.println("No security results!!");
}
if (results != null) {
System.out.println("Number of results: " + results.size());
for (int i = 0; i < results.size(); i++) {
WSDoAllReceiverResult rResult =
(WSDoAllReceiverResult) results.get(i);
Vector wsSecEngineResults = rResult.getResults();
for (int j = 0; j < wsSecEngineResults.size(); j++) {
WSSecurityEngineResult wser =
(WSSecurityEngineResult) wsSecEngineResults.get(j);
if (wser.getAction() != WSConstants.ENCR
&& wser.getPrincipal() != null) {
System.out.println(wser.getPrincipal().getName());
}
}
}
}
}
}
1.2 +1 -1 ws-fx/wss4j/src/org/apache/ws/security/conversation/message/token/DerivedKeyToken.java
Index: DerivedKeyToken.java
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/conversation/message/token/DerivedKeyToken.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DerivedKeyToken.java 18 Jun 2004 11:33:03 -0000 1.1
+++ DerivedKeyToken.java 19 Jun 2004 20:29:55 -0000 1.2
@@ -105,7 +105,7 @@
"wsc:"
+ ConversationConstants.DERIVED_KEY_TOKEN_LN);
WSSecurityUtil.setNamespace(this.element, ConversationConstants.WSC_NS,
- WSConstants.WSSE_PREFIX);
+ ConversationConstants.WSC_PREFIX);
}
/**
1.2 +48 -38 ws-fx/wss4j/src/org/apache/ws/security/conversation/message/token/RequestedProofToken.java
Index: RequestedProofToken.java
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/conversation/message/token/RequestedProofToken.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- RequestedProofToken.java 18 Jun 2004 11:33:03 -0000 1.1
+++ RequestedProofToken.java 19 Jun 2004 20:29:55 -0000 1.2
@@ -42,13 +42,13 @@
* Field log
*/
private static Log log =
- LogFactory.getLog(RequestedProofToken.class.getName());
+ LogFactory.getLog(RequestedProofToken.class.getName());
/**
* Field TOKEN
*/
- public static final QName TOKEN = new QName(WSConstants.WSSE_NS,
- "RequestedProofToken");
+ public static final QName TOKEN =
+ new QName(WSConstants.WSSE_NS, "RequestedProofToken");
/**
* Field proofEle
@@ -113,7 +113,9 @@
* @throws WSSecurityException
*/
public RequestedProofToken(Document doc) throws WSSecurityException {
- this.proofEle = doc.createElementNS(WSConstants.WSSE_NS,
+ this.proofEle =
+ doc.createElementNS(
+ WSConstants.WSSE_NS,
"wsse:RequestedProofToken");
System.out.println("RequestedProofToken....... created .....");
}
@@ -128,9 +130,10 @@
doDebug = log.isDebugEnabled();
QName el = new QName(elem.getNamespaceURI(), elem.getLocalName());
if (!el.equals(TOKEN)) {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "badElement", new Object[]{TOKEN,
- el});
+ throw new WSSecurityException(
+ WSSecurityException.FAILURE,
+ "badElement",
+ new Object[] { TOKEN, el });
}
this.proofEle = elem;
}
@@ -143,15 +146,19 @@
* @throws WSSecurityException
*/
public void doDecryption(String callback, Crypto crypto)
- throws WSSecurityException {
+ throws WSSecurityException {
WSSecurityEngine secEngine = new WSSecurityEngine();
CallbackHandler cbHandler;
// Element
- NodeList ndList = this.proofEle.getElementsByTagNameNS("http://www.w3.org/2001/04/xmlenc#", "EncryptedKey");
+ NodeList ndList =
+ this.proofEle.getElementsByTagNameNS(
+ "http://www.w3.org/2001/04/xmlenc#",
+ "EncryptedKey");
if (ndList.getLength() < 1) {
- throw new WSSecurityException(WSSecurityException.SECURITY_TOKEN_UNAVAILABLE,
- "RequestedProofToken is empty");
+ throw new WSSecurityException(
+ WSSecurityException.SECURITY_TOKEN_UNAVAILABLE,
+ "RequestedProofToken is empty");
}
// CbHandler :: taken from WSSecurityEngine class
@@ -160,21 +167,25 @@
try {
cbClass = java.lang.Class.forName(callback);
} catch (ClassNotFoundException e) {
- throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC,
- "RequestedProofToken: cannot load password callback class: "
+ throw new WSSecurityException(
+ WSSecurityException.FAILED_ENC_DEC,
+ "RequestedProofToken: cannot load password callback class: "
+ callback);
}
try {
cbHandler = (CallbackHandler) cbClass.newInstance();
} catch (java.lang.Exception e) {
- throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC,
- "RequestedProofToken: cannot create instance of password callback: "
+ throw new WSSecurityException(
+ WSSecurityException.FAILED_ENC_DEC,
+ "RequestedProofToken: cannot create instance of password callback: "
+ callback);
}
- secEngine.handleEncryptedKey((Element) ndList.item(0), cbHandler,
- crypto);
+ secEngine.handleEncryptedKey(
+ (Element) ndList.item(0),
+ cbHandler,
+ crypto);
- // this.sharedSecret=secEngine.getDecryptedBytes();
+ this.sharedSecret = secEngine.getDecryptedBytes();
System.out.println(new String(this.sharedSecret));
} else {
System.out.println("Do somehting....... Decryption problem");
@@ -186,28 +197,27 @@
*
* @param doc
*/
- public void doEncryptProof(Document doc) {
- // throws WSSecurityException {
+ public void doEncryptProof(Document doc) throws WSSecurityException {
WSEncryptBody wsEncrypt = new WSEncryptBody();
- // try {
- Crypto crypto;
- crypto = CryptoFactory.getInstance("crypto.properties");
- wsEncrypt.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
- wsEncrypt.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e");
-
- // wsEncrypt.setParentNode(
- // (Element) (doc
- // .getElementsByTagNameNS(
- // WSConstants.WSSE_NS,
- // "RequestedProofToken")
- // .item(0)));
- // wsEncrypt.build(doc, crypto);
- // // this.sharedSecret=wsEncrypt.getSymmetricKey().getEncoded();
- // System.out.println(new String(sharedSecret));
- // } catch (WSSecurityException e) {
- // e.printStackTrace();
- // }
+ try {
+ Crypto crypto;
+ crypto = CryptoFactory.getInstance("crypto.properties");
+ wsEncrypt.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
+ wsEncrypt.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e");
+
+ wsEncrypt.setParentNode(
+ (Element) (doc
+ .getElementsByTagNameNS(
+ WSConstants.WSSE_NS,
+ "RequestedProofToken")
+ .item(0)));
+ wsEncrypt.build(doc, crypto);
+ this.sharedSecret = wsEncrypt.getSymmetricKey().getEncoded();
+
+ } catch (WSSecurityException e) {
+ e.printStackTrace();
+ }
}
/**
1.25 +12 -2 ws-fx/wss4j/src/org/apache/ws/security/WSSecurityEngine.java
Index: WSSecurityEngine.java
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/WSSecurityEngine.java,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- WSSecurityEngine.java 2 Jun 2004 19:35:44 -0000 1.24
+++ WSSecurityEngine.java 19 Jun 2004 20:29:55 -0000 1.25
@@ -93,6 +93,10 @@
private static Map tokenImpl = new Hashtable();
private static boolean sigCheck = true;
private static WSSecurityEngine engine = null;
+ /**
+ * The symmetric key.
+ */
+ private byte[] decryptedBytes = null;
private boolean doDebug = false;
/**
@@ -992,8 +996,7 @@
"noPassword", new Object[]{alias});
}
- byte[] decryptedBytes = null;
-
+
try {
cipher.init(
Cipher.DECRYPT_MODE,
@@ -1311,4 +1314,11 @@
e);
}
}
+ /**
+ * @return
+ */
+ public byte[] getDecryptedBytes() {
+ return decryptedBytes;
+ }
+
}