SecureSOAPMessage.java revision 4a2f0f0be43dfd4c1b490cbf3cc48b6ba6084b1c
/**
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2007 Sun Microsystems Inc. All Rights Reserved
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at opensso/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id: SecureSOAPMessage.java,v 1.30 2010/01/23 00:20:27 mrudul_uchil Exp $
*
*/
/**
* This class <code>SecureSOAPMessage</code> constructs the secured
* <code>SOAPMessage</code> for the given security mechanism token.
* @supported.all.api
*/
public class SecureSOAPMessage {
private boolean create = false;
private String server_proto =
private String server_host =
private String server_port =
private long msgTimestamp = 0;
/**
* Constructor to create secure SOAP message.
*
* @param soapMessage the SOAP message to be secured.
*
* @param create if true, creates a new secured SOAP message by adding
* security headers.
* if false, parses the secured SOAP message.
*
* @exception SecurityException if failed in creating or parsing the
* new secured SOAP message.
*/
throws SecurityException {
}
/**
* Constructor to create secure SOAP message.
*
* @param soapMessage the SOAP message to be secured.
*
* @param create if true, creates a new secured SOAP message by adding
* security headers.
* if false, parses the secured SOAP message.
* @param signedElements list of signed elements
*
* @exception SecurityException if failed in creating or parsing the
* new secured SOAP message.
*/
this.soapMessage = soapMessage;
this.signedElements = signedElements;
if(debug.messageEnabled()) {
}
if(!create) {
} else {
if(debug.messageEnabled()) {
}
}
if (debug.messageEnabled()) {
debug.message("SecureSOAPMessage.Output SOAP message: " + WSSUtils.print(soapMessage.getSOAPPart()));
}
}
/**
* Returns the Security Header Element.
*
* @return the Security Header Element.
*/
public Element getSecurityHeaderElement() {
return this.wsseHeader;
}
/**
* Returns the secured SOAP message.
*
* @return the secured SOAP message.
*/
public SOAPMessage getSOAPMessage() {
return this.soapMessage;
}
/**
* Sets the secured SOAP message.
*
* @param inSoapMessage the input secured SOAP message.
*/
this.soapMessage = inSoapMessage;
}
/**
* Parses the secured SOAP message.
* @param soapMessage the secured SOAP message which needs to be parsed.
*
* @exception SecurityException if there is any failure in parsing.
*/
throws SecurityException {
try {
if(debug.messageEnabled()) {
"No SOAP header found.");
}
}
if((headerChildNodes == null) ||
if(debug.messageEnabled()) {
"No security header found.");
}
}
continue;
}
}
}
continue;
}
}
}
} catch (SOAPException se) {
"Exception in parsing the headers.", se);
data,
null);
}
}
/**
* Parses for the security header.
* @param node security header node.
*
* @exception SecurityException if there is any error occured.
*/
continue;
}
nameSpace)) ) {
if(debug.messageEnabled()) {
+ "Assertion token found in the security header.");
}
try {
if(assertionToken.isSenderVouches()) {
} else {
}
} catch (SAMLException se) {
"Header: unable to parse the token", se);
}
nameSpace)) ) {
if(debug.messageEnabled()) {
+ "SAML2 token found in the security header.");
}
try {
if(saml2Token.isSenderVouches()) {
} else {
}
} catch (SAML2Exception se) {
"Header: unable to parse the token", se);
}
} else if( (WSSConstants.TAG_BINARY_SECURITY_TOKEN.
if(debug.messageEnabled()) {
+ "binary token found in the security header.");
}
} else {
}
if(debug.messageEnabled()) {
+ "username token found in the security header.");
}
if (passwordType != null) {
if (passwordType.equals(
} else if
}
}
if(securityToken != null) {
continue;
}
if(messageCertificate != null) {
}
throw new SecurityException(
}
} else {
if(debug.messageEnabled()) {
+ "ignore header element, " + localName);
}
}
}
}
}
/**
* Returns the security mechanism of the secure soap message.
*
* @return SecurityMechanism the security mechanism of the secure
* <code>SOAPMessage</code>.
*/
public SecurityMechanism getSecurityMechanism() {
return securityMechanism;
}
/**
* Sets the security mechanism for securing the soap message.
*
* @param securityMechanism the security mechanism that will be used
* to secure the soap message.
*/
this.securityMechanism = securityMechanism;
}
/**
* Sets the security token for securing the soap message.
*
* @param token the security token that is used to secure the soap message.
*
* @exception SecurityException if the security token can not be added
* to the security header.
*/
throws SecurityException {
if(wsseHeader == null) {
" Header is not found in the Secure SOAP Message.");
throw new SecurityException(
}
this.securityToken = token;
}
}
}
try {
} catch (SOAPException se) {
"SOAPException" , se);
}
}
/**
* Returns the security token associated with this secure soap message.
*
* @return SecurityToken the security token for this secure soap message.
*/
public SecurityToken getSecurityToken() {
return securityToken;
}
public SecurityContext getSecurityContext() {
return securityContext;
}
this.securityContext = securityContext;
}
/**
* Adds the WSSE related name spaces to the SOAP Envelope.
*/
private void addNameSpaces() throws SecurityException {
try {
} catch (SOAPException se) {
"Name spaces. ", se);
throw new SecurityException(
}
}
/**
* Adds the security header to the SOAP Envelope.
*/
private void addSecurityHeader() throws SecurityException {
if(debug.messageEnabled()) {
" security header");
}
try {
}
}
//Add time stamp
if(signingIds != null) {
}
}
} catch (SOAPException se) {
" while adding the security header.", se);
data,
null);
throw new SecurityException(
}
}
private void checkForAddressingHeaders() throws SecurityException {
try {
while(childElements.hasNext()) {
}
}
}
} catch (SOAPException se) {
"Name spaces. ", se);
throw new SecurityException(
}
}
/**
* Signs the <code>SOAPMessage</code> for the given security profile.
*
* @exception SecurityException if there is any failure in signing.
*/
public void sign()
throws SecurityException {
if(debug.messageEnabled()) {
}
// securityToken=null if the secmech is Anonymous
if (securityToken!=null) {
} else {
if((securityMechanism != null) &&
}
}
// treat Anonymous secmech (securityToken=null) same as UserName
// Token
(null==securityToken)){
} else {
" XML signing.");
}
if(debug.messageEnabled()) {
}
}
/**
* Signs the SOAP Message with SAML Assertion.
*/
securityContext.getKeyType()) ? true : false;
if(!symmetricKey) {
}
if(!symmetricKey) {
}
securityToken.getTokenType())) {
if(!symmetricKey) {
}
securityToken.getTokenType())) {
if(!symmetricKey) {
}
}
}
} else {
"Unknown security mechanism");
throw new SecurityException(
}
try {
if(securityToken instanceof AssertionToken) {
} else if (securityToken instanceof SAML2Token) {
}
if(signingKey == null) {
}
}
if(encryptionKey == null) {
} else {
}
} catch (XMLSignatureException se) {
"signing failed", se);
data,
null);
throw new SecurityException(
"signing failed", ex);
data,
null);
throw new SecurityException(
}
try {
this.soapMessage.saveChanges();
"SOAP message save failed : ", ex);
}
}
/**
* Signs the document with binary security token.
*/
try {
} catch (XMLSignatureException se) {
"Exception.", se);
data,
null);
throw new SecurityException(
"signing failed", ex);
data,
null);
throw new SecurityException(
}
try {
this.soapMessage.saveChanges();
"SOAP message save failed : ", ex);
}
}
/**
* Signs the document with kerberos security token.
*/
throws SecurityException {
try {
getSigningIds());
} catch (XMLSignatureException se) {
"Exception.", se);
data,
null);
throw new SecurityException(
"signing failed", ex);
data,
null);
throw new SecurityException(
}
try {
this.soapMessage.saveChanges();
"SOAP message save failed : ", ex);
}
}
/**
* Signs the document with binary security token.
*/
throws SecurityException {
try {
} catch (XMLSignatureException se) {
"Exception.", se);
data,
null);
throw new SecurityException(
"signing failed", ex);
data,
null);
throw new SecurityException(
}
try {
this.soapMessage.saveChanges();
"SOAP message save failed : ", ex);
}
}
/**
* Returns the list of signing ids.
*/
if(signingIds == null) {
signingIds = new ArrayList();
}
if(signedElements.isEmpty() ||
}
return signingIds;
}
/**
* Returns the messageID from the <wsa:Addressing> header.
* @return the messageID from the <wsa:Addressing> header.
*/
public String getMessageID() {
return messageID;
}
/**
* Retruns the message timestamp.
* @return the message timestamp.
*/
public long getMessageTimestamp() {
return msgTimestamp;
}
/**
* Verifies the signature of the SOAP message.
* @return true if the signature verification is successful.
* @exception SecurityException if there is any failure in validation.
*/
public boolean verifySignature() throws SecurityException {
try {
if(securityToken != null) {
} else {
}
}
if(issuerAlias == null) {
+ " issuer alias does not present in the trusted ca" +
" alias list");
return false;
}
}
+ " Signature verification for the assertion failed");
}
return false;
} else {
+ "Signature verification successful for the assertion");
}
}
}
if(messageCertificate != null) {
} else {
// check if this symmetric encrypted key
}
}
} catch (SAMLException se) {
"failed", se);
data,
null);
throw new SecurityException(
"failed", ex);
throw new SecurityException(
}
}
/**
* Verifies the signature of the SOAP message that has kerberos key.
* @param secretKey the secret key that is used for signature verification.
* @return true if the signature verification is successful.
* @exception SecurityException if there is any failure in validation.
*/
throws SecurityException {
try {
} catch (SAMLException se) {
"failed", se);
throw new SecurityException(
}
}
/**
* Converts the SOAP Message into an XML document.
*/
try {
/* make sure changes to the soapMessage are persisted before
* using writeTo() ... possibly SAAJ bug as 'writeTo()' should always
* save the changes first
*/
if (debug.messageEnabled()) {
}
if (debug.messageEnabled()) {
}
return doc;
" Convert the SOAP Message to XML document.", ex);
}
}
/**
* Returns the <code>X509Certificate</code> that is used to secure
* the <code>SOAPMessage</code>.
*
* @return the X509 certificate.
*/
public X509Certificate getMessageCertificate() {
return messageCertificate;
}
/**
* Encrypts the <code>SOAPMessage</code> for the given security profile.
*
* @param certAlias the certificate alias
* @param encryptBody boolean flag to encrypt Body
* @param encryptHeader boolean flag to encrypt Security header
*
* @exception SecurityException if there is any failure in encryption.
*/
boolean encryptBody,
boolean encryptHeader) throws SecurityException {
// securityToken=null if the secmech is Anonymous
if (securityToken == null) {
} else {
}
try {
if (encryptBody) {
}
if (encryptHeader) {
}
if(debug.messageEnabled()) {
}
if (secHeaderElement != null) {
}
}
}
doc,
0,
} catch (EncryptionException ee) {
"Exception : ", ee);
data,
null);
throw new SecurityException(
"encryption failed : ", ex);
data,
null);
throw new SecurityException(
}
try {
.equals("Signature")) {
continue;
}
break;
}
if(debug.messageEnabled()) {
}
// Append EncryptedKey element in the Security header
true);
// Append some how does not work for webshpere SOAP runtime
// So, if it's not added for whatever reason, get the enveloped
// and add it.
"EncryptedKey");
}
if(debug.messageEnabled()) {
+ "after Encrypt : "
}
// EncryptedData elements
for (int i=0; i < length; i++) {
if(debug.messageEnabled()) {
"EncryptedData DOC (" + i + ") : "
}
// Replace first child of Body element or Security
// header element with the EncryptedData element
importNode(encryptedDataElem,true);
} else if (encryptHeader) {
if(debug.messageEnabled()) {
}
}
}
}
this.soapMessage.saveChanges();
if(debug.messageEnabled()) {
}
"encryption failed : ", ex);
throw new SecurityException(
}
}
/**
* Decrypts the <code>SOAPMessage</code> for the given security profile.
* @param keyAlias private key alias that is used to decrypt.
* @param decryptBody boolean flag to decrypt Body
* @param decryptHeader boolean flag to decrypt Security header
* @exception SecurityException if there is any failure in decryption.
*/
boolean decryptBody,
boolean decryptHeader)
throws SecurityException {
try {
"is not encrypted.");
throw new SecurityException(
}
if(messageCertificate != null) {
} else {
}
} catch (EncryptionException ee) {
"encryption failed : ", ee);
data,
null);
throw new SecurityException(
"exception : ", ex);
data,
null);
throw new SecurityException(
}
try {
if (decryptBody) {
// Decrypted Body element replacement
if(debug.messageEnabled()) {
}
// Replace first child of Body element with the
// first child of Decrypted Body element
true);
getBody().getChildNodes();
continue;
}
break;
}
}
// Decrypted Security token element replacement
if (decryptHeader) {
decryptedSecHeaderElement, true);
if(debug.messageEnabled()) {
"Security Header doc : " +
"from decrypted Security header doc: " +
"from current SOAP wsseHeader : " +
}
}
}
this.soapMessage.saveChanges();
if(debug.messageEnabled()) {
}
"decryption failed : ", ex);
throw new SecurityException(
}
}
/**
* Returns the token Node for corresponding Security token.
*/
} else if( (WSSConstants.TAG_BINARY_SECURITY_TOKEN.
}
if (searchType != null) {
break;
}
}
return tokenNode;
}
continue;
}
}
}
try {
return false;
} else {
return true;
}
}
return true;
}
return true;
}
return false;
"parsing exception", pe);
return false;
}
}
try {
return;
}
"Action");
return;
}
}
} else {
}
} catch (SOAPException se) {
"SOAP Exception", se);
}
}
public String getClientDnsClaim() {
return clientDnsClaim;
}
this.signedElements = elements;
}
}