String dataEncAlgo = MessageConstants.TRIPLE_DES_BLOCK_ENCRYPTION;
String symmetricKeyName = null;
AuthenticationTokenPolicy.X509CertificateBinding certificateBinding = null;
WSSPolicy wssPolicy = (WSSPolicy)context.getSecurityPolicy();
EncryptionPolicy.FeatureBinding featureBinding =(EncryptionPolicy.FeatureBinding) wssPolicy.getFeatureBinding();
WSSPolicy keyBinding = (WSSPolicy)wssPolicy.getKeyBinding();
AlgorithmSuite algSuite = context.getAlgorithmSuite();
SecurityTokenReference samlTokenRef = null;
SecurityTokenReference secConvRef = null;
SecurityTokenReference ekTokenRef = null;
SecurityTokenReference dktSctTokenRef = null;
SecurityTokenReference issuedTokenRef = null;
//adding EncryptedKey Direct Reference to handle EncryptBeforeSigning
SecurityTokenReference ekDirectRef = null;
DerivedKeyTokenHeaderBlock dktHeadrBlock = null;
SecurityContextTokenImpl sct = null;
boolean sctTokenInserted = false;
SOAPElement sctElement = null;
boolean sctWithDKT = false;
boolean includeSCT = true;
boolean issuedWithDKT = false;
SecurityTokenReference dktIssuedTokenRef = null;
SOAPElement issuedTokenElement = null;
Element issuedTokenElementFromMsg = null;
boolean issuedTokenInserted = false;
boolean includeIST = true;
boolean dktSender = false;
//Key obtained from SymmetricKeyBinding in case of DKT
Key originalKey = null;
String ekId = context.getSecurableSoapMessage().generateId();
String insertedEkId = null;
//Check to see if same x509 token used for Signature and Encryption
boolean skbX509TokenInserted = false;
boolean useStandaloneRefList = false;
HashMap ekCache = context.getEncryptedKeyCache();
SOAPElement x509TokenElement = null;
SecurableSoapMessage secureMessage = context.getSecurableSoapMessage();
if(log.isLoggable(Level.FINEST)){
log.log(Level.FINEST, "KeyBinding in Encryption is "+keyBinding);
}
boolean wss11Receiver = "true".equals(context.getExtraneousProperty("EnableWSS11PolicyReceiver"));
boolean wss11Sender = "true".equals(context.getExtraneousProperty("EnableWSS11PolicySender"));
boolean sendEKSHA1 = wss11Receiver && wss11Sender && (getEKSHA1Ref(context) != null);
boolean wss10 = !wss11Sender;
String tmp = featureBinding.getDataEncryptionAlgorithm();
if (tmp == null || "".equals(tmp)) {
if (context.getAlgorithmSuite() != null) {
tmp = context.getAlgorithmSuite().getEncryptionAlgorithm();
} else {
// warn that no dataEncAlgo was set
}
}
//TODO :: Change to getDataEncryptionAlgorith,
if(tmp != null && !"".equals(tmp)){
dataEncAlgo = tmp;
}
if (context.getAlgorithmSuite() != null) {
keyEncAlgo = context.getAlgorithmSuite().getAsymmetricKeyAlgorithm();
}
// derivedTokenKeyBinding with x509 as originalkeyBinding is to be treated same as
// DerivedKey with Symmetric binding and X509 as key binding of Symmetric binding
if(PolicyTypeUtil.derivedTokenKeyBinding(keyBinding)){
DerivedTokenKeyBinding dtk = (DerivedTokenKeyBinding)keyBinding.clone();
WSSPolicy originalKeyBinding = dtk.getOriginalKeyBinding();
if (PolicyTypeUtil.x509CertificateBinding(originalKeyBinding)){
AuthenticationTokenPolicy.X509CertificateBinding ckBindingClone =
(AuthenticationTokenPolicy.X509CertificateBinding)originalKeyBinding.clone();
//create a symmetric key binding and set it as original key binding of dkt
SymmetricKeyBinding skb = new SymmetricKeyBinding();
skb.setKeyBinding(ckBindingClone);
// set the x509 binding as key binding of symmetric binding
dtk.setOriginalKeyBinding(skb);
keyBinding = dtk;
}
}
if (PolicyTypeUtil.usernameTokenPolicy(keyBinding)) {
log.log(Level.SEVERE,"WSS1210.unsupported.UsernameToken.AsKeyBinding.EncryptionPolicy");
throw new XWSSecurityException("UsernameToken as KeyBinding for EncryptionPolicy is Not Yet Supported");
} else if(PolicyTypeUtil.x509CertificateBinding(keyBinding)) {
//we need to use standalone reflist to support EncryptBeforeSigning
useStandaloneRefList=true;
if ( context.getX509CertificateBinding() != null) {
certificateBinding = context.getX509CertificateBinding();
context.setX509CertificateBinding(null);
} else {
certificateBinding =(AuthenticationTokenPolicy.X509CertificateBinding)keyBinding;
}
x509TokenId = certificateBinding.getUUID();
if(x509TokenId == null || x509TokenId.equals("")){
x509TokenId = secureMsg.generateId();
}
if(log.isLoggable(Level.FINEST)){
log.log(Level.FINEST, "Certificate was "+_x509Cert);
log.log(Level.FINEST, "BinaryToken ID "+x509TokenId);
}
HashMap tokenCache = context.getTokenCache();
HashMap insertedX509Cache = context.getInsertedX509Cache();
SecurityUtil.checkIncludeTokenPolicy(context, certificateBinding, x509TokenId);
_x509Cert = certificateBinding.getX509Certificate();
referenceType = certificateBinding.getReferenceType();
if(referenceType.equals("Identifier") && certificateBinding.getValueType().equals(MessageConstants.X509v1_NS)){
log.log(Level.SEVERE,"WSS1211.unsupported.KeyIdentifierStrategy.X509v1");
throw new XWSSecurityException("Key Identifier strategy with X509v1 certificate is not allowed");
}
keyInfoStrategy = KeyInfoStrategy.getInstance(referenceType);
_exportCertificate = true;
keyInfoStrategy.setCertificate(_x509Cert);
if(MessageConstants.DIRECT_REFERENCE_TYPE.equals(referenceType)){
X509SecurityToken token = (X509SecurityToken)tokenCache.get(x509TokenId);
if(token == null){
String valueType = certificateBinding.getValueType();
if(valueType==null||valueType.equals("")){
//default valueType for X509 as v3
valueType = MessageConstants.X509v3_NS;
}
token = new X509SecurityToken(secureMsg.getSOAPPart(),_x509Cert,x509TokenId, valueType);
}
if(insertedX509Cache.get(x509TokenId) == null){
secureMsg.findOrCreateSecurityHeader().insertHeaderBlock(token);
insertedX509Cache.put(x509TokenId, token);
x509TokenElement = secureMsg.findOrCreateSecurityHeader().getNextSiblingOfTimestamp();
} else{
x509TokenElement = secureMsg.getElementByWsuId(x509TokenId);
}
//x509TokenElement = secureMsg.findOrCreateSecurityHeader().getFirstChildElement();
}
//TODO:Revisit this -Venu
tmp = null;
tmp = certificateBinding.getKeyAlgorithm();
if(tmp != null && !tmp.equals("")){
keyEncAlgo = tmp;
}
_symmetricKey = SecurityUtil.generateSymmetricKey(dataEncAlgo);
} else if (PolicyTypeUtil.symmetricKeyBinding(keyBinding)) {
SymmetricKeyBinding skb = null;
if ( context.getSymmetricKeyBinding() != null) {
skb = context.getSymmetricKeyBinding();
context.setSymmetricKeyBinding(null);
} else {
skb = (SymmetricKeyBinding)keyBinding;
}
KeyInfoHeaderBlock keyInfoBlock = null;
if(!skb.getKeyIdentifier().equals(MessageConstants._EMPTY)){
keyEncAlgo = skb.getKeyAlgorithm();
if(keyEncAlgo != null && !"".equals(keyEncAlgo)){
_symmetricKey = SecurityUtil.generateSymmetricKey(dataEncAlgo);
}
keyInfoStrategy = KeyInfoStrategy.getInstance(MessageConstants.KEY_NAME_TYPE);
keyEncSK = skb.getSecretKey();
symmetricKeyName = skb.getKeyIdentifier();
String secKeyAlgo = keyEncSK.getAlgorithm();
if(_symmetricKey == null){
((KeyNameStrategy)keyInfoStrategy).setKeyName(symmetricKeyName);
_symmetricKey = keyEncSK;
keyEncSK = null;
}
} else if (sendEKSHA1) {
//get the signing key and EKSHA1 reference from the Subject, it was stored from the incoming message
String ekSha1Ref = getEKSHA1Ref(context);
_symmetricKey = skb.getSecretKey();
keyInfoBlock = new KeyInfoHeaderBlock(secureMessage.getSOAPPart());
ekTokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
EncryptedKeySHA1Identifier refElem = new EncryptedKeySHA1Identifier(secureMessage.getSOAPPart());
refElem.setReferenceValue(ekSha1Ref);
ekTokenRef.setReference(refElem);
//set the wsse11:TokenType attribute as required by WSS 1.1
//ekTokenRef.setTokenType(MessageConstants.EncryptedKey_NS);
referenceType = MessageConstants.EK_SHA1_TYPE;
keyInfoStrategy = KeyInfoStrategy.getInstance(referenceType);
//keyInfoStrategy.insertKey(ekTokenRef, secureMsg);
//TODO: the below cond is always true.
} else if (wss11Sender || wss10) {
_symmetricKey = skb.getSecretKey();
useStandaloneRefList = true;
if(!skb.getCertAlias().equals(MessageConstants._EMPTY)){
certificateBinding = new AuthenticationTokenPolicy.X509CertificateBinding();
//x509Binding.newPrivateKeyBinding();
certificateBinding.setCertificateIdentifier(skb.getCertAlias());
_x509Cert = context.getSecurityEnvironment().getCertificate(context.getExtraneousProperties(), certificateBinding.getCertificateIdentifier(), false);
certificateBinding.setX509Certificate(_x509Cert);
certificateBinding.setReferenceType("Direct");
}else if ( context.getX509CertificateBinding() != null ) {
certificateBinding = context.getX509CertificateBinding();
context.setX509CertificateBinding(null);
}
_x509Cert = certificateBinding.getX509Certificate();
x509TokenId = certificateBinding.getUUID();
if(x509TokenId == null || x509TokenId.equals("")){
x509TokenId = secureMsg.generateId();
}
if(log.isLoggable(Level.FINEST)){
log.log(Level.FINEST, "Certificate was "+_x509Cert);
log.log(Level.FINEST, "BinaryToken ID "+x509TokenId);
}
HashMap tokenCache = context.getTokenCache();
HashMap insertedX509Cache = context.getInsertedX509Cache();
SecurityUtil.checkIncludeTokenPolicy(context, certificateBinding, x509TokenId);
X509SecurityToken token = (X509SecurityToken)tokenCache.get(x509TokenId);
if(token == null){
String valueType = certificateBinding.getValueType();
if(valueType==null||valueType.equals("")){
//default valueType for X509 as v3
valueType = MessageConstants.X509v3_NS;
}
token = new X509SecurityToken(secureMsg.getSOAPPart(),_x509Cert,x509TokenId, valueType);
tokenCache.put(x509TokenId, token);
context.setCurrentSecret(_symmetricKey);
} else{
skbX509TokenInserted = true;
_symmetricKey = context.getCurrentSecret();
}
ekTokenRef = new SecurityTokenReference(secureMessage.getSOAPPart());
DirectReference reference = new DirectReference();
insertedEkId = (String)ekCache.get(x509TokenId);
if(insertedEkId == null)
insertedEkId = ekId;
reference.setURI("#"+insertedEkId);
reference.setValueType(MessageConstants.EncryptedKey_NS);
ekTokenRef.setReference(reference);
if(!skbX509TokenInserted){
referenceType = certificateBinding.getReferenceType();
if(referenceType.equals("Identifier") && certificateBinding.getValueType().equals(MessageConstants.X509v1_NS)){
log.log(Level.SEVERE,"WSS1211.unsupported.KeyIdentifierStrategy.X509v1");
throw new XWSSecurityException("Key Identifier strategy with X509v1 is not allowed");
}
keyInfoStrategy = KeyInfoStrategy.getInstance(referenceType);
_exportCertificate = true;
keyInfoStrategy.setCertificate(_x509Cert);
//Store SymmetricKey generated in ProcessingContext
context.setExtraneousProperty("SecretKey", _symmetricKey);
}
if(MessageConstants.DIRECT_REFERENCE_TYPE.equals(referenceType)){
if(insertedX509Cache.get(x509TokenId) == null){
secureMsg.findOrCreateSecurityHeader().insertHeaderBlock(token);
insertedX509Cache.put(x509TokenId, token);
x509TokenElement = secureMsg.findOrCreateSecurityHeader().getNextSiblingOfTimestamp();
} else{
//x509TokenElement = secureMsg.findOrCreateSecurityHeader().getFirstChildElement();
x509TokenElement = secureMsg.getElementByWsuId(x509TokenId);
}
}
}
} else if (PolicyTypeUtil.samlTokenPolicy(keyBinding)) {
//TODO handler saml, it should be a remote SAML Assertion
// since a message from the sender cannot have the receivers assertion as part of message
AuthenticationTokenPolicy.SAMLAssertionBinding samlBinding =
(AuthenticationTokenPolicy.SAMLAssertionBinding)keyBinding;
Assertion assertion1 = null;
Assertion assertion2 = null;
try {
if (System.getProperty("com.sun.xml.wss.saml.binding.jaxb") == null ) {
if (samlBinding.getAssertion().getAttributeNode("ID") != null) {
assertion1 = (Assertion)com.sun.xml.wss.saml.assertion.saml20.jaxb20.Assertion.fromElement(samlBinding.getAssertion());
}else{
assertion1 = (Assertion)com.sun.xml.wss.saml.assertion.saml11.jaxb20.Assertion.fromElement(samlBinding.getAssertion());
}
} else {
assertion2 = (Assertion)com.sun.xml.wss.saml.assertion.saml11.jaxb10.Assertion.fromElement(samlBinding.getAssertion());
}
} catch (SAMLException ex) {
log.log(Level.SEVERE, "WSS1212.error.SAMLAssertionException");
throw new XWSSecurityException(ex);
}
String assertionID = null;
if (assertion1 != null) {
HashMap tokenCache = context.getTokenCache();
//assuming unique IDs
assertionID = ((com.sun.xml.wss.saml.Assertion)assertion1).getAssertionID();
tokenCache.put(assertionID, assertion1);
} else if (assertion2 != null) {
HashMap tokenCache = context.getTokenCache();
//assuming unique IDs
assertionID = ((com.sun.xml.wss.saml.Assertion)assertion2).getAssertionID();
tokenCache.put(assertionID, assertion2);
} else{
log.log(Level.SEVERE,"WSS1213.null.SAMLAssertion");
throw new XWSSecurityException("SAML Assertion is NULL");
}
//Key key = null;
samlkey = KeyResolver.resolveSamlAssertion(
context.getSecurableSoapMessage(), samlBinding.getAssertion(), true, context, assertionID);
/*
_x509Cert = context.getSecurityEnvironment().getCertificate(
context.getExtraneousProperties() ,(PublicKey)key, false);
if (_x509Cert == null) {
log.log(Level.SEVERE,"WSS1214.unableto.locate.certificate.SAMLAssertion");
throw new XWSSecurityException("Could not locate Certificate corresponding to Key in SubjectConfirmation of SAML Assertion");
}*/
if (!"".equals(samlBinding.getKeyAlgorithm())) {
keyEncAlgo = samlBinding.getKeyAlgorithm();
}
_symmetricKey = SecurityUtil.generateSymmetricKey(dataEncAlgo);
referenceType = samlBinding.getReferenceType();
if (referenceType.equals(MessageConstants.EMBEDDED_REFERENCE_TYPE)) {
log.log(Level.SEVERE, "WSS1215.unsupported.EmbeddedReference.SAMLAssertion");
throw new XWSSecurityException("Embedded Reference Type for SAML Assertions not supported yet");
}
String assertionId = null;
if ( assertion1 != null) {
assertionId = ((com.sun.xml.wss.saml.Assertion)assertion1).getAssertionID();
}else if ( assertion2 != null) {
assertionId = ((com.sun.xml.wss.saml.Assertion)assertion2).getAssertionID();
}
Element binding = samlBinding.getAuthorityBinding();
samlTokenRef = new SecurityTokenReference(secureMsg.getSOAPPart());
String strId = samlBinding.getSTRID();
if(strId == null){
strId = secureMsg.generateId();
}
samlTokenRef.setWsuId(strId);
if (binding != null) {
samlTokenRef.setSamlAuthorityBinding(binding, secureMsg.getSOAPPart());
}
keyInfoStrategy = new KeyIdentifierStrategy(assertionId);
keyInfoStrategy.insertKey(samlTokenRef, secureMsg);
} else if ( PolicyTypeUtil.issuedTokenKeyBinding(keyBinding)) {
IssuedTokenContext trustContext = context.getTrustContext();
//get the symmetric key for encryption
try{
_symmetricKey = new SecretKeySpec(trustContext.getProofKey(), SecurityUtil.getSecretKeyAlgorithm(dataEncAlgo));
} catch(Exception e){
log.log(Level.SEVERE, "WSS1216.unableto.get.symmetrickey.Encryption");
throw new XWSSecurityException(e);
}
//Get the IssuedToken and insert it into the message
GenericToken issuedToken = (GenericToken)trustContext.getSecurityToken();
// 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);
SecurityTokenReference str = null;
Element strElem = null;
String tokenVersion = ikb.getIncludeToken();
includeIST = (IssuedTokenKeyBinding.INCLUDE_ALWAYS_TO_RECIPIENT.equals(tokenVersion) ||
IssuedTokenKeyBinding.INCLUDE_ALWAYS.equals(tokenVersion) ||
IssuedTokenKeyBinding.INCLUDE_ALWAYS_VER2.equals(tokenVersion) ||
IssuedTokenKeyBinding.INCLUDE_ALWAYS_TO_RECIPIENT_VER2.equals(tokenVersion)
);
if (includeIST && (issuedToken == null)) {
log.log(Level.SEVERE, "WSS1217.null.IssueToken");
throw new XWSSecurityException("Issued Token to be inserted into the Message was Null");
}
//trust token to be inserted into message
if (issuedToken != null) {
// treat the token as an Opaque entity and just insert the token into message
Element elem = (Element)issuedToken.getTokenValue();
//TODO: remove these expensive conversions DOM Imports
if (tok == null) {
issuedTokenElement = XMLUtil.convertToSoapElement(secureMessage.getSOAPPart(), elem);
//Temp FIX for Issue#26: We need an Id to cache and MS not sending Id in some cases
String tokId = issuedTokenElement.getAttribute("Id");
if ("".equals(tokId) &&
MessageConstants.ENCRYPTED_DATA_LNAME.equals(issuedTokenElement.getLocalName())) {
issuedTokenElement.setAttribute("Id", secureMessage.generateId());
}
tokCache.put(ikbPolicyId, issuedTokenElement);
} else {
issuedTokenInserted = true;
// it will be SOAPElement retrieve its wsuId attr
String wsuId = SecurityUtil.getWsuIdOrId((Element)tok);
issuedTokenElementFromMsg = secureMessage.getElementById(wsuId);
if (issuedTokenElementFromMsg == null) {
log.log(Level.SEVERE, "WSS1218.unableto.locate.IssueToken.Message");
throw new XWSSecurityException("Could not locate Issued Token in Message");
}
}
}
if (includeIST) {
if (trustContext.getAttachedSecurityTokenReference() != null) {
strElem = SecurityUtil.convertSTRToElement(trustContext.getAttachedSecurityTokenReference().getTokenValue(), secureMessage.getSOAPPart());
} else {
log.log(Level.SEVERE, "WSS1219.unableto.refer.Attached.IssueToken");
throw new XWSSecurityException("Cannot determine how to reference the Attached Issued Token in the Message");
}
} else {
//Trust Issued Token should not be in message at all, so use an external reference
if (trustContext.getUnAttachedSecurityTokenReference() != null) {
strElem = SecurityUtil.convertSTRToElement(trustContext.getUnAttachedSecurityTokenReference().getTokenValue(), secureMessage.getSOAPPart());
} else {
log.log(Level.SEVERE, "WSS1220.unableto.refer.Un-Attached.IssueToken");
throw new XWSSecurityException("Cannot determine how to reference the Un-Attached Issued Token in the Message");
}
}
//TODO: remove these expensive conversions
Element imported = (Element)secureMessage.getSOAPPart().importNode(strElem,true);
issuedTokenRef = new SecurityTokenReference(XMLUtil.convertToSoapElement(secureMessage.getSOAPPart(), imported), false);
SecurityUtil.updateSamlVsKeyCache(issuedTokenRef, context, _symmetricKey);
} else if (PolicyTypeUtil.secureConversationTokenKeyBinding(keyBinding)) {
SecureConversationTokenKeyBinding sctBinding = (SecureConversationTokenKeyBinding)keyBinding;
//String sctPolicyId = sctBinding.getPolicyToken().getTokenId();
String sctPolicyId = sctBinding.getUUID();
//Look for SCT in TokenCache
HashMap tokCache = context.getTokenCache();
sct = (SecurityContextTokenImpl)tokCache.get(sctPolicyId);
IssuedTokenContext ictx = context.getSecureConversationContext();
if (sct == null) {
SecurityContextToken sct1 =(SecurityContextToken)ictx.getSecurityToken();
if (sct1 == null) {
log.log(Level.SEVERE,"WSS1221.null.SecureConversationToken");
throw new XWSSecurityException("SecureConversation Token not Found");
}
sct = new SecurityContextTokenImpl(
secureMessage.getSOAPPart(), sct1.getIdentifier().toString(), sct1.getInstance(), sct1.getWsuId(), sct1.getExtElements());
// put back in token cache
tokCache.put(sctPolicyId, sct);
} else {
sctTokenInserted = true;
// record the element
sctElement = secureMessage.getElementByWsuId(sct.getWsuId());
}
String sctWsuId = sct.getWsuId();
if (sctWsuId == null) {
sct.setId(secureMessage.generateId());
}
sctWsuId = sct.getWsuId();
secConvRef = new SecurityTokenReference(secureMessage.getSOAPPart());
DirectReference reference = new DirectReference();
if (SecureConversationTokenKeyBinding.INCLUDE_ALWAYS_TO_RECIPIENT.equals(sctBinding.getIncludeToken()) ||
SecureConversationTokenKeyBinding.INCLUDE_ALWAYS.equals(sctBinding.getIncludeToken())) {
reference.setURI("#" + sctWsuId);
} else {
includeSCT = false;
reference.setSCTURI(sct.getIdentifier().toString(), sct.getInstance());
}
secConvRef.setReference(reference);
referenceType = MessageConstants.DIRECT_REFERENCE_TYPE;
keyInfoStrategy = KeyInfoStrategy.getInstance(referenceType);
String jceAlgo = SecurityUtil.getSecretKeyAlgorithm(dataEncAlgo);
_symmetricKey = new SecretKeySpec(ictx.getProofKey(), jceAlgo);
} else if (PolicyTypeUtil.derivedTokenKeyBinding(keyBinding)){
DerivedTokenKeyBinding dtk = (DerivedTokenKeyBinding)keyBinding.clone();
WSSPolicy originalKeyBinding = dtk.getOriginalKeyBinding();
String algorithm = null;
if(algSuite != null){
algorithm = algSuite.getEncryptionAlgorithm();
}