blob: 852593fb5f99d56c0d85d0c86eac7418630c16ea [file] [log] [blame]
/*
* 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.sandbox.security.conversation;
import java.util.HashMap;
import java.util.Vector;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.xml.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.sandbox.axis.security.conversation.ConvHandlerConstants;
import org.apache.ws.security.SOAPConstants;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSDocInfo;
import org.apache.ws.security.WSDocInfoStore;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.WSSecurityEngine;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.processor.EncryptedKeyProcessor;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
import org.apache.ws.sandbox.security.conversation.message.info.DerivedKeyInfo;
import org.apache.ws.sandbox.security.conversation.message.info.SecurityContextInfo;
import org.apache.ws.sandbox.security.conversation.message.token.DerivedKeyToken;
import org.apache.ws.sandbox.security.conversation.message.token.SecurityContextToken;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.message.EnvelopeIdResolver;
import org.apache.ws.security.message.token.Reference;
import org.apache.ws.security.message.token.SecurityTokenReference;
import org.apache.ws.sandbox.security.trust.TrustConstants;
import org.apache.ws.sandbox.security.trust.TrustEngine;
import org.apache.ws.sandbox.security.trust.WSTrustException;
import org.apache.ws.sandbox.security.trust.message.token.RequestSecurityTokenResponse;
import org.apache.ws.sandbox.security.trust.message.token.RequestedProofToken;
import org.apache.ws.security.util.WSSecurityUtil;
import org.apache.ws.security.util.Loader;
import org.apache.xml.security.encryption.XMLCipher;
import org.apache.xml.security.encryption.XMLEncryptionException;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.keys.KeyInfo;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.signature.XMLSignatureException;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
/**
* Conversation Engine follows the basic structure of SecurityEngine<link>
*
* @author Dimuthu (muthulee@yahoo.com)
*/
public class ConversationEngine {
private static Log log =
LogFactory.getLog(ConversationEngine.class.getName());
private static Log tlog = LogFactory.getLog("org.apache.ws.security.TIME");
private boolean doDebug = false;
/**
* <code>wsc:DerivedKeyToken</code> as defined in WS Secure Conversation specification.
*/
protected static final QName DERIVEDKEY_TOKEN =
new QName(
ConversationConstants.WSC_NS,
ConversationConstants.DERIVED_KEY_TOKEN_LN);
/**
* <code>wsc:SecurityContextToken</code> as defined in WS Secure Conversation specification.
*/
protected static final QName SCT_TOKEN =
new QName(
ConversationConstants.WSC_NS,
ConversationConstants.SECURITY_CONTEXT_TOKEN_LN);
/**
* Refer WS secure Conversation specification
*/
protected static final QName REQUESTED_SECURITY_TOKEN_RESPONSE =
new QName(
TrustConstants.WST_NS,
TrustConstants.REQUEST_SECURITY_TOKEN_RESPONSE_LN);
/**
* <code>ds:Signature</code> as defined by XML Signature specification.
*/
protected static final QName SIGNATURE =
new QName(WSConstants.SIG_NS, WSConstants.SIG_LN);
/**
* <code>xenc:ReferenceList</code> as defined by XML Encryption specification,
*/
protected static final QName REFERENCE_LIST =
new QName(WSConstants.ENC_NS, WSConstants.REF_LIST_LN);
protected static final QName SCT = SecurityContextToken.TOKEN;
protected HashMap configurator = new HashMap();
protected String trustPropFile = null;
protected boolean verifyTrust = false;
protected WSSConfig wssConfig = WSSConfig.getDefaultWSConfig();
static {
org.apache.xml.security.Init.init();
}
public ConversationEngine(HashMap config) {
this.configurator = config;
//TODO :: Move this out of here.
Boolean bool = null;
if ((bool =
(Boolean) configurator.get(ConvHandlerConstants.VERIFY_TRUST))
== null) {
} else {
this.verifyTrust = bool.booleanValue();
if (verifyTrust) {
this.trustPropFile =
(String) configurator.get(
ConvHandlerConstants.TRUST_ENGINE_PROP);
}
}
}
/**
* This method is extracted from org.apache.ws.security.SecurityEngine
*
* @param doc
* @param actor
* @param cb
* @return
* @throws ConversationException
*/
public Vector processSecConvHeader(
Document doc,
String actor,
DerivedKeyCallbackHandler dkcb,
String callback)
throws ConversationException {
doDebug = log.isDebugEnabled();
if (doDebug) {
log.debug("enter processSecurityHeader()");
}
if (actor == null) {
actor = "";
}
NodeList list =
doc.getElementsByTagNameNS(
WSConstants.WSSE_NS,
WSConstants.WSSE_LN);
int len = list.getLength();
if (len == 0) { // No Security headers found
return null;
}
if (doDebug) {
log.debug("Found WS-Security header(s): " + len);
}
Element elem = null;
Attr attr = null;
String headerActor = null;
SOAPConstants sc =
WSSecurityUtil.getSOAPConstants(doc.getDocumentElement());
Vector convResult = new Vector();
for (int i = 0; i < len; i++) {
elem = (Element) list.item(i);
attr =
elem.getAttributeNodeNS(
sc.getEnvelopeURI(),
sc.getRoleAttributeQName().getLocalPart());
if (attr != null) {
headerActor = attr.getValue();
}
if ((headerActor == null)
|| (headerActor.length() == 0)
|| headerActor.equalsIgnoreCase(actor)
|| headerActor.equals(sc.getNextRoleURI())) {
if (doDebug) {
log.debug(
"Processing WS-Security header for '"
+ actor
+ "' actor.");
}
try {
convResult = processConvHeader(elem, doc, dkcb, callback);
} catch (WSSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ConversationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return convResult;
}
/**
* @param doc
* @param dkcbHandler
* @throws ConversationException
*/
protected Vector processConvHeader(
Element securityHeader,
Document doc,
DerivedKeyCallbackHandler dkcbHandler,
String callback)
throws ConversationException, WSSecurityException {
long t0 = 0, t1 = 0, t2 = 0;
if (tlog.isDebugEnabled()) {
t0 = System.currentTimeMillis();
}
NodeList list = securityHeader.getChildNodes();
int len = list.getLength();
Node elem;
String localName = null;
String namespace = null;
if (tlog.isDebugEnabled()) {
t1 = System.currentTimeMillis();
}
Vector returnResults = new Vector();
for (int i = 0; i < len; i++) {
elem = list.item(i);
if (elem.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
QName el = new QName(elem.getNamespaceURI(), elem.getLocalName());
if (el.equals(REQUESTED_SECURITY_TOKEN_RESPONSE)) {
if (doDebug) {
log.debug("Found RequestedSecurityTokenResponse element");
}
returnResults.add(
this.handleRequestedSecurityTokenResponse(
(Element) elem,
dkcbHandler,
callback));
} else if (el.equals(SIGNATURE)) {
if (doDebug) {
log.debug("Found Signature element");
}
ConvEngineResult convResult =
this.VerifySignature((Element) elem, dkcbHandler);
returnResults.add(convResult);
} else if (el.equals(REFERENCE_LIST)) {
if (doDebug) {
log.debug("Found Reference List element");
}
Vector tmpVec =
handleReferenceList((Element) elem, dkcbHandler);
for (int j = 0; j < tmpVec.size(); j++) {
returnResults.add(tmpVec.get(j));
}
} else if (el.equals(SCT)) {
SecurityContextToken sct =
new SecurityContextToken((Element) elem);
String uuid = sct.getIdentifier();
ConvEngineResult convResult =
new ConvEngineResult(ConvEngineResult.SCT);
convResult.setUuid(uuid);
returnResults.add(convResult);
}
}
return returnResults;
}
public ConvEngineResult handleRequestedSecurityTokenResponse(
Element eleSTRes,
DerivedKeyCallbackHandler dkcbHandler,
String callback)
throws ConversationException {
String uuid = null;
RequestSecurityTokenResponse stRes = null;
try {
if (verifyTrust) {
TrustEngine trstEngine = new TrustEngine(this.trustPropFile);
// TODO :: Verify trust......
System.out.println("...........Verifying trust.........");
}
//Now trust is verified.
stRes = new RequestSecurityTokenResponse(eleSTRes, true);
SecurityContextToken SCT =
stRes.getRequestedSecurityToken().getSct();
uuid = SCT.getIdentifier();
RequestedProofToken proofToken = stRes.getRequestedProofToken();
//TODO:: romove the hard coded decryption
proofToken.doDecryption(callback, this.loadDecryptionCrypto());
SecurityContextInfo scInfo = null;
scInfo = new SecurityContextInfo(SCT, proofToken, 1);
dkcbHandler.addSecurtiyContext(uuid, scInfo);
dkcbHandler.setDerivedKeyLength(
uuid,
((Long) configurator.get(ConvHandlerConstants.KEY_LEGNTH))
.longValue());
log.debug(" Done SecurityToekenResponse Handled");
ConvEngineResult res =
new ConvEngineResult(ConvEngineResult.SECURITY_TOKEN_RESPONSE);
res.setUuid(uuid);
return res;
} catch (WSTrustException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new ConversationException("");
} catch (WSSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new ConversationException("");
}
}
private ConvEngineResult VerifySignature(
Element elem,
DerivedKeyCallbackHandler dkcbHandler)
throws ConversationException {
ConvEngineResult convResult = null;
XMLSignature sig = null;
// System.out.println("******** at VerifySignature");
// ByteArrayOutputStream os = new ByteArrayOutputStream();
// XMLUtils.outputDOM(elem, os, true);
// String osStr = os.toString();
// System.out.println(osStr);
try {
sig = new XMLSignature(elem, null);
} catch (XMLSignatureException e2) {
throw new ConversationException("noXMLSig");
} catch (XMLSecurityException e2) {
throw new ConversationException("noXMLSig");
}
String sigMethodURI = sig.getSignedInfo().getSignatureMethodURI();
//verifying the sinature
if (sigMethodURI.equals(XMLSignature.ALGO_ID_MAC_HMAC_SHA1)) {
try {
//sign.verifiyXMLHMac_SHA1_Signarue(sig, dkcbHandler);
convResult =
this.verifiyXMLHMac_SHA1_Signarue(sig, dkcbHandler);
} catch (WSSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
throw new ConversationException("Failed");
}
return convResult;
}
/**
* This method is extracted from WSSecurityEngine.
* <p/>
* Dereferences and decodes encrypted data elements.
*/
private Vector handleReferenceList(
Element elem,
DerivedKeyCallbackHandler dkcbHandler)
throws WSSecurityException {
Vector results = new Vector();
Document doc = elem.getOwnerDocument();
Node tmpE = null;
for (tmpE = elem.getFirstChild();
tmpE != null;
tmpE = tmpE.getNextSibling()) {
if (tmpE.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
if (!tmpE.getNamespaceURI().equals(WSConstants.ENC_NS)) {
continue;
}
if (tmpE.getLocalName().equals("DataReference")) {
String dataRefURI = ((Element) tmpE).getAttribute("URI");
ConvEngineResult convRes =
decryptDataRef(doc, dataRefURI, dkcbHandler);
results.add((Object) convRes);
} else if (tmpE.getLocalName().equals("KeyReference")) {
String keyRefURI = ((Element) tmpE).getAttribute("URI");
}
}
return results;
}
private ConvEngineResult decryptDataRef(
Document doc,
String dataRefURI,
DerivedKeyCallbackHandler dkcbHandler)
throws WSSecurityException {
log.debug("ConversationEngine :: Found data refernce: " + dataRefURI);
ConvEngineResult convResult = null;
/*
* Look up the encrypted data. First try wsu:Id="someURI". If no such Id then
* try the generic lookup to find Id="someURI"
*/
Element encBodyData = null;
if ((encBodyData =
WSSecurityUtil.getElementByWsuId(
doc,
dataRefURI))
== null) {
encBodyData = WSSecurityUtil.getElementByGenId(doc, dataRefURI);
}
if (encBodyData == null) {
throw new WSSecurityException(
WSSecurityException.INVALID_SECURITY,
"dataRef",
new Object[] { dataRefURI });
}
Element tmpE = null;
log.debug(
"ConversationEngine :: Going to figure out the key to decrypt");
byte[] decryptedBytes = null;
/*
* Decryption is performed in 3 major steps
*/
//Step 1 : Get the key from SecurityTokenReference.
log.debug(
"ConversationEngine:: Going to look for SecurityTokenReference");
if ((tmpE =
(Element) WSSecurityUtil.findElement(
(Node) encBodyData,
"SecurityTokenReference",
WSConstants.WSSE_NS))
!= null) {
SecurityTokenReference secRef =
new SecurityTokenReference(
tmpE);
try {
convResult =
this.handleSecurityTokenReference(secRef, dkcbHandler);
decryptedBytes = convResult.getKeyAssociated();
} catch (ConversationException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
} else {
//TODO:: Provide more info
throw new WSSecurityException(WSSecurityException.FAILURE);
}
// Step 2 :: Now figure out the encryption algorithm
String symEncAlgo = getEncAlgo(encBodyData);
SecretKey symmetricKey =
WSSecurityUtil.prepareSecretKey(symEncAlgo, decryptedBytes);
// Step 3 :: initialize Cipher ....
XMLCipher xmlCipher = null;
try {
xmlCipher = XMLCipher.getInstance(symEncAlgo);
xmlCipher.init(XMLCipher.DECRYPT_MODE, symmetricKey);
} catch (XMLEncryptionException e1) {
throw new WSSecurityException(
WSSecurityException.UNSUPPORTED_ALGORITHM,
null,
null,
e1);
}
WSSecurityEngine eng = new WSSecurityEngine();
boolean content = this.isContent(encBodyData);//Whether content encryption or element encryption
if (content) {
encBodyData = (Element) encBodyData.getParentNode();
}else{
System.out.println("Not content:-)");
}
try {
xmlCipher.doFinal(doc, encBodyData, content);
} catch (Exception e) {
throw new WSSecurityException(
WSSecurityException.FAILED_ENC_DEC,
null,
null,
e);
}
return convResult;
}
public ConvEngineResult handleSecurityTokenReference(
SecurityTokenReference secRef2DkToken,
DerivedKeyCallbackHandler dkcbHandler)
throws ConversationException {
if (secRef2DkToken.containsReference()) {
Reference ref = null;
try {
ref = secRef2DkToken.getReference();
} catch (WSSecurityException e1) {
e1.printStackTrace();
throw new ConversationException(e1.getMessage());
}
String valueType = ref.getValueType();
// System.out.println("ref.getURI()" + ref.getURI());
//If the reference type is a derived key token
if (valueType.equals(ConversationConstants.TOKEN_TYPE_DERIVED_KEY_TOKEN)) {
//Get hold of the DerivedKeyToken 'Element'
Element ele =
WSSecurityUtil.getElementByWsuId(
secRef2DkToken.getElement().getOwnerDocument(),
ref.getURI());
if (ele == null) {
throw new ConversationException("Cannot find referenced Derived Key");
}
String uuid = null;
DerivedKeyToken dkToken = null;
try {
dkToken = new DerivedKeyToken(ele); //Cover the 'Element' into 'DerivedKeyToken' object
if (dkToken.getSecuityTokenReference() == null) {
//if dkToken doesn't have a STR find a SecurityContextToken in the SOAP Envelope
SecurityContextToken secContextTk =
ConversationUtil.getSCT(dkToken);
uuid = secContextTk.getIdentifier();
log.debug(
"ConversationEngine :: The uuid is found " + uuid);
DerivedKeyInfo dkInfo = new DerivedKeyInfo(dkToken);
dkcbHandler.addDerivedKey(uuid, dkInfo);
} else { ///i.e. dkToken has a STR
SecurityTokenReference str2Base =
dkToken.getSecuityTokenReference();
if (str2Base.containsReference()) {
Reference ref2Base = str2Base.getReference();
if (ref2Base
.getValueType()
.equals("http://docs.oasis-open.org/wss/2004/XX/oasis-2004XX-wss-saml-token-profile-1.0#SAMLAssertionID")) {
/* ok now I have a SAML token. What should I do ?
* -Decrypt the secret.
* -create tempUUID
* -add the scTInfo into dkcbHandler
* -add the derived key token to dkcbHandler.
*/
uuid = ref2Base.getURI();
if(dkcbHandler.getSession(uuid)==null){
byte[] key = handleSAML(ref2Base.getElement().getOwnerDocument(), uuid);
System.out.println("I am here :-)");
SecurityContextInfo sctInfo = new SecurityContextInfo(
uuid,
key,
1);
dkcbHandler.addSecurtiyContext(
uuid,
sctInfo);
}
DerivedKeyInfo dkInfo = new DerivedKeyInfo(dkToken);
dkcbHandler.addDerivedKey(uuid, dkInfo);
}
//TODO :: Add other tokens else if
} else if(str2Base.containsKeyIdentifier()){
Element elem = str2Base.getFirstElement();
//.getKeyIdentifier()System.out.println("KeyIdentifier :: He ehee ........");
String value = elem.getAttribute("ValueType");
if("http://docs.oasis-open.org/wss/2004/XX/oasis-2004XX-wss-saml-token-profile-1.0#SAMLAssertionID".equals(value)){
uuid = ((Text)elem.getChildNodes().item(0)).getNodeValue();
if(dkcbHandler.getSession(uuid)==null){
byte[] key = handleSAML(elem.getOwnerDocument(), uuid);
System.out.println("UUID of SAML is"+uuid);
SecurityContextInfo sctInfo = new SecurityContextInfo(
uuid,
key,
1);
dkcbHandler.addSecurtiyContext(uuid,sctInfo);
}
DerivedKeyInfo dkInfo = new DerivedKeyInfo(dkToken);
dkcbHandler.addDerivedKey(uuid, dkInfo);
}
}else{
throw new ConversationException("Cannot handle this type of security token reference: " + dkToken.getSecuityTokenReference().getReference().getValueType());
}
} //////end :if dkToken has a STR
//TODO :: Ask ruchith to throw correct exception
} catch (WSSecurityException e2) {
e2.printStackTrace();
} catch (ConversationException e2) {
e2.printStackTrace();
}
String identifier =
ConversationUtil.generateIdentifier(uuid, dkToken.getID());
WSPasswordCallback pwCb =
new WSPasswordCallback(
identifier,
WSPasswordCallback.UNKNOWN);
Callback[] callbacks = new Callback[1];
callbacks[0] = pwCb;
try {
dkcbHandler.handle(callbacks);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] arr = pwCb.getKey();
ConvEngineResult res =
new ConvEngineResult(ConvEngineResult.ENCRYPT_DERIVED_KEY);
res.setKeyAssociated(arr);
return res;
} else {
throw new ConversationException("ConversationEngine :: SecurityTokenRerence doesn't contain DerivedKeys");
}
} else {
throw new ConversationException("ConversationEngine ::SecurityTokenRerence doesn't contain refernce");
}
}
/**
* @param sig - XML Signature obeject containing the XMLSignature element.
* @param cb - Callback handler to get the symmetric key.
* @return
*/
private ConvEngineResult verifiyXMLHMac_SHA1_Signarue(
XMLSignature sig,
DerivedKeyCallbackHandler dkcbHandler)
throws WSSecurityException {
log.debug("Verifying HMAC-SHA1 Signature......");
String userName = null;
long t0 = 0, t1 = 0, t2 = 0;
if (tlog.isDebugEnabled()) {
t0 = System.currentTimeMillis();
}
ConvEngineResult convResult = null;
if (sig == null) {
throw new WSSecurityException(
WSSecurityException.INVALID_SECURITY_TOKEN,
"XMLSignature object is null");
} /* Following lines of code - upto WSDocInfoStore.lookup(docHash) is copied
* from the verifyXMLSignature() method.
*
*/
sig.addResourceResolver(
EnvelopeIdResolver.getInstance());
KeyInfo info = sig.getKeyInfo();
if (info == null) {
throw new WSSecurityException(
WSSecurityException.INVALID_SECURITY,
"unsupportedKeyInfo");
}
Node node =
WSSecurityUtil.getDirectChild(
info.getElement(),
SecurityTokenReference.SECURITY_TOKEN_REFERENCE,
WSConstants.WSSE_NS);
if (node == null) {
throw new WSSecurityException(
WSSecurityException.INVALID_SECURITY,
"unsupportedKeyInfo");
}
SecurityTokenReference secRef =
new SecurityTokenReference(
(Element) node);
Document docSig = sig.getDocument();
int docHash = docSig.hashCode();
if (doDebug) {
log.debug("XML Verify doc: " + docHash);
} /*
* Her we get some information about the document that is being processed,
* in partucular the crypto implementation, and already detected BST that
* may be used later during dereferencing.
*/
WSDocInfo wsDocInfo = WSDocInfoStore.lookup(docHash);
if (secRef.containsReference()) {
Element token =
secRef.getTokenElement(sig.getDocument(), wsDocInfo);
/* check token type: We support Derivedkey tokens now.
* We will support security context tokens.
*/
QName el = new QName(token.getNamespaceURI(), token.getLocalName());
if (el.equals(DERIVEDKEY_TOKEN)) {
DerivedKeyToken dkToken = new DerivedKeyToken(token);
DerivedKeyInfo dkInfo = null;
String uuid = null;
try {
if (dkToken.getSecuityTokenReference() == null) {
//if dkToken doesn't have a STR
SecurityContextToken secContextTk =
ConversationUtil.getSCT(dkToken);
uuid = secContextTk.getIdentifier();
log.debug(
"ConversationEngine :: The uuid is found " + uuid);
dkInfo = new DerivedKeyInfo(dkToken);
dkcbHandler.addDerivedKey(uuid, dkInfo);
} else { ///i.e. dkToken has a STR
SecurityTokenReference str2Base =
dkToken.getSecuityTokenReference();
if (str2Base.containsReference()) {
Reference ref2Base = str2Base.getReference();
//TODO:: Find where can I find the constants.
if (ref2Base
.getValueType()
.equals("http://docs.oasis-open.org/wss/2004/XX/oasis-2004XX-wss-saml-token-profile-1.0#SAMLAssertionID")) {
/* ok now I have a SAML token. What should I do ?
* -Decrypt the secret.
* -create tempUUID
* -add the scTInfo into dkcbHandler
* -add the derived key token to dkcbHandler.
*/
uuid = ref2Base.getURI();
if(dkcbHandler.getSession(uuid)==null){
byte[] key = handleSAML(docSig, uuid);
System.out.println("I am here :-)");
SecurityContextInfo sctInfo =
new SecurityContextInfo(
uuid,
key,
1);
dkcbHandler.addSecurtiyContext(
uuid,
sctInfo);
}
dkInfo = new DerivedKeyInfo(dkToken);
dkcbHandler.addDerivedKey(uuid, dkInfo);
}
} else if(str2Base.containsKeyIdentifier()){
Element elem = str2Base.getFirstElement();
//.getKeyIdentifier()System.out.println("KeyIdentifier :: He ehee ........");
String value = elem.getAttribute("ValueType");
if("http://docs.oasis-open.org/wss/2004/XX/oasis-2004XX-wss-saml-token-profile-1.0#SAMLAssertionID".equals(value)){
uuid = ((Text)elem.getChildNodes().item(0)).getNodeValue();
if(dkcbHandler.getSession(uuid)==null){
byte[] key = handleSAML(elem.getOwnerDocument(), uuid);
System.out.println("UUID of SAML is"+uuid);
SecurityContextInfo sctInfo = new SecurityContextInfo(uuid,key,1);
dkcbHandler.addSecurtiyContext(uuid,sctInfo);
}
dkInfo = new DerivedKeyInfo(dkToken);
dkcbHandler.addDerivedKey(uuid, dkInfo);
}
} else {
throw new ConversationException("Don't know how to process here");
}
}
//String uuid = "aNewUuid";
String dkId = dkToken.getID();
userName = ConversationUtil.generateIdentifier(uuid, dkId);
convResult =
new ConvEngineResult(ConvEngineResult.SIGN_DERIVED_KEY);
dkcbHandler.addDerivedKey(uuid, dkInfo);
log.debug(
"ConversationEngine: added for signature varification. uuil:"
+ uuid
+ " id:"
+ dkId);
} catch (ConversationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//TODO :: Ask ruchith to throw correct exception
} catch (WSSecurityException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
} else if (el.equals(SCT_TOKEN)) {
throw new WSSecurityException(
WSSecurityException.INVALID_SECURITY,
"SCT is not Yet supported",
new Object[] { el.toString()});
} else {
throw new WSSecurityException(
WSSecurityException.INVALID_SECURITY,
"unsupportedToken",
new Object[] { el.toString()});
}
if (tlog.isDebugEnabled()) {
t1 = System.currentTimeMillis();
}
try {
// get the key from the callback handler
WSPasswordCallback callbacks[] =
{
new WSPasswordCallback(
userName,
WSPasswordCallback.UNKNOWN)};
try {
dkcbHandler.handle(callbacks);
} catch (UnsupportedCallbackException e) {
e.printStackTrace();
throw new WSSecurityException(
WSSecurityException.FAILED_SIGNATURE,
"password call back failed",
new Object[] { e.toString()});
} // get the key and check whether it is null
byte[] keyBytes = callbacks[0].getKey();
if (keyBytes == null) {
throw new WSSecurityException(
WSSecurityException.INVALID_SECURITY,
"password call bac in DerivedKeyTokenHandler failed");
}
convResult.setKeyAssociated(keyBytes);
//System.out.println(new String(keyBytes));
SecretKey symetricKey =
new SecretKeySpec(
keyBytes,
XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
if (sig.checkSignatureValue(symetricKey)) {
if (tlog.isDebugEnabled()) {
t2 = System.currentTimeMillis();
tlog.debug(
"Verify: total= "
+ (t2 - t0)
+ ", Find-the token refernced by wsse:Reference= "
+ (t1 - t0)
+ ", password call back & verify= "
+ (t2 - t1));
}
} else {
throw new WSSecurityException(
WSSecurityException.FAILED_CHECK);
}
} catch (XMLSignatureException e1) {
throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
}
}
return convResult;
}
/**
* Extracted from WSSecurityEngine.
*
* @param encBodyData
* @return
* @throws WSSecurityException
*/
private String getEncAlgo(Node encBodyData) throws WSSecurityException {
Element tmpE =
(Element) WSSecurityUtil.findElement(
encBodyData,
"EncryptionMethod",
WSConstants.ENC_NS);
String symEncAlgo = null;
if (tmpE != null) {
symEncAlgo = tmpE.getAttribute("Algorithm");
}
if (symEncAlgo == null) {
throw new WSSecurityException(
WSSecurityException.UNSUPPORTED_ALGORITHM,
"noEncAlgo");
}
if (doDebug) {
log.debug("Sym Enc Algo: " + symEncAlgo);
}
return symEncAlgo;
} //TODO :: Remove this. Temporary method.
private Crypto loadDecryptionCrypto() {
Crypto crypto = null;
String encPropFile = (String)configurator.get(WSHandlerConstants.DEC_PROP_FILE);
crypto = CryptoFactory.getInstance(encPropFile);
return crypto;
}
/**
* This method will be scrapped after the re-architecture.
* Not so elegant work-around.
*
*/
private byte[] handleSAML(Document doc, String assertionId) throws ConversationException{
try {
Crypto crypto = this.loadDecryptionCrypto();
//get the security header block
//get the saml assertion
Element ele=WSSecurityUtil.findWsseSecurityHeaderBlock(doc, doc.getDocumentElement(), false);
Element samEle =(Element)WSSecurityUtil.getDirectChild(ele, "Assertion", "urn:oasis:names:tc:SAML:1.0:assertion" );
// SAMLAssertion assertion = new SAMLAssertion(samEle);
//
// Iterator itr = assertion.getStatements();
//
// SAMLAuthenticationStatement auth = (SAMLAuthenticationStatement)itr.next();
// Element eleEnc = auth.getSubject().getConfirmationData();
//
Element eleEnc = (Element)samEle.getElementsByTagNameNS("http://www.w3.org/2001/04/xmlenc#","EncryptedKey").item(0);
String cb = (String)this.configurator.get(WSHandlerConstants.PW_CALLBACK_CLASS);
CallbackHandler cbHandler = null;
if (cb != null) {
Class cbClass = null;
try {
cbClass = Loader.loadClass(cb);
cbHandler = (CallbackHandler) cbClass.newInstance();
} catch (ClassNotFoundException e) {
throw new ConversationException("Cannot find passwordcallback");
} catch (InstantiationException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} catch (IllegalAccessException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
}else{
throw new ConversationException("Cannot find passwordcallback");
}
EncryptedKeyProcessor processor = new EncryptedKeyProcessor();
processor.handleEncryptedKey(eleEnc, cbHandler, crypto);
byte[] key = processor.getDecryptedBytes();
return key;
}catch (WSSecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
throw new ConversationException("Cannot find passwordcallback");
}
}
/**
*
* Taken from WSSecurityEngine
*
* @param encBodyData
* @return
*/
private boolean isContent(Node encBodyData) {
/*
* Depending on the encrypted data type (Content or Element) the encBodyData either
* holds the element whose contents where encrypted, e.g. soapenv:Body, or the
* xenc:EncryptedData element (in case of Element encryption). In either case we need
* to get the xenc:EncryptedData element. So get it. The findElement method returns
* immediatly if its already the correct element.
* Then we can get the Type attribute.
*/
Element tmpE = (Element) WSSecurityUtil.findElement(encBodyData,
"EncryptedData", WSConstants.ENC_NS);
String typeStr = null;
boolean content = true;
if (tmpE != null) {
typeStr = tmpE.getAttribute("Type");
}
if (typeStr != null) {
content = typeStr.equals(WSConstants.ENC_NS + "Content") ? true : false;
}
return content;
}
}