SecretKey symmetricKey,
String symEncAlgo,
RequestData requestData
) throws WSSecurityException {
WSDataRef dataRef = new WSDataRef();
dataRef.setWsuId(dataRefURI);
dataRef.setAlgorithm(symEncAlgo);
String typeStr = encData.getAttribute("Type");
if (typeStr != null &&
(WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_CONTENT_ONLY.equals(typeStr) ||
WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE.equals(typeStr))) {
try {
Element cipherData = WSSecurityUtil.getDirectChildElement(encData, "CipherData", WSConstants.ENC_NS);
if (cipherData == null) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
}
Element cipherReference = WSSecurityUtil.getDirectChildElement(cipherData, "CipherReference", WSConstants.ENC_NS);
if (cipherReference == null) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
}
String uri = cipherReference.getAttributeNS(null, "URI");
if (uri == null || uri.length() < 5) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
}
if (!uri.startsWith("cid:")) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
}
dataRef.setWsuId(uri);
dataRef.setAttachment(true);
CallbackHandler attachmentCallbackHandler = requestData.getAttachmentCallbackHandler();
if (attachmentCallbackHandler == null) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK);
}
final String attachmentId = uri.substring(4);
AttachmentRequestCallback attachmentRequestCallback = new AttachmentRequestCallback();
attachmentRequestCallback.setAttachmentId(attachmentId);
attachmentCallbackHandler.handle(new Callback[]{attachmentRequestCallback});
List<Attachment> attachments = attachmentRequestCallback.getAttachments();
if (attachments == null || attachments.isEmpty() || !attachmentId.equals(attachments.get(0).getId())) {
throw new WSSecurityException(
WSSecurityException.ErrorCode.INVALID_SECURITY,
"empty", "Attachment not found"
);
}
Attachment attachment = attachments.get(0);
final String encAlgo = X509Util.getEncAlgo(encData);
final String jceAlgorithm =
JCEMapper.translateURItoJCEID(encAlgo);
final Cipher cipher = Cipher.getInstance(jceAlgorithm);
InputStream attachmentInputStream =
AttachmentUtils.setupAttachmentDecryptionStream(
encAlgo, cipher, symmetricKey, attachment.getSourceStream());
Attachment resultAttachment = new Attachment();
resultAttachment.setId(attachment.getId());
resultAttachment.setMimeType(encData.getAttributeNS(null, "MimeType"));
resultAttachment.setSourceStream(attachmentInputStream);
resultAttachment.addHeaders(attachment.getHeaders());
if (WSConstants.SWA_ATTACHMENT_ENCRYPTED_DATA_TYPE_COMPLETE.equals(typeStr)) {
AttachmentUtils.readAndReplaceEncryptedAttachmentHeaders(
resultAttachment.getHeaders(), attachmentInputStream);
}
AttachmentResultCallback attachmentResultCallback = new AttachmentResultCallback();
attachmentResultCallback.setAttachment(resultAttachment);
attachmentResultCallback.setAttachmentId(resultAttachment.getId());
attachmentCallbackHandler.handle(new Callback[]{attachmentResultCallback});
} catch (UnsupportedCallbackException e) {
throw new WSSecurityException(
WSSecurityException.ErrorCode.FAILED_CHECK, e);
} catch (IOException e) {
throw new WSSecurityException(
WSSecurityException.ErrorCode.FAILED_CHECK, e);
} catch (NoSuchAlgorithmException e) {
throw new WSSecurityException(
WSSecurityException.ErrorCode.FAILED_CHECK, e);
} catch (NoSuchPaddingException e) {
throw new WSSecurityException(
WSSecurityException.ErrorCode.FAILED_CHECK, e);
}
dataRef.setContent(true);
// Remove this EncryptedData from the security header to avoid processing it again
encData.getParentNode().removeChild(encData);
return dataRef;
}
boolean content = X509Util.isContent(encData);
dataRef.setContent(content);
Node parent = encData.getParentNode();
Node previousSibling = encData.getPreviousSibling();
if (content) {
encData = (Element) encData.getParentNode();
parent = encData.getParentNode();
}
XMLCipher xmlCipher = null;
try {
xmlCipher = XMLCipher.getInstance(symEncAlgo);
xmlCipher.setSecureValidation(true);
xmlCipher.init(XMLCipher.DECRYPT_MODE, symmetricKey);
} catch (XMLEncryptionException ex) {
throw new WSSecurityException(
WSSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, ex
);
}
try {
xmlCipher.doFinal(doc, encData, content);
} catch (Exception ex) {
throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_CHECK, ex);
}
if (parent.getLocalName().equals(WSConstants.ENCRYPTED_HEADER)
&& parent.getNamespaceURI().equals(WSConstants.WSSE11_NS)
|| parent.getLocalName().equals(WSConstants.ENCRYPED_ASSERTION_LN)
&& parent.getNamespaceURI().equals(WSConstants.SAML2_NS)) {
Node decryptedHeader = parent.getFirstChild();
Node soapHeader = parent.getParentNode();
soapHeader.replaceChild(decryptedHeader, parent);
dataRef.setProtectedElement((Element)decryptedHeader);
dataRef.setXpath(getXPath(decryptedHeader));
} else if (content) {
dataRef.setProtectedElement(encData);
dataRef.setXpath(getXPath(encData));
} else {
Node decryptedNode;
if (previousSibling == null) {
decryptedNode = parent.getFirstChild();
} else {
decryptedNode = previousSibling.getNextSibling();
}
if (decryptedNode != null && Node.ELEMENT_NODE == decryptedNode.getNodeType()) {
dataRef.setProtectedElement((Element)decryptedNode);
}
dataRef.setXpath(getXPath(decryptedNode));
}
return dataRef;
}