if(sendEKSHA1){
String ekSha1Ref = getEKSHA1Ref(context);
//STR for DerivedKeyToken
SecurityTokenReference tokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
EncryptedKeySHA1Identifier refElem = new EncryptedKeySHA1Identifier(secureMessage.getSOAPPart());
refElem.setReferenceValue(ekSha1Ref);
tokenRef.setReference(refElem);
//set the wsse11:TokenType attribute as required by WSS 1.1
//tokenRef.setTokenType(MessageConstants.EncryptedKey_NS);
//TODO: Temporary fix for signing
String dktId = keyBinding.getUUID();
if (dktId == null) {
dktId = secureMessage.generateId();
}
String nonce = Base64.encode(dkt.getNonce());
DerivedKeyTokenHeaderBlock dktHeadrBlock =
new DerivedKeyTokenHeaderBlock(securityHeader.getOwnerDocument(), tokenRef, nonce, dkt.getOffset(), dkt.getLength() ,dktId);
// insert the derivedKey into SecurityHeader
secureMessage.findOrCreateSecurityHeader().insertHeaderBlock(dktHeadrBlock);
// set the next sibling to next sibling of derived key token
nextSibling = dktHeadrBlock.getAsSoapElement().getNextSibling();
nxtSiblingContainer[0] = nextSibling;
//Construct the STR for signature
DirectReference reference = new DirectReference();
reference.setURI("#"+dktId);
SecurityTokenReference sigTokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
sigTokenRef.setReference(reference);
keyInfo = dsigHelper.constructKeyInfo(signaturePolicy,sigTokenRef);
return keyInfo;
} else if(wss11Sender || wss10){
AuthenticationTokenPolicy.X509CertificateBinding x509Binding = null;
X509Certificate cert = null;
if ( context.getX509CertificateBinding() != null ) {
x509Binding = context.getX509CertificateBinding();
context.setX509CertificateBinding(null);
}
HashMap tokenCache = context.getTokenCache();
HashMap insertedX509Cache = context.getInsertedX509Cache();
String x509id = x509Binding.getUUID();
if(x509id == null || x509id.equals("")){
x509id = secureMessage.generateId();
}
SecurityUtil.checkIncludeTokenPolicy(context, x509Binding, x509id);
referenceType = x509Binding.getReferenceType();
strategy = KeyInfoStrategy.getInstance(referenceType);
X509SecurityToken token = null;
cert = x509Binding.getX509Certificate();
String x509TokenId = x509Binding.getUUID();
//Check to see if same x509 token used for Signature and Encryption
boolean tokenInserted = false;
if(x509TokenId == null || x509TokenId.equals("")){
x509TokenId = secureMessage.generateId();
}
// ReferenceType adjustment in checkIncludeTokenPolicy is also currently
// causing an insertion of the X509 into the Message
X509SecurityToken insertedx509 =
(X509SecurityToken)context.getInsertedX509Cache().get(x509TokenId);
// this one is used to determine if the whole BST + EK + DKT(opt)
// has been inserted by another filter such as Encryption running before
token = (X509SecurityToken)tokenCache.get(x509TokenId);
if (token == null) {
if (insertedx509 != null) {
token = insertedx509;
tokenCache.put(x509TokenId, insertedx509);
} else {
String valueType = x509Binding.getValueType();
if(valueType==null||valueType.equals("")){
//default valueType for X509 as v3
valueType = MessageConstants.X509v3_NS;
}
token = new X509SecurityToken(secureMessage.getSOAPPart(), cert, x509TokenId, valueType);
tokenCache.put(x509TokenId, token);
}
context.setCurrentSecret(originalKey);
} else{
tokenInserted = true;
}
String dktId = keyBinding.getUUID();
if (dktId == null) {
dktId = secureMessage.generateId();
}
String nonce = Base64.encode(dkt.getNonce());
HashMap ekCache = context.getEncryptedKeyCache();
String ekId = (String)ekCache.get(x509TokenId);
EncryptedKey encryptedKey = null;
XMLCipher keyEncryptor = null;
if(!tokenInserted){
//Store SymmetricKey generated in ProcessingContext
context.setExtraneousProperty("SecretKey", originalKey); //this is the originalKey
//keyinfo for encryptedKey
keyInfoBlock = new KeyInfoHeaderBlock(secureMessage.getSOAPPart());
strategy.setCertificate(cert);
strategy.insertKey(keyInfoBlock, secureMessage, x509TokenId);
com.sun.org.apache.xml.internal.security.keys.KeyInfo apacheKeyInfo = keyInfoBlock.getKeyInfo();
//create an encrypted Key --- it encrypts the original key
try{
keyEncryptor = XMLCipher.getInstance(keyEncAlgo);
keyEncryptor.init(XMLCipher.WRAP_MODE, cert.getPublicKey());
if (keyEncryptor != null) {
encryptedKey = keyEncryptor.encryptKey(secureMessage.getSOAPPart(), originalKey);
}
}catch(Exception e){
logger.log(Level.SEVERE, LogStringsMessages.WSS_1335_UNSUPPORTED_KEYBINDING_SIGNATUREPOLICY());
throw new XWSSecurityException(e);
}
ekId = secureMessage.generateId();
ekCache.put(x509TokenId, ekId);
encryptedKey.setId(ekId);
// set its KeyInfo
encryptedKey.setKeyInfo(apacheKeyInfo);
}
//STR for DerivedKeyToken
SecurityTokenReference tokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
DirectReference reference = new DirectReference();
//TODO: PLUGFEST commenting this as Microsoft puts Value type on reference itself
//tokenRef.setTokenType(MessageConstants.EncryptedKey_NS);
//set id of encrypted key in STR of DKT
reference.setValueType(MessageConstants.EncryptedKey_NS);
reference.setURI("#"+ekId);
tokenRef.setReference(reference);
DerivedKeyTokenHeaderBlock dktHeadrBlock =
new DerivedKeyTokenHeaderBlock(securityHeader.getOwnerDocument(), tokenRef, nonce, dkt.getOffset(), dkt.getLength() ,dktId);
if(!tokenInserted){
Node nsX509 = null;
if (insertedx509 != null) {
nsX509 = insertedx509.getNextSibling();
}
// move DKT below X509 if present
if (nsX509 == null) {
secureMessage.findOrCreateSecurityHeader().insertHeaderBlock(dktHeadrBlock);
} else {
secureMessage.findOrCreateSecurityHeader().insertBefore(dktHeadrBlock, nsX509);
}
// move EK above DKT but below X509
if (insertedx509 != null) {
nsX509 = insertedx509.getNextSibling();
}
// insert the EK into the SOAPMessage - this goes on top of DKT Header block
SOAPElement se = (SOAPElement)keyEncryptor.martial(encryptedKey);
if (nsX509 == null) {
secureMessage.findOrCreateSecurityHeader().insertHeaderBlockElement(se);
}else {
secureMessage.findOrCreateSecurityHeader().insertBefore(se, nsX509);
}
//insert the token as the first child in SecurityHeader
if (MessageConstants.DIRECT_REFERENCE_TYPE.equals(referenceType) && insertedX509Cache.get(x509TokenId) == null){
secureMessage.findOrCreateSecurityHeader().insertHeaderBlock(token);
insertedX509Cache.put(x509TokenId, token);
}
//store EKSHA1 of KeyValue contents in context
Element cipherData = (Element)se.getChildElements(new QName(MessageConstants.XENC_NS, "CipherData", MessageConstants.XENC_PREFIX)).next();
String cipherValue = cipherData.getElementsByTagNameNS(MessageConstants.XENC_NS, "CipherValue").item(0).getTextContent();
byte[] decodedCipher = Base64.decode(cipherValue);
byte[] ekSha1 = MessageDigest.getInstance("SHA-1").digest(decodedCipher);
String encEkSha1 = Base64.encode(ekSha1);
context.setExtraneousProperty("EncryptedKeySHA1", encEkSha1);
} else{
//insert derived key after the existing EK
Element ekElem = secureMessage.getElementById(ekId);
secureMessage.findOrCreateSecurityHeader().insertBefore(dktHeadrBlock, ekElem.getNextSibling());
}
//Construct the STR for signature
DirectReference refSig = new DirectReference();
refSig.setURI("#"+dktId);
SecurityTokenReference sigTokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
sigTokenRef.setReference(refSig);
keyInfo = dsigHelper.constructKeyInfo(signaturePolicy,sigTokenRef);
// set the next sibling to next sibling of derived key token
nextSibling = dktHeadrBlock.getAsSoapElement().getNextSibling();
nxtSiblingContainer[0] = nextSibling;
return keyInfo;
}
} else if ( PolicyTypeUtil.issuedTokenKeyBinding(originalKeyBinding)) {
IssuedTokenKeyBinding itk = (IssuedTokenKeyBinding)originalKeyBinding;
IssuedTokenContext issuedTokenContext = context.getTrustContext();
//Get the IssuedToken and insert it into the message
GenericToken issuedToken = (GenericToken)issuedTokenContext.getSecurityToken();
SOAPElement tokenElem = null;
SecurityTokenReference str = null;
Element strElem = null;
// check if the token is already present
IssuedTokenKeyBinding ikb = (IssuedTokenKeyBinding)originalKeyBinding;
//String ikbPolicyId = ikb.getPolicyToken().getTokenId();
String ikbPolicyId = ikb.getUUID();
//Look for TrustToken in TokenCache
HashMap tokCache = context.getTokenCache();
Object tok = tokCache.get(ikbPolicyId);
SOAPElement issuedTokenElementFromMsg = null;
String iTokenType = ikb.getIncludeToken();
boolean includeIST = (ikb.INCLUDE_ALWAYS_TO_RECIPIENT.equals(iTokenType) ||
ikb.INCLUDE_ALWAYS.equals(iTokenType) ||
ikb.INCLUDE_ALWAYS_VER2.equals(iTokenType) ||
ikb.INCLUDE_ALWAYS_TO_RECIPIENT_VER2.equals(iTokenType)
);
if (includeIST && (issuedToken == null)) {
logger.log(Level.SEVERE, LogStringsMessages.WSS_1343_NULL_ISSUED_TOKEN());
throw new XWSSecurityException("Issued Token to be inserted into the Message was Null");
}
if (issuedToken != null) {
// treat the token as an Opaque entity and just insert the token into message
Element elem = (Element)issuedToken.getTokenValue();
if (tok == null) {
//TODO: remove these expensive conversions DOM Imports
tokenElem = XMLUtil.convertToSoapElement(secureMessage.getSOAPPart(), elem);
//FIX for Issue 26: We need an Id to cache and MS is not setting in some cases
String tokId = tokenElem.getAttribute("Id");
if ("".equals(tokId) &&
MessageConstants.ENCRYPTED_DATA_LNAME.equals(tokenElem.getLocalName())) {
tokenElem.setAttribute("Id", secureMessage.generateId());
}
tokCache.put(ikbPolicyId, tokenElem);
} else {
// it will be SOAPElement retrieve its wsuId attr
String wsuId = SecurityUtil.getWsuIdOrId((Element)tok);
issuedTokenElementFromMsg = (SOAPElement)secureMessage.getElementById(wsuId);
if (issuedTokenElementFromMsg == null) {
logger.log(Level.SEVERE,LogStringsMessages.WSS_1344_ERROR_LOCATE_ISSUE_TOKEN_MESSAGE());
throw new XWSSecurityException("Could not locate Issued Token in Message");
}
}
}
if (includeIST) {
strElem = (Element)issuedTokenContext.getAttachedSecurityTokenReference().getTokenValue();
} else {
strElem = (Element)issuedTokenContext.getUnAttachedSecurityTokenReference().getTokenValue();
}
//TODO: remove these expensive conversions
Element imported = (Element)secureMessage.getSOAPPart().importNode(strElem,true);
str = new SecurityTokenReference(XMLUtil.convertToSoapElement(secureMessage.getSOAPPart(), imported), false);
if (originalKey != null) {
SecurityUtil.updateSamlVsKeyCache(str, context, originalKey);
}
String dktId = keyBinding.getUUID();
if (dktId == null) {
dktId = secureMessage.generateId();
}
DerivedKeyTokenHeaderBlock derivedKeyTokenHeaderBlock =
new DerivedKeyTokenHeaderBlock(
secureMessage.getSOAPPart(),
str,
Base64.encode(dkt.getNonce()),
dkt.getOffset(),
dkt.getLength(),
dktId);
if (issuedTokenElementFromMsg != null) {
SecurityHeader _secHeader = secureMessage.findOrCreateSecurityHeader();
_secHeader.insertBefore(derivedKeyTokenHeaderBlock, issuedTokenElementFromMsg.getNextSibling());
} else {
Node reflist = context.getCurrentRefList();
if (reflist != null) {
secureMessage.findOrCreateSecurityHeader().insertBefore(derivedKeyTokenHeaderBlock, reflist);
context.setCurrentReferenceList(null);
} else {
secureMessage.findOrCreateSecurityHeader().insertHeaderBlock(derivedKeyTokenHeaderBlock);
}
}
// insert the Issued Token after the DKT
if (tokenElem != null) {
if (includeIST) {
secureMessage.findOrCreateSecurityHeader().insertHeaderBlockElement(tokenElem);
}
// also store the token in Packet.invocationProperties to be used by
// client side response processing
context.setIssuedSAMLToken(tokenElem);
}
//Construct the STR for signature
DirectReference refSig = new DirectReference();
refSig.setURI("#"+dktId);
SecurityTokenReference sigTokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
sigTokenRef.setReference(refSig);
keyInfo = dsigHelper.constructKeyInfo(signaturePolicy,sigTokenRef);
// set the next sibling to next sibling of derived key token
nextSibling = derivedKeyTokenHeaderBlock.getAsSoapElement().getNextSibling();
nxtSiblingContainer[0] = nextSibling;
return keyInfo;
} else if ( PolicyTypeUtil.samlTokenPolicy(originalKeyBinding)) {
logger.log(Level.SEVERE, LogStringsMessages.WSS_1345_UNSUPPORTED_DERIVEDKEYS_SAML_TOKEN());
throw new UnsupportedOperationException("DerivedKeys with SAMLToken not yet supported");
} else if (PolicyTypeUtil.secureConversationTokenKeyBinding(originalKeyBinding)) {
SecureConversationTokenKeyBinding sctBinding = (SecureConversationTokenKeyBinding)originalKeyBinding;
//STR for DerivedKeyToken
SecurityTokenReference tokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
SOAPElement sctElement = insertSCT(context, sctBinding, tokenRef);
String dktId = keyBinding.getUUID();
if (dktId == null) {
dktId = secureMessage.generateId();
}
String nonce = Base64.encode(dkt.getNonce());
DerivedKeyTokenHeaderBlock dktHeaderBlock =
new DerivedKeyTokenHeaderBlock(
securityHeader.getOwnerDocument(), tokenRef, nonce, dkt.getOffset(), dkt.getLength() ,dktId);
Node next = (sctElement != null) ? sctElement.getNextSibling() : null;
if (next == null) {
Node reflist = context.getCurrentRefList();
if (reflist != null) {
next = reflist;
context.setCurrentReferenceList(null);
}
}
SOAPElement dktElem = (SOAPElement)securityHeader.insertBefore(
dktHeaderBlock.getAsSoapElement(), next);
//Construct the STR for signature
DirectReference refSig = new DirectReference();
refSig.setURI("#"+dktId);
SecurityTokenReference sigTokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
sigTokenRef.setReference(refSig);
// signature should be below DKT
nextSibling = dktElem.getNextSibling();
nxtSiblingContainer[0] = nextSibling;
keyInfo = dsigHelper.constructKeyInfo(signaturePolicy,sigTokenRef);
return keyInfo;
}
} else if ( PolicyTypeUtil.issuedTokenKeyBinding(keyBinding)) {
//Get the IssuedToken and insert it into the message
IssuedTokenContext issuedTokenContext = context.getTrustContext();
GenericToken issuedToken = (GenericToken)issuedTokenContext.getSecurityToken();
SOAPElement tokenElem = null;
SecurityTokenReference str = null;
Element strElem = null;
SOAPElement issuedTokenElementFromMsg = null;
// check if the token is already present
IssuedTokenKeyBinding ikb = (IssuedTokenKeyBinding)keyBinding;
//String ikbPolicyId = ikb.getPolicyToken().getTokenId();
String ikbPolicyId = ikb.getUUID();
//Look for TrustToken in TokenCache
HashMap tokCache = context.getTokenCache();
Object tok = tokCache.get(ikbPolicyId);
String iTokenType = ikb.getIncludeToken();
boolean includeIST = (ikb.INCLUDE_ALWAYS_TO_RECIPIENT.equals(iTokenType) ||
ikb.INCLUDE_ALWAYS.equals(iTokenType) ||
ikb.INCLUDE_ALWAYS_VER2.equals(iTokenType) ||
ikb.INCLUDE_ALWAYS_TO_RECIPIENT_VER2.equals(iTokenType)
);
if (includeIST && (issuedToken == null)) {
logger.log(Level.SEVERE, LogStringsMessages.WSS_1343_NULL_ISSUED_TOKEN());
throw new XWSSecurityException("Issued Token to be inserted into the Message was Null");
}
if (issuedToken != null) {
// treat the token as an Opaque entity and just insert the token into message
Element elem = (Element)issuedToken.getTokenValue();
if (tok == null) {
//TODO: remove these expensive conversions DOM Imports
tokenElem = XMLUtil.convertToSoapElement(secureMessage.getSOAPPart(), elem);
//FIX for Issue 26: We need an Id to cache and MS is not setting in some cases
String tokId = tokenElem.getAttribute("Id");
if ("".equals(tokId) &&
MessageConstants.ENCRYPTED_DATA_LNAME.equals(tokenElem.getLocalName())) {
tokenElem.setAttribute("Id", secureMessage.generateId());
}
tokCache.put(ikbPolicyId, tokenElem);
} else {
// it will be SOAPElement retrieve its wsuId attr
String wsuId = SecurityUtil.getWsuIdOrId((Element)tok);
issuedTokenElementFromMsg = (SOAPElement)secureMessage.getElementById(wsuId);
if (issuedTokenElementFromMsg == null) {
logger.log(Level.SEVERE, LogStringsMessages.WSS_1344_ERROR_LOCATE_ISSUE_TOKEN_MESSAGE());
throw new XWSSecurityException("Could not locate Issued Token in Message");
}
}
}
if (includeIST) {
strElem = SecurityUtil.convertSTRToElement(issuedTokenContext.getAttachedSecurityTokenReference().getTokenValue(), secureMessage.getSOAPPart());
} else {
strElem = SecurityUtil.convertSTRToElement(issuedTokenContext.getUnAttachedSecurityTokenReference().getTokenValue(), secureMessage.getSOAPPart());
}
if(strElem == null){
logger.log(Level.SEVERE, LogStringsMessages.WSS_1378_UNABLETO_REFER_ISSUE_TOKEN());
throw new XWSSecurityException("Cannot determine how to reference the Issued Token in the Message");
}
//TODO: remove these expensive conversions
Element imported = (Element)secureMessage.getSOAPPart().importNode(strElem,true);
str = new SecurityTokenReference(
XMLUtil.convertToSoapElement(secureMessage.getSOAPPart(), (Element)imported.cloneNode(true)), false);
if (originalKey != null) {
SecurityUtil.updateSamlVsKeyCache(str, context, originalKey);
}
if (tokenElem != null) {
if(includeIST) {
secureMessage.findOrCreateSecurityHeader().insertHeaderBlockElement(tokenElem);
nxtSiblingContainer[0] = tokenElem.getNextSibling();
} else {
nxtSiblingContainer[0] = null;
}
// also store the token in Packet.invocationProperties to be used by
// client side response processing
context.setIssuedSAMLToken(tokenElem);
} else if (issuedTokenElementFromMsg != null) {
nxtSiblingContainer[0] = issuedTokenElementFromMsg.getNextSibling();
}
keyInfo = dsigHelper.constructKeyInfo(signaturePolicy,str);
return keyInfo;
} else if (PolicyTypeUtil.secureConversationTokenKeyBinding(keyBinding)){
SecurityTokenReference secTokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
SecureConversationTokenKeyBinding sctBinding = (SecureConversationTokenKeyBinding)keyBinding;
SOAPElement sctElement = insertSCT(context, sctBinding, secTokenRef);
// signature should be below SCT
nextSibling = (sctElement != null) ? sctElement.getNextSibling() : null;