/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.cxf.ws.security.wss4j.policyhandlers;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.crypto.dsig.Reference;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import org.w3c.dom.Element;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.common.logging.LogUtils;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.MessageUtils;
import org.apache.cxf.ws.policy.AssertionInfo;
import org.apache.cxf.ws.policy.AssertionInfoMap;
import org.apache.cxf.ws.security.SecurityConstants;
import org.apache.cxf.ws.security.tokenstore.SecurityToken;
import org.apache.cxf.ws.security.wss4j.AttachmentCallbackHandler;
import org.apache.cxf.ws.security.wss4j.StaxSerializer;
import org.apache.cxf.ws.security.wss4j.WSS4JUtils;
import org.apache.wss4j.common.WSEncryptionPart;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.derivedKey.ConversationConstants;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.saml.SamlAssertionWrapper;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.engine.WSSConfig;
import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
import org.apache.wss4j.dom.handler.WSHandlerConstants;
import org.apache.wss4j.dom.handler.WSHandlerResult;
import org.apache.wss4j.dom.message.WSSecBase;
import org.apache.wss4j.dom.message.WSSecDKEncrypt;
import org.apache.wss4j.dom.message.WSSecDKSign;
import org.apache.wss4j.dom.message.WSSecEncrypt;
import org.apache.wss4j.dom.message.WSSecEncryptedKey;
import org.apache.wss4j.dom.message.WSSecHeader;
import org.apache.wss4j.dom.message.WSSecSignature;
import org.apache.wss4j.dom.message.WSSecTimestamp;
import org.apache.wss4j.policy.SPConstants;
import org.apache.wss4j.policy.model.AbstractSymmetricAsymmetricBinding;
import org.apache.wss4j.policy.model.AbstractToken;
import org.apache.wss4j.policy.model.AbstractToken.DerivedKeys;
import org.apache.wss4j.policy.model.AbstractTokenWrapper;
import org.apache.wss4j.policy.model.AlgorithmSuite;
import org.apache.wss4j.policy.model.AlgorithmSuite.AlgorithmSuiteType;
import org.apache.wss4j.policy.model.AsymmetricBinding;
import org.apache.wss4j.policy.model.IssuedToken;
import org.apache.wss4j.policy.model.SamlToken;
import org.opensaml.saml.common.SAMLVersion;
/**
*
*/
public class AsymmetricBindingHandler extends AbstractBindingBuilder {
private static final Logger LOG = LogUtils.getL7dLogger(AsymmetricBindingHandler.class);
AsymmetricBinding abinding;
private WSSecEncryptedKey encrKey;
private String encryptedKeyId;
private byte[] encryptedKeyValue;
public AsymmetricBindingHandler(WSSConfig config,
AsymmetricBinding binding,
SOAPMessage saaj,
WSSecHeader secHeader,
AssertionInfoMap aim,
SoapMessage message) throws SOAPException {
super(config, binding, saaj, secHeader, aim, message);
this.abinding = binding;
protectionOrder = binding.getProtectionOrder();
}
public void handleBinding() {
WSSecTimestamp timestamp = createTimestamp();
handleLayout(timestamp);
assertPolicy(abinding.getName());
if (abinding.getProtectionOrder()
== AbstractSymmetricAsymmetricBinding.ProtectionOrder.EncryptBeforeSigning) {
doEncryptBeforeSign();
assertPolicy(
new QName(abinding.getName().getNamespaceURI(), SPConstants.ENCRYPT_BEFORE_SIGNING));
} else {
doSignBeforeEncrypt();
assertPolicy(
new QName(abinding.getName().getNamespaceURI(), SPConstants.SIGN_BEFORE_ENCRYPTING));
}
reshuffleTimestamp();
assertAlgorithmSuite(abinding.getAlgorithmSuite());
assertWSSProperties(abinding.getName().getNamespaceURI());
assertTrustProperties(abinding.getName().getNamespaceURI());
assertPolicy(
new QName(abinding.getName().getNamespaceURI(), SPConstants.ONLY_SIGN_ENTIRE_HEADERS_AND_BODY));
}
private void doSignBeforeEncrypt() {
try {
AbstractTokenWrapper initiatorWrapper = abinding.getInitiatorSignatureToken();
if (initiatorWrapper == null) {
initiatorWrapper = abinding.getInitiatorToken();
}
assertTokenWrapper(initiatorWrapper);
boolean attached = false;
if (initiatorWrapper != null) {
AbstractToken initiatorToken = initiatorWrapper.getToken();
if (initiatorToken instanceof IssuedToken) {
SecurityToken secToken = getSecurityToken();
if (secToken == null) {
unassertPolicy(initiatorToken, "Security token is not found or expired");
return;
} else if (isTokenRequired(initiatorToken.getIncludeTokenType())) {
Element el = secToken.getToken();
this.addEncryptedKeyElement(cloneElement(el));
attached = true;
}
} else if (initiatorToken instanceof SamlToken && isRequestor()) {
SamlAssertionWrapper assertionWrapper = addSamlToken((SamlToken)initiatorToken);
if (assertionWrapper != null && isTokenRequired(initiatorToken.getIncludeTokenType())) {
Element envelope = saaj.getSOAPPart().getEnvelope();
envelope = (Element)DOMUtils.getDomElement(envelope);
addSupportingElement(assertionWrapper.toDOM(envelope.getOwnerDocument()));
storeAssertionAsSecurityToken(assertionWrapper);
}
} else if (initiatorToken instanceof SamlToken) {
String tokenId = getSAMLToken();
if (tokenId == null) {
unassertPolicy(initiatorToken, "Security token is not found or expired");
return;
}
}
assertToken(initiatorToken);
}
// Add timestamp
List<WSEncryptionPart> sigs = new ArrayList<>();
if (timestampEl != null) {
WSEncryptionPart timestampPart =
convertToEncryptionPart(timestampEl.getElement());
sigs.add(timestampPart);
}
addSupportingTokens(sigs);
sigs.addAll(this.getSignedParts(null));
if (isRequestor() && initiatorWrapper != null) {
doSignature(initiatorWrapper, sigs, attached);
doEndorse();
} else if (!isRequestor()) {
//confirm sig
addSignatureConfirmation(sigs);
AbstractTokenWrapper recipientSignatureToken = abinding.getRecipientSignatureToken();
if (recipientSignatureToken == null) {
recipientSignatureToken = abinding.getRecipientToken();
}
if (recipientSignatureToken != null) {
assertTokenWrapper(recipientSignatureToken);
assertToken(recipientSignatureToken.getToken());
doSignature(recipientSignatureToken, sigs, attached);
}
}
List<WSEncryptionPart> enc = getEncryptedParts();
//Check for signature protection
if (abinding.isEncryptSignature()) {
if (mainSigId != null) {
WSEncryptionPart sigPart = new WSEncryptionPart(mainSigId, "Element");
sigPart.setElement(bottomUpElement);
enc.add(sigPart);
}
if (sigConfList != null && !sigConfList.isEmpty()) {
enc.addAll(sigConfList);
}
assertPolicy(
new QName(abinding.getName().getNamespaceURI(), SPConstants.ENCRYPT_SIGNATURE));
}
//Do encryption
AbstractTokenWrapper encToken;
if (isRequestor()) {
enc.addAll(encryptedTokensList);
encToken = abinding.getRecipientEncryptionToken();
if (encToken == null) {
encToken = abinding.getRecipientToken();
}
} else {
encToken = abinding.getInitiatorEncryptionToken();
if (encToken == null) {
encToken = abinding.getInitiatorToken();
}
}
doEncryption(encToken, enc, false);
if (encToken != null) {
assertTokenWrapper(encToken);
assertToken(encToken.getToken());
}
} catch (Exception e) {
String reason = e.getMessage();
LOG.log(Level.WARNING, "Sign before encryption failed due to : " + reason);
LOG.log(Level.FINE, e.getMessage(), e);
throw new Fault(e);
}
}
private AbstractTokenWrapper getEncryptBeforeSignWrapper() {
AbstractTokenWrapper wrapper;
if (isRequestor()) {
wrapper = abinding.getRecipientEncryptionToken();
if (wrapper == null) {
wrapper = abinding.getRecipientToken();
}
} else {
wrapper = abinding.getInitiatorEncryptionToken();
if (wrapper == null) {
wrapper = abinding.getInitiatorToken();
}
}
assertTokenWrapper(wrapper);
return wrapper;
}
private void doEncryptBeforeSign() {
AbstractTokenWrapper wrapper = getEncryptBeforeSignWrapper();
AbstractToken encryptionToken = null;
if (wrapper != null) {
encryptionToken = wrapper.getToken();
assertToken(encryptionToken);
}
AbstractTokenWrapper initiatorWrapper = abinding.getInitiatorSignatureToken();
if (initiatorWrapper == null) {
initiatorWrapper = abinding.getInitiatorToken();
}
assertTokenWrapper(initiatorWrapper);
boolean attached = false;
if (initiatorWrapper != null) {
AbstractToken initiatorToken = initiatorWrapper.getToken();
if (initiatorToken instanceof IssuedToken) {
SecurityToken secToken = getSecurityToken();
if (secToken == null) {
unassertPolicy(initiatorToken, "Security token is not found or expired");
return;
} else if (isTokenRequired(initiatorToken.getIncludeTokenType())) {
Element el = secToken.getToken();
this.addEncryptedKeyElement(cloneElement(el));
attached = true;
}
} else if (initiatorToken instanceof SamlToken && isRequestor()) {
try {
SamlAssertionWrapper assertionWrapper = addSamlToken((SamlToken)initiatorToken);
if (assertionWrapper != null && isTokenRequired(initiatorToken.getIncludeTokenType())) {
Element envelope = saaj.getSOAPPart().getEnvelope();
envelope = (Element)DOMUtils.getDomElement(envelope);
addSupportingElement(assertionWrapper.toDOM(envelope.getOwnerDocument()));
storeAssertionAsSecurityToken(assertionWrapper);
}
} catch (Exception e) {
String reason = e.getMessage();
LOG.log(Level.WARNING, "Encrypt before sign failed due to : " + reason);
LOG.log(Level.FINE, e.getMessage(), e);
throw new Fault(e);
}
} else if (initiatorToken instanceof SamlToken) {
String tokenId = getSAMLToken();
if (tokenId == null) {
unassertPolicy(initiatorToken, "Security token is not found or expired");
return;
}
}
}
List<WSEncryptionPart> sigParts = new ArrayList<>();
if (timestampEl != null) {
WSEncryptionPart timestampPart =
convertToEncryptionPart(timestampEl.getElement());
sigParts.add(timestampPart);
}
try {
addSupportingTokens(sigParts);
} catch (WSSecurityException ex) {
LOG.log(Level.FINE, ex.getMessage(), ex);
unassertPolicy(encryptionToken, ex);
}
List<WSEncryptionPart> encrParts = null;
try {
encrParts = getEncryptedParts();
//Signed parts are determined before encryption because encrypted signed headers
//will not be included otherwise
sigParts.addAll(this.getSignedParts(null));
} catch (SOAPException ex) {
LOG.log(Level.FINE, ex.getMessage(), ex);
throw new Fault(ex);
}
WSSecBase encrBase = null;
if (encryptionToken != null && !encrParts.isEmpty()) {
encrBase = doEncryption(wrapper, encrParts, true);
handleEncryptedSignedHeaders(encrParts, sigParts);
}
if (!isRequestor()) {
addSignatureConfirmation(sigParts);
}
try {
if (!sigParts.isEmpty()) {
if (initiatorWrapper != null && isRequestor()) {
doSignature(initiatorWrapper, sigParts, attached);
} else if (!isRequestor()) {
AbstractTokenWrapper recipientSignatureToken =
abinding.getRecipientSignatureToken();
if (recipientSignatureToken == null) {
recipientSignatureToken = abinding.getRecipientToken();
}
if (recipientSignatureToken != null) {
assertTokenWrapper(recipientSignatureToken);
assertToken(recipientSignatureToken.getToken());
doSignature(recipientSignatureToken, sigParts, attached);
}
}
}
} catch (WSSecurityException ex) {
LOG.log(Level.FINE, ex.getMessage(), ex);
throw new Fault(ex);
} catch (SOAPException ex) {
LOG.log(Level.FINE, ex.getMessage(), ex);
throw new Fault(ex);
}
if (isRequestor()) {
doEndorse();
}
if (encrBase != null) {
encryptTokensInSecurityHeader(encryptionToken, encrBase);
}
}
private void encryptTokensInSecurityHeader(AbstractToken encryptionToken, WSSecBase encrBase) {
List<WSEncryptionPart> secondEncrParts = new ArrayList<>();
// Check for signature protection
if (abinding.isEncryptSignature()) {
assertPolicy(
new QName(abinding.getName().getNamespaceURI(), SPConstants.ENCRYPT_SIGNATURE));
// Now encrypt the signature using the above token
if (mainSigId != null) {
WSEncryptionPart sigPart = new WSEncryptionPart(mainSigId, "Element");
sigPart.setElement(bottomUpElement);
secondEncrParts.add(sigPart);
}
if (sigConfList != null && !sigConfList.isEmpty()) {
secondEncrParts.addAll(sigConfList);
}
}
// Add any SupportingTokens that need to be encrypted
if (isRequestor()) {
secondEncrParts.addAll(encryptedTokensList);
}
if (secondEncrParts.isEmpty()) {
return;
}
// Perform encryption
if (encryptionToken.getDerivedKeys() == DerivedKeys.RequireDerivedKeys
&& encrBase instanceof WSSecDKEncrypt) {
try {
Element secondRefList =
((WSSecDKEncrypt)encrBase).encryptForExternalRef(null, secondEncrParts);
if (secondRefList != null) {
((WSSecDKEncrypt)encrBase).addExternalRefElement(secondRefList);
}
} catch (WSSecurityException ex) {
LOG.log(Level.FINE, ex.getMessage(), ex);
throw new Fault(ex);
}
} else if (encrBase instanceof WSSecEncrypt) {
try {
// Encrypt, get hold of the ref list and add it
Element secondRefList = saaj.getSOAPPart()
.createElementNS(WSConstants.ENC_NS,
WSConstants.ENC_PREFIX + ":ReferenceList");
if (lastEncryptedKeyElement != null) {
insertAfter(secondRefList, lastEncryptedKeyElement);
} else {
this.insertBeforeBottomUp(secondRefList);
}
((WSSecEncrypt)encrBase).encryptForRef(secondRefList, secondEncrParts);
} catch (WSSecurityException ex) {
LOG.log(Level.FINE, ex.getMessage(), ex);
throw new Fault(ex);
}
}
}
private WSSecBase doEncryption(AbstractTokenWrapper recToken,
List<WSEncryptionPart> encrParts,
boolean externalRef) {
//Do encryption
if (recToken != null && recToken.getToken() != null && !encrParts.isEmpty()) {
AbstractToken encrToken = recToken.getToken();
assertPolicy(recToken);
assertPolicy(encrToken);
AlgorithmSuite algorithmSuite = abinding.getAlgorithmSuite();
if (encrToken.getDerivedKeys() == DerivedKeys.RequireDerivedKeys) {
return doEncryptionDerived(recToken, encrToken, encrParts, algorithmSuite);
} else {
try {
WSSecEncrypt encr = new WSSecEncrypt(secHeader);
encr.setEncryptionSerializer(new StaxSerializer());
encr.setIdAllocator(wssConfig.getIdAllocator());
encr.setCallbackLookup(callbackLookup);
encr.setAttachmentCallbackHandler(new AttachmentCallbackHandler(message));
encr.setStoreBytesInAttachment(storeBytesInAttachment);
encr.setExpandXopInclude(isExpandXopInclude());
encr.setWsDocInfo(wsDocInfo);
Crypto crypto = getEncryptionCrypto();
SecurityToken securityToken = getSecurityToken();
if (!isRequestor() && securityToken != null
&& recToken.getToken() instanceof SamlToken) {
String tokenType = securityToken.getTokenType();
if (WSConstants.WSS_SAML_TOKEN_TYPE.equals(tokenType)
|| WSConstants.SAML_NS.equals(tokenType)) {
encr.setCustomEKTokenValueType(WSConstants.WSS_SAML_KI_VALUE_TYPE);
encr.setKeyIdentifierType(WSConstants.CUSTOM_KEY_IDENTIFIER);
encr.setCustomEKTokenId(securityToken.getId());
} else if (WSConstants.WSS_SAML2_TOKEN_TYPE.equals(tokenType)
|| WSConstants.SAML2_NS.equals(tokenType)) {
encr.setCustomEKTokenValueType(WSConstants.WSS_SAML2_KI_VALUE_TYPE);
encr.setKeyIdentifierType(WSConstants.CUSTOM_KEY_IDENTIFIER);
encr.setCustomEKTokenId(securityToken.getId());
} else {
setKeyIdentifierType(encr, encrToken);
}
} else {
setKeyIdentifierType(encr, encrToken);
}
//
// Using a stored cert is only suitable for the Issued Token case, where
// we're extracting the cert from a SAML Assertion on the provider side
//
if (!isRequestor() && securityToken != null
&& securityToken.getX509Certificate() != null) {
encr.setUseThisCert(securityToken.getX509Certificate());
} else if (!isRequestor() && securityToken != null
&& securityToken.getKey() instanceof PublicKey) {
encr.setUseThisPublicKey((PublicKey)securityToken.getKey());
} else {
setEncryptionUser(encr, encrToken, false, crypto);
}
if (!encr.isCertSet() && encr.getUseThisPublicKey() == null && crypto == null) {
unassertPolicy(recToken, "Missing security configuration. "
+ "Make sure jaxws:client element is configured "
+ "with a " + SecurityConstants.ENCRYPT_PROPERTIES + " value.");
}
AlgorithmSuiteType algType = algorithmSuite.getAlgorithmSuiteType();
encr.setSymmetricEncAlgorithm(algType.getEncryption());
encr.setKeyEncAlgo(algType.getAsymmetricKeyWrap());
encr.setMGFAlgorithm(algType.getMGFAlgo());
encr.setDigestAlgorithm(algType.getEncryptionDigest());
encr.prepare(crypto);
Element encryptedKeyElement = encr.getEncryptedKeyElement();
List<Element> attachments = encr.getAttachmentEncryptedDataElements();
//Encrypt, get hold of the ref list and add it
if (externalRef) {
Element refList = encr.encryptForRef(null, encrParts);
if (refList != null) {
insertBeforeBottomUp(refList);
}
if (attachments != null) {
for (Element attachment : attachments) {
this.insertBeforeBottomUp(attachment);
}
}
if (refList != null || (attachments != null && !attachments.isEmpty())) {
this.addEncryptedKeyElement(encryptedKeyElement);
}
} else {
Element refList = encr.encryptForRef(null, encrParts);
if (refList != null || (attachments != null && !attachments.isEmpty())) {
this.addEncryptedKeyElement(encryptedKeyElement);
}
// Add internal refs
if (refList != null) {
encryptedKeyElement.appendChild(refList);
}
if (attachments != null) {
for (Element attachment : attachments) {
this.addEncryptedKeyElement(attachment);
}
}
}
// Put BST before EncryptedKey element
if (encr.getBSTTokenId() != null) {
encr.prependBSTElementToHeader();
}
return encr;
} catch (WSSecurityException e) {
LOG.log(Level.FINE, e.getMessage(), e);
unassertPolicy(recToken, e);
}
}
}
return null;
}
private WSSecBase doEncryptionDerived(AbstractTokenWrapper recToken,
AbstractToken encrToken,
List<WSEncryptionPart> encrParts,
AlgorithmSuite algorithmSuite) {
try {
WSSecDKEncrypt dkEncr = new WSSecDKEncrypt(secHeader);
dkEncr.setEncryptionSerializer(new StaxSerializer());
dkEncr.setIdAllocator(wssConfig.getIdAllocator());
dkEncr.setCallbackLookup(callbackLookup);
dkEncr.setAttachmentCallbackHandler(new AttachmentCallbackHandler(message));
dkEncr.setStoreBytesInAttachment(storeBytesInAttachment);
dkEncr.setExpandXopInclude(isExpandXopInclude());
dkEncr.setWsDocInfo(wsDocInfo);
if (recToken.getToken().getVersion() == SPConstants.SPVersion.SP11) {
dkEncr.setWscVersion(ConversationConstants.VERSION_05_02);
}
if (encrKey == null) {
setupEncryptedKey(recToken, encrToken);
}
dkEncr.setExternalKey(this.encryptedKeyValue, this.encryptedKeyId);
dkEncr.getParts().addAll(encrParts);
dkEncr.setCustomValueType(WSConstants.SOAPMESSAGE_NS11 + "#"
+ WSConstants.ENC_KEY_VALUE_TYPE);
AlgorithmSuiteType algType = algorithmSuite.getAlgorithmSuiteType();
dkEncr.setSymmetricEncAlgorithm(algType.getEncryption());
dkEncr.setDerivedKeyLength(algType.getEncryptionDerivedKeyLength() / 8);
dkEncr.prepare();
addDerivedKeyElement(dkEncr.getdktElement());
Element refList = dkEncr.encryptForExternalRef(null, encrParts);
if (refList != null) {
insertBeforeBottomUp(refList);
}
return dkEncr;
} catch (Exception e) {
LOG.log(Level.FINE, e.getMessage(), e);
unassertPolicy(recToken, e);
}
return null;
}
private void assertUnusedTokens(AbstractTokenWrapper wrapper) {
if (wrapper == null) {
return;
}
Collection<AssertionInfo> ais = aim.getAssertionInfo(wrapper.getName());
if (ais != null) {
for (AssertionInfo ai : ais) {
if (ai.getAssertion() == wrapper) {
ai.setAsserted(true);
}
}
}
ais = aim.getAssertionInfo(wrapper.getToken().getName());
if (ais != null) {
for (AssertionInfo ai : ais) {
if (ai.getAssertion() == wrapper.getToken()) {
ai.setAsserted(true);
}
}
}
}
private void doSignature(AbstractTokenWrapper wrapper, List<WSEncryptionPart> sigParts, boolean attached)
throws WSSecurityException, SOAPException {
if (!isRequestor()) {
assertUnusedTokens(abinding.getInitiatorToken());
assertUnusedTokens(abinding.getInitiatorEncryptionToken());
assertUnusedTokens(abinding.getInitiatorSignatureToken());
} else {
assertUnusedTokens(abinding.getRecipientToken());
assertUnusedTokens(abinding.getRecipientEncryptionToken());
assertUnusedTokens(abinding.getRecipientSignatureToken());
}
AbstractToken sigToken = wrapper.getToken();
if (sigParts.isEmpty()) {
// Add the BST to the security header if required
if (!attached && isTokenRequired(sigToken.getIncludeTokenType())) {
WSSecSignature sig = getSignatureBuilder(sigToken, attached, false);
sig.appendBSTElementToHeader();
}
return;
}
if (sigToken.getDerivedKeys() == DerivedKeys.RequireDerivedKeys) {
// Set up the encrypted key to use
setupEncryptedKey(wrapper, sigToken);
WSSecDKSign dkSign = new WSSecDKSign(secHeader);
dkSign.setIdAllocator(wssConfig.getIdAllocator());
dkSign.setCallbackLookup(callbackLookup);
dkSign.setAttachmentCallbackHandler(new AttachmentCallbackHandler(message));
dkSign.setStoreBytesInAttachment(storeBytesInAttachment);
dkSign.setExpandXopInclude(isExpandXopInclude());
dkSign.setWsDocInfo(wsDocInfo);
if (wrapper.getToken().getVersion() == SPConstants.SPVersion.SP11) {
dkSign.setWscVersion(ConversationConstants.VERSION_05_02);
}
dkSign.setExternalKey(this.encryptedKeyValue, this.encryptedKeyId);
// Set the algo info
dkSign.setSignatureAlgorithm(abinding.getAlgorithmSuite().getSymmetricSignature());
dkSign.setSigCanonicalization(abinding.getAlgorithmSuite().getC14n().getValue());
AlgorithmSuiteType algType = abinding.getAlgorithmSuite().getAlgorithmSuiteType();
dkSign.setDigestAlgorithm(algType.getDigest());
dkSign.setDerivedKeyLength(algType.getSignatureDerivedKeyLength() / 8);
dkSign.setCustomValueType(WSConstants.SOAPMESSAGE_NS11 + "#"
+ WSConstants.ENC_KEY_VALUE_TYPE);
boolean includePrefixes =
MessageUtils.getContextualBoolean(
message, SecurityConstants.ADD_INCLUSIVE_PREFIXES, true
);
dkSign.setAddInclusivePrefixes(includePrefixes);
try {
dkSign.prepare();
if (abinding.isProtectTokens()) {
assertPolicy(
new QName(abinding.getName().getNamespaceURI(), SPConstants.PROTECT_TOKENS));
if (bstElement != null) {
WSEncryptionPart bstPart =
new WSEncryptionPart(bstElement.getAttributeNS(WSConstants.WSU_NS, "Id"));
bstPart.setElement(bstElement);
sigParts.add(bstPart);
} else {
WSEncryptionPart ekPart =
new WSEncryptionPart(encrKey.getId());
ekPart.setElement(encrKey.getEncryptedKeyElement());
sigParts.add(ekPart);
}
}
dkSign.getParts().addAll(sigParts);
List<Reference> referenceList = dkSign.addReferencesToSign(sigParts);
if (!referenceList.isEmpty()) {
// Add elements to header
addDerivedKeyElement(dkSign.getdktElement());
//Do signature
if (bottomUpElement == null) {
dkSign.computeSignature(referenceList, false, null);
} else {
dkSign.computeSignature(referenceList, true, bottomUpElement);
}
bottomUpElement = dkSign.getSignatureElement();
addSig(dkSign.getSignatureValue());
mainSigId = dkSign.getSignatureId();
}
} catch (Exception ex) {
LOG.log(Level.FINE, ex.getMessage(), ex);
throw new Fault(ex);
}
} else {
WSSecSignature sig = getSignatureBuilder(sigToken, attached, false);
// This action must occur before sig.prependBSTElementToHeader
if (abinding.isProtectTokens()) {
assertPolicy(
new QName(abinding.getName().getNamespaceURI(), SPConstants.PROTECT_TOKENS));
if (sig.getBSTTokenId() != null) {
WSEncryptionPart bstPart =
new WSEncryptionPart(sig.getBSTTokenId());
bstPart.setElement(sig.getBinarySecurityTokenElement());
sigParts.add(bstPart);
}
sig.prependBSTElementToHeader();
}
List<Reference> referenceList = sig.addReferencesToSign(sigParts);
if (!referenceList.isEmpty()) {
//Do signature
if (bottomUpElement == null) {
sig.computeSignature(referenceList, false, null);
} else {
sig.computeSignature(referenceList, true, bottomUpElement);
}
bottomUpElement = sig.getSignatureElement();
if (!abinding.isProtectTokens()) {
Element bstElement = sig.getBinarySecurityTokenElement();
if (bstElement != null) {
secHeader.getSecurityHeaderElement().insertBefore(bstElement, bottomUpElement);
}
}
addSig(sig.getSignatureValue());
mainSigId = sig.getId();
}
}
}
private void setupEncryptedKey(AbstractTokenWrapper wrapper, AbstractToken token) throws WSSecurityException {
if (!isRequestor() && token.getDerivedKeys() == DerivedKeys.RequireDerivedKeys) {
//If we already have them, simply return
if (encryptedKeyId != null && encryptedKeyValue != null) {
return;
}
//Use the secret from the incoming EncryptedKey element
List<WSHandlerResult> results =
CastUtils.cast(
(List<?>)message.getExchange().getInMessage().get(WSHandlerConstants.RECV_RESULTS));
if (results != null) {
WSSecurityEngineResult encryptedKeyResult = getEncryptedKeyResult();
if (encryptedKeyResult != null) {
encryptedKeyId = (String)encryptedKeyResult.get(WSSecurityEngineResult.TAG_ID);
encryptedKeyValue = (byte[])encryptedKeyResult.get(WSSecurityEngineResult.TAG_SECRET);
}
//In the case where we don't have the EncryptedKey in the
//request, for the control to have reached this state,
//the scenario MUST be a case where this is the response
//message by a listener created for an async client
//Therefore we will create a new EncryptedKey
if (encryptedKeyId == null && encryptedKeyValue == null) {
createEncryptedKey(wrapper, token);
}
} else {
unassertPolicy(token, "No security results found");
}
} else {
createEncryptedKey(wrapper, token);
}
}
private void createEncryptedKey(AbstractTokenWrapper wrapper, AbstractToken token)
throws WSSecurityException {
//Set up the encrypted key to use
encrKey = this.getEncryptedKeyBuilder(token);
Element bstElem = encrKey.getBinarySecurityTokenElement();
if (bstElem != null) {
// If a BST is available then use it
encrKey.prependBSTElementToHeader();
}
// Add the EncryptedKey
this.addEncryptedKeyElement(encrKey.getEncryptedKeyElement());
encryptedKeyValue = encrKey.getEphemeralKey();
encryptedKeyId = encrKey.getId();
}
private String getSAMLToken() {
List<WSHandlerResult> results = CastUtils.cast((List<?>)message.getExchange().getInMessage()
.get(WSHandlerConstants.RECV_RESULTS));
for (WSHandlerResult rResult : results) {
List<WSSecurityEngineResult> wsSecEngineResults = rResult.getResults();
for (WSSecurityEngineResult wser : wsSecEngineResults) {
Integer actInt = (Integer)wser.get(WSSecurityEngineResult.TAG_ACTION);
String id = (String)wser.get(WSSecurityEngineResult.TAG_ID);
if (actInt.intValue() == WSConstants.ST_SIGNED
|| actInt.intValue() == WSConstants.ST_UNSIGNED) {
Instant created = Instant.now();
Instant expires = created.plusSeconds(WSS4JUtils.getSecurityTokenLifetime(message) / 1000L);
SecurityToken tempTok = new SecurityToken(id, created, expires);
tempTok.setSecret((byte[])wser.get(WSSecurityEngineResult.TAG_SECRET));
tempTok.setX509Certificate(
(X509Certificate)wser.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE), null
);
SamlAssertionWrapper samlAssertion =
(SamlAssertionWrapper)wser.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
if (samlAssertion.getSamlVersion() == SAMLVersion.VERSION_20) {
tempTok.setTokenType(WSConstants.WSS_SAML2_TOKEN_TYPE);
} else {
tempTok.setTokenType(WSConstants.WSS_SAML_TOKEN_TYPE);
}
message.put(SecurityConstants.TOKEN, tempTok);
return id;
}
}
}
return null;
}
}