You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fx-dev@ws.apache.org by we...@apache.org on 2004/10/24 14:41:13 UTC
cvs commit: ws-fx/wss4j/src/org/apache/ws/security/util WSSecurityUtil.java
werner 2004/10/24 05:41:13
Modified: wss4j/src/org/apache/ws/security WSConstants.java
WSSecurityEngine.java
wss4j/src/org/apache/ws/security/handler WSS4JHandler.java
WSHandlerConstants.java
wss4j/src/org/apache/ws/security/message
WSSAddUsernameToken.java WSSignEnvelope.java
WSEncryptBody.java
wss4j/src/org/apache/ws/security/message/token
UsernameToken.java
wss4j/src/org/apache/ws/security/util WSSecurityUtil.java
Log:
Enhancements to support "siging with key derived from UsernameToken",
refer to E-mail conversation in ws-fx mailing list (Oct, 20, 2004).
Revision Changes Path
1.25 +11 -1 ws-fx/wss4j/src/org/apache/ws/security/WSConstants.java
Index: WSConstants.java
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/WSConstants.java,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- WSConstants.java 9 Aug 2004 17:53:42 -0000 1.24
+++ WSConstants.java 24 Oct 2004 12:41:13 -0000 1.25
@@ -300,9 +300,18 @@
* Embeds a keyinfo/wsse:SecurityTokenReference into EncryptedData element.
*/
public static final int EMBED_SECURITY_TOKEN_REF = 6;
+
+ /**
+ * <code>UT_SIGNING</code> is used interally only to set a specific Signature
+ * behaviour.
+ *
+ * The signing token is constructed from values in the UsernameToken according
+ * to WS-Trust specification.
+ */
+ public static final int UT_SIGNING = 7;
public static final int NO_SECURITY = 0;
- public static final int UT = 0x1; // perform UsernameToken only
+ public static final int UT = 0x1; // perform UsernameToken
public static final int SIGN = 0x2; // Perform Signature
public static final int ENCR = 0x4; // Perform Encryption
@@ -315,6 +324,7 @@
public static final int ST_SIGNED = 0x10; // perform SAMLToken signed
public static final int TS = 0x20; // insert Timestamp
+ public static final int UT_SIGN = 0x40; // perform sinagture with UT secrect key
public static final int NO_SERIALIZE = 0x100;
public static final int SERIALIZE = 0x200;
1.37 +187 -138 ws-fx/wss4j/src/org/apache/ws/security/WSSecurityEngine.java
Index: WSSecurityEngine.java
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/WSSecurityEngine.java,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -r1.36 -r1.37
--- WSSecurityEngine.java 20 Oct 2004 21:14:24 -0000 1.36
+++ WSSecurityEngine.java 24 Oct 2004 12:41:13 -0000 1.37
@@ -64,7 +64,6 @@
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
-import java.security.InvalidKeyException;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.CertificateExpiredException;
@@ -90,7 +89,6 @@
LogFactory.getLog("org.apache.ws.security.TIME");
private static final Class[] constructorType = {WSSConfig.class, org.w3c.dom.Element.class};
- private static boolean sigCheck = true;
private static WSSecurityEngine engine = null;
/**
* The symmetric key.
@@ -316,22 +314,27 @@
if (doDebug) {
log.debug("Found signature element");
}
- if (sigCrypto == null) {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "noSigCryptoFile");
- }
WSDocInfoStore.store(wsDocInfo);
X509Certificate[] returnCert = new X509Certificate[1];
Vector returnQname[] = new Vector[1];
try {
- lastPrincipalFound = verifyXMLSignature((Element) elem, sigCrypto, returnCert, returnQname);
- } catch (WSSecurityException ex) {
- throw ex;
- } finally {
- WSDocInfoStore.delete(wsDocInfo);
- }
- returnResults.add(0, new WSSecurityEngineResult(WSConstants.SIGN, lastPrincipalFound, returnCert[0],
- returnQname[0]));
+ lastPrincipalFound = verifyXMLSignature((Element) elem,
+ sigCrypto, returnCert, returnQname);
+ } catch (WSSecurityException ex) {
+ throw ex;
+ } finally {
+ WSDocInfoStore.delete(wsDocInfo);
+ }
+ if (lastPrincipalFound instanceof WSUsernameTokenPrincipal) {
+ returnResults.add(0, new WSSecurityEngineResult(
+ WSConstants.UT_SIGN, lastPrincipalFound, null,
+ returnQname[0]));
+
+ } else {
+ returnResults.add(0, new WSSecurityEngineResult(
+ WSConstants.SIGN, lastPrincipalFound,
+ returnCert[0], returnQname[0]));
+ }
} else if (el.equals(ENCRYPTED_KEY)) {
if (doDebug) {
log.debug("Found encrypted key element");
@@ -476,135 +479,181 @@
X509Certificate[] certs = null;
KeyInfo info = sig.getKeyInfo();
- if (/*crypto.getDefaultX509Alias() == null &&*/ info != null) {
- Node node;
- if (wssConfig.getProcessNonCompliantMessages()) {
- node = WSSecurityUtil.getDirectChildWSSE(info.getElement(),
- SecurityTokenReference.SECURITY_TOKEN_REFERENCE);
- } else {
- node = WSSecurityUtil.getDirectChild(info.getElement(),
- SecurityTokenReference.SECURITY_TOKEN_REFERENCE,
- wssConfig.getWsseNS());
- }
- if (node == null) {
- throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
- "unsupportedKeyInfo");
- }
- SecurityTokenReference secRef =
- new SecurityTokenReference(wssConfig, (Element) node);
-
- int docHash = elem.getOwnerDocument().hashCode();
- if (doDebug) {
- log.debug("XML Verify doc: " + docHash);
- }
-
- /*
- * Her we get some information about the document that is being processed,
- * in partucular the crypto implementation, and already detected BST that
- * may be used later during dereferencing.
- */
- WSDocInfo wsDocInfo = WSDocInfoStore.lookup(docHash);
-
- if (secRef.containsReference()) {
- Element token = secRef.getTokenElement(elem.getOwnerDocument(), wsDocInfo);
- // at this point ... check token type: Binary
- QName el = new QName(token.getNamespaceURI(), token.getLocalName());
- if (token.getLocalName().equals(binaryToken.getLocalPart())) { // the namespace has already been checked
- certs = getCertificatesTokenReference((Element) token, crypto);
- } else if (el.equals(SAML_TOKEN)) {
- certs = getCertificatesFromSAML((Element) token, crypto);
- } else {
- throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
- "unsupportedKeyInfo", new Object[]{el.toString()});
- }
- } else if (secRef.containsX509IssuerSerial()) {
- certs = secRef.getX509IssuerSerial(crypto);
- } else if (secRef.containsKeyIdentifier()) {
- certs = secRef.getKeyIdentifier(crypto);
- } else {
- throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
- "unsupportedKeyInfo", new Object[]{node.toString()});
- }
- } else if (crypto.getDefaultX509Alias() != null) {
- certs = crypto.getCertificates(crypto.getDefaultX509Alias());
- } else {
- throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
- "unsupportedKeyInfo");
- }
- if (tlog.isDebugEnabled()) {
+ byte[] secretKey = null;
+ UsernameToken ut = null;
+
+ if (info != null) {
+ Node node;
+ if (wssConfig.getProcessNonCompliantMessages()) {
+ node = WSSecurityUtil.getDirectChildWSSE(info.getElement(),
+ SecurityTokenReference.SECURITY_TOKEN_REFERENCE);
+ } else {
+ node = WSSecurityUtil.getDirectChild(info.getElement(),
+ SecurityTokenReference.SECURITY_TOKEN_REFERENCE,
+ wssConfig.getWsseNS());
+ }
+ if (node == null) {
+ throw new WSSecurityException(
+ WSSecurityException.INVALID_SECURITY,
+ "unsupportedKeyInfo");
+ }
+ SecurityTokenReference secRef = new SecurityTokenReference(
+ wssConfig, (Element) node);
+
+ int docHash = elem.getOwnerDocument().hashCode();
+ /*
+ * Her we get some information about the document that is being
+ * processed, in partucular the crypto implementation, and already
+ * detected BST that may be used later during dereferencing.
+ */
+ WSDocInfo wsDocInfo = WSDocInfoStore.lookup(docHash);
+
+ if (secRef.containsReference()) {
+ Element token = secRef.getTokenElement(elem.getOwnerDocument(),
+ wsDocInfo);
+ /*
+ * at this point check token type: UsernameToken, Binary, SAML
+ * Crypto required only for Binary and SAML
+ */
+ QName el = new QName(token.getNamespaceURI(), token
+ .getLocalName());
+ if (token.getLocalName().equals(UsernameToken.TOKEN)) {
+ ut = new UsernameToken(wssConfig, token);
+ secretKey = ut.getSecretKey();
+ } else {
+ if (crypto == null) {
+ throw new WSSecurityException(WSSecurityException.FAILURE,
+ "noSigCryptoFile");
+ }
+ if (token.getLocalName().equals(binaryToken.getLocalPart())) {
+ certs = getCertificatesTokenReference((Element) token,
+ crypto);
+ } else if (el.equals(SAML_TOKEN)) {
+ certs = getCertificatesFromSAML((Element) token, crypto);
+ } else {
+ throw new WSSecurityException(
+ WSSecurityException.INVALID_SECURITY,
+ "unsupportedKeyInfo", new Object[] { el
+ .toString() });
+ }
+ }
+ } else if (secRef.containsX509IssuerSerial()) {
+ certs = secRef.getX509IssuerSerial(crypto);
+ } else if (secRef.containsKeyIdentifier()) {
+ certs = secRef.getKeyIdentifier(crypto);
+ } else {
+ throw new WSSecurityException(
+ WSSecurityException.INVALID_SECURITY,
+ "unsupportedKeyInfo", new Object[] { node.toString() });
+ }
+ } else {
+ if (crypto == null) {
+ throw new WSSecurityException(WSSecurityException.FAILURE,
+ "noSigCryptoFile");
+ }
+ if (crypto.getDefaultX509Alias() != null) {
+ certs = crypto.getCertificates(crypto.getDefaultX509Alias());
+ } else {
+ throw new WSSecurityException(
+ WSSecurityException.INVALID_SECURITY,
+ "unsupportedKeyInfo");
+ }
+ }
+ if (tlog.isDebugEnabled()) {
t1 = System.currentTimeMillis();
}
- if (certs == null || certs.length == 0 || certs[0] == null) {
+ if ((certs == null || certs.length == 0 || certs[0] == null) && secretKey == null) {
throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
}
+ if (certs != null) {
+ try {
+ certs[0].checkValidity();
+ } catch (CertificateExpiredException e) {
+ throw new WSSecurityException(WSSecurityException.FAILED_CHECK,
+ "invalidCert");
+ } catch (CertificateNotYetValidException e) {
+ throw new WSSecurityException(WSSecurityException.FAILED_CHECK,
+ "invalidCert");
+ }
+ }
try {
- certs[0].checkValidity();
- } catch (CertificateExpiredException e) {
- throw new WSSecurityException(WSSecurityException.FAILED_CHECK,
- "invalidCert");
- } catch (CertificateNotYetValidException e) {
- throw new WSSecurityException(WSSecurityException.FAILED_CHECK,
- "invalidCert");
- }
- try {
- if (sigCheck && sig.checkSignatureValue(certs[0])) {
- if (tlog.isDebugEnabled()) {
- t2 = System.currentTimeMillis();
- tlog.debug("Verify: total= "
- + (t2 - t0)
- + ", prepare-cert= "
- + (t1 - t0)
- + ", verify= "
- + (t2 - t1));
- }
- /*
- * Now dig into the Signature element to get the elements that this
- * Signature covers. Build the QName of these Elements and return
- * them to caller
- */
- SignedInfo si = sig.getSignedInfo();
- int numReferences = si.getLength();
- Vector qvec = new Vector(numReferences);
- for (int i = 0; i < numReferences; i++) {
- Reference siRef;
- try {
- siRef = si.item(i);
- } catch (XMLSecurityException e3) {
- throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
- // TODO Auto-generated catch block
- // e3.printStackTrace();
- }
- String uri = siRef.getURI();
- Element se = WSSecurityUtil.getElementByWsuId(wssConfig, elem.getOwnerDocument(), uri);
- if (se == null) {
- se = WSSecurityUtil.getElementByGenId(elem.getOwnerDocument(), uri);
- }
- if (se == null) {
- throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
- }
- QName qn = new QName(se.getNamespaceURI(), se.getLocalName());
- qvec.add(qn);
- }
- returnQname[0] = qvec;
- returnCert[0] = certs[0];
- return certs[0].getSubjectDN();
- } else {
- throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
- }
- } catch (XMLSignatureException e1) {
- throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
- }
- }
-
- /**
- * Extracts the certificate(s) from the Binary Security token reference.
- * <p/>
- *
- * @param elem The element containing the binary security token. This
- * is either X509 certificate(s) or a PKIPath.
- * @return an array of X509 certificates
- * @throws WSSecurityException
- */
+ boolean signatureOk = false;
+ if (certs != null) {
+ signatureOk = sig.checkSignatureValue(certs[0]);
+ } else {
+ signatureOk = sig.checkSignatureValue(sig
+ .createSecretKey(secretKey));
+ }
+ if (signatureOk) {
+ if (tlog.isDebugEnabled()) {
+ t2 = System.currentTimeMillis();
+ tlog.debug("Verify: total= " + (t2 - t0)
+ + ", prepare-cert= " + (t1 - t0) + ", verify= "
+ + (t2 - t1));
+ }
+ /*
+ * Now dig into the Signature element to get the elements that
+ * this Signature covers. Build the QName of these Elements and
+ * return them to caller
+ */
+ SignedInfo si = sig.getSignedInfo();
+ int numReferences = si.getLength();
+ Vector qvec = new Vector(numReferences);
+ for (int i = 0; i < numReferences; i++) {
+ Reference siRef;
+ try {
+ siRef = si.item(i);
+ } catch (XMLSecurityException e3) {
+ throw new WSSecurityException(
+ WSSecurityException.FAILED_CHECK);
+ }
+ String uri = siRef.getURI();
+ Element se = WSSecurityUtil.getElementByWsuId(wssConfig,
+ elem.getOwnerDocument(), uri);
+ if (se == null) {
+ se = WSSecurityUtil.getElementByGenId(elem
+ .getOwnerDocument(), uri);
+ }
+ if (se == null) {
+ throw new WSSecurityException(
+ WSSecurityException.FAILED_CHECK);
+ }
+ QName qn = new QName(se.getNamespaceURI(), se
+ .getLocalName());
+ qvec.add(qn);
+ }
+ returnQname[0] = qvec;
+ if (certs != null) {
+ returnCert[0] = certs[0];
+ return certs[0].getSubjectDN();
+ } else {
+ WSUsernameTokenPrincipal principal = new WSUsernameTokenPrincipal(
+ ut.getName(), ut.isHashed());
+ principal.setNonce(ut.getNonce());
+ principal.setPassword(ut.getPassword());
+ principal.setCreatedTime(ut.getCreated());
+ return principal;
+ }
+ } else {
+ throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
+ }
+ } catch (XMLSignatureException e1) {
+ throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
+ } catch (XMLSecurityException e1) {
+ throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
+ }
+ }
+
+ /**
+ * Extracts the certificate(s) from the Binary Security token reference.
+ * <p/>
+ *
+ * @param elem
+ * The element containing the binary security token. This is
+ * either X509 certificate(s) or a PKIPath.
+ * @return an array of X509 certificates
+ * @throws WSSecurityException
+ */
public X509Certificate[] getCertificatesTokenReference(Element elem,
Crypto crypto)
throws WSSecurityException {
1.3 +84 -42 ws-fx/wss4j/src/org/apache/ws/security/handler/WSS4JHandler.java
Index: WSS4JHandler.java
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/handler/WSS4JHandler.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- WSS4JHandler.java 18 Aug 2004 06:54:45 -0000 1.2
+++ WSS4JHandler.java 24 Oct 2004 12:41:13 -0000 1.3
@@ -38,6 +38,7 @@
import org.apache.ws.security.saml.SAMLIssuerFactory;
import org.apache.ws.security.util.StringUtil;
import org.apache.ws.security.util.WSSecurityUtil;
+import org.apache.xml.security.signature.XMLSignature;
import org.opensaml.SAMLAssertion;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
@@ -221,7 +222,7 @@
* functions. No need to do it for encryption only. Check if username
* is available and then get a passowrd.
*/
- if ((doAction & (WSConstants.SIGN | WSConstants.UT)) != 0) {
+ if ((doAction & (WSConstants.SIGN | WSConstants.UT | WSConstants.UT_SIGN)) != 0) {
/*
* We need a username - if none throw an JAXRPCException. For encryption
* there is a specific parameter to get a username.
@@ -275,6 +276,13 @@
decodeUTParameter();
}
/*
+ * Here we have action, username, password, and actor, mustUnderstand.
+ * Now get the action specific parameters.
+ */
+ if ((doAction & WSConstants.UT_SIGN) == WSConstants.UT_SIGN) {
+ decodeUTParameter();
+ }
+ /*
* Get and check the Signature specific parameters first because they
* may be used for encryption too.
*/
@@ -309,49 +317,53 @@
}
switch (actionToDo) {
- case WSConstants.UT:
- performUTAction(actionToDo, mu, doc);
- break;
-
- case WSConstants.ENCR:
- performENCRAction(mu, actionToDo, doc);
- break;
-
- case WSConstants.SIGN:
- performSIGNAction(actionToDo, mu, doc);
- break;
-
- case WSConstants.ST_SIGNED:
- performST_SIGNAction(actionToDo, mu, doc);
- break;
-
- case WSConstants.ST_UNSIGNED:
- performSTAction(mu, doc);
- break;
-
- case WSConstants.TS:
- performTSAction(mu, doc);
- break;
-
- case WSConstants.NO_SERIALIZE:
- noSerialization = true;
- break;
- }
+ case WSConstants.UT:
+ performUTAction(actionToDo, mu, doc);
+ break;
+
+ case WSConstants.ENCR:
+ performENCRAction(mu, actionToDo, doc);
+ break;
+
+ case WSConstants.SIGN:
+ performSIGNAction(actionToDo, mu, doc);
+ break;
+
+ case WSConstants.ST_SIGNED:
+ performST_SIGNAction(actionToDo, mu, doc);
+ break;
+
+ case WSConstants.ST_UNSIGNED:
+ performSTAction(mu, doc);
+ break;
+
+ case WSConstants.TS:
+ performTSAction(mu, doc);
+ break;
+
+ case WSConstants.UT_SIGN:
+ performUT_SIGNAction(actionToDo, mu, doc);
+ break;
+
+ case WSConstants.NO_SERIALIZE:
+ noSerialization = true;
+ break;
+ }
}
/*
- * If required convert the resulting document into a message first. The
- * outputDOM() method performs the necessary c14n call. After that we
- * extract it as a string for further processing.
- *
- * Set the resulting byte array as the new SOAP message.
- *
- * If noSerialization is false, this handler shall be the last (or
- * only) one in a handler chain. If noSerialization is true, just set
- * the processed Document in the transfer property. The next Axis WSS4J
- * handler takes it and performs additional security processing steps.
- *
- */
+ * If required convert the resulting document into a message first. The
+ * outputDOM() method performs the necessary c14n call. After that we
+ * extract it as a string for further processing.
+ *
+ * Set the resulting byte array as the new SOAP message.
+ *
+ * If noSerialization is false, this handler shall be the last (or only)
+ * one in a handler chain. If noSerialization is true, just set the
+ * processed Document in the transfer property. The next Axis WSS4J
+ * handler takes it and performs additional security processing steps.
+ *
+ */
if (noSerialization) {
msgContext.setProperty(WSHandlerConstants.SND_SECURITY, doc);
} else {
@@ -1086,6 +1098,32 @@
}
}
+ private void performUT_SIGNAction(int actionToDo, boolean mu, Document doc)
+ throws JAXRPCException {
+ String password;
+ password = getPassword(username, actionToDo,
+ WSHandlerConstants.PW_CALLBACK_CLASS,
+ WSHandlerConstants.PW_CALLBACK_REF).getPassword();
+
+ WSSAddUsernameToken builder = new WSSAddUsernameToken(actor, mu);
+ builder.setPasswordType(WSConstants.PASSWORD_TEXT);
+ builder.preSetUsernameToken(doc, username, password);
+ builder.addCreated(doc);
+ builder.addNonce(doc);
+
+ WSSignEnvelope sign = new WSSignEnvelope(actor, mu);
+ sign.setUsernameToken(builder);
+ sign.setKeyIdentifierType(WSConstants.UT_SIGNING);
+ sign.setSignatureAlgorithm(XMLSignature.ALGO_ID_MAC_HMAC_SHA1);
+ try {
+ sign.build(doc, null);
+ } catch (WSSecurityException e) {
+ throw new JAXRPCException("WSS4JHandler: Error during Signatur with UsernameToken secret"
+ + e);
+ }
+ builder.build(doc, null, null);
+ }
+
private void performSTAction(boolean mu, Document doc)
throws JAXRPCException {
WSSAddSAMLToken builder = new WSSAddSAMLToken(actor, mu);
@@ -1220,6 +1258,9 @@
} else if (single[i].equals(WSHandlerConstants.NO_SERIALIZATION)) {
doAction |= WSConstants.NO_SERIALIZE;
actions.add(new Integer(WSConstants.NO_SERIALIZE));
+ } else if (single[i].equals(WSHandlerConstants.SIGN_WITH_UT_KEY)) {
+ doAction |= WSConstants.UT_SIGN;
+ actions.add(new Integer(WSConstants.UT_SIGN));
} else {
throw new JAXRPCException("WSS4JHandler: Unknown action defined" + single[i]);
}
@@ -1524,7 +1565,8 @@
int reason = 0;
switch (doAction) {
- case WSConstants.UT:
+ case WSConstants.UT:
+ case WSConstants.UT_SIGN:
reason = WSPasswordCallback.USERNAME_TOKEN;
break;
case WSConstants.SIGN:
1.2 +1 -0 ws-fx/wss4j/src/org/apache/ws/security/handler/WSHandlerConstants.java
Index: WSHandlerConstants.java
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/handler/WSHandlerConstants.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- WSHandlerConstants.java 12 Aug 2004 17:42:09 -0000 1.1
+++ WSHandlerConstants.java 24 Oct 2004 12:41:13 -0000 1.2
@@ -98,6 +98,7 @@
*/
public static final String NO_SERIALIZATION = "NoSerialization";
+ public static final String SIGN_WITH_UT_KEY = "UsernameTokenSignature";
/**
* This is an interal property name to support handler chaining.
* The Axis WSS4J handlers use this message context property to
1.9 +12 -3 ws-fx/wss4j/src/org/apache/ws/security/message/WSSAddUsernameToken.java
Index: WSSAddUsernameToken.java
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/message/WSSAddUsernameToken.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- WSSAddUsernameToken.java 11 Aug 2004 12:39:33 -0000 1.8
+++ WSSAddUsernameToken.java 24 Oct 2004 12:41:13 -0000 1.9
@@ -119,6 +119,9 @@
ut.setID(id);
}
+ public byte[] getSecretKey() {
+ return ut.getSecretKey();
+ }
/**
* get the id
* @return
@@ -127,6 +130,12 @@
return id;
}
+ public Document preSetUsernameToken(Document doc, String username, String password) {
+ ut = new UsernameToken(wssConfig, doc, passwordType);
+ ut.setName(username);
+ ut.setPassword(password);
+ return doc;
+ }
/**
* Adds a new <code>UsernameToken</code> to a soap envelope.
* <p/>
@@ -141,9 +150,9 @@
public Document build(Document doc, String username, String password) { // throws Exception {
log.debug("Begin add username token...");
Element securityHeader = insertSecurityHeader(doc);
- ut = new UsernameToken(wssConfig, doc, passwordType);
- ut.setName(username);
- ut.setPassword(password);
+ if (ut == null) {
+ preSetUsernameToken(doc, username, password);
+ }
if (id != null)
ut.setID(id);
WSSecurityUtil.prependChildElement(doc, securityHeader, ut.getElement(), true);
1.20 +571 -572 ws-fx/wss4j/src/org/apache/ws/security/message/WSSignEnvelope.java
Index: WSSignEnvelope.java
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/message/WSSignEnvelope.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- WSSignEnvelope.java 9 Aug 2004 17:53:45 -0000 1.19
+++ WSSignEnvelope.java 24 Oct 2004 12:41:13 -0000 1.20
@@ -66,142 +66,150 @@
*/
public class WSSignEnvelope extends WSBaseMessage {
- private static Log log = LogFactory.getLog(WSSignEnvelope.class.getName());
+ private static Log log = LogFactory.getLog(WSSignEnvelope.class.getName());
- private static Log tlog = LogFactory.getLog("org.apache.ws.security.TIME");
+ private static Log tlog = LogFactory.getLog("org.apache.ws.security.TIME");
- protected boolean useSingleCert = true;
+ protected boolean useSingleCert = true;
- protected String sigAlgo = null;
+ protected String sigAlgo = null;
- protected String canonAlgo = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;
-
- static {
- Transform.init();
- try {
- Transform.register(STRTransform.implementedTransformURI,
- "org.apache.ws.security.transform.STRTransform");
- } catch (Exception ex) {
- }
- ;
- }
-
- /**
- * Constructor.
- */
- public WSSignEnvelope() {
- }
-
- /**
- * Constructor. <p/>
- *
- * @param actor The actor name of the <code>wsse:Security</code> header
- */
- public WSSignEnvelope(String actor) {
- super(actor);
- }
-
- /**
- * Constructor. <p/>
- *
- * @param actor The actor name of the <code>wsse:Security</code> header
- * @param mu Set <code>mustUnderstand</code> to true or false
- */
- public WSSignEnvelope(String actor, boolean mu) {
- super(actor, mu);
- }
-
- /**
- * Constructor. <p/>
- *
- * @param wssConfig Configuration options for processing and building security headers
- * @param actor The actor name of the <code>wsse:Security</code> header
- * @param mu Set <code>mustUnderstand</code> to true or false
- */
- public WSSignEnvelope(WSSConfig wssConfig, String actor, boolean mu) {
- super(wssConfig, actor, mu);
- }
-
- /**
- * set the single cert flag. <p/>
- *
- * @param useSingleCert
- */
- public void setUseSingleCertificate(boolean useSingleCert) {
- this.useSingleCert = useSingleCert;
- }
-
- /**
- * Get the single cert flag. <p/>
- *
- * @return
- */
- public boolean isUseSingleCertificate() {
- return this.useSingleCert;
- }
-
- /**
- * Set the name of the signature encryption algorithm to use <p/>If the
- * algorithm is not set then Triple RSA is used. Refer to WSConstants which
- * algorithms are supported. <p/>
- *
- * @param algo Is the name of the signature algorithm
- * @see WSConstants#RSA
- * @see WSConstants#DSA
- */
- public void setSignatureAlgorithm(String algo) {
- sigAlgo = algo;
- }
-
- /**
- * Get the name of the signature algorithm that is being used <p/>If the
- * algorithm is not set then RSA is default. <p/>
- *
- * @return
- */
- public String getSignatureAlgorithm() {
- return sigAlgo;
- }
-
- /**
- * Set the canonicalization method to use. <p/>If the canonicalization
- * method is not set then the recommended Exclusive XML Canonicalization is
- * used by default Refer to WSConstants which algorithms are supported.
- * <p/>
- *
- * @param algo Is the name of the signature algorithm
- * @see WSConstants#C14N_OMIT_COMMENTS
- * @see WSConstants#C14N_WITH_COMMENTS
- * @see WSConstants#C14N_EXCL_OMIT_COMMENTS
- * @see WSConstants#C14N_EXCL_WITH_COMMENTS
- */
- public void setSigCanonicalization(String algo) {
- canonAlgo = algo;
- }
-
- /**
- * Get the canonicalization method. <p/>If the canonicalization method was
- * not set then Exclusive XML Canonicalization is used by default. <p/>
- *
- * @return
- */
- public String getSigCanonicalization() {
- return canonAlgo;
- }
-
- /**
- * Builds a signed soap envelope. <p/>The method first gets an appropriate
- * security header. According to the defined parameters for certificate
- * handling the signature elements are constructed and inserted into the
- * <code>wsse:Signature</code>
- *
- * @param doc The unsigned SOAP envelope as <code>Document</code>
- * @param crypto An instance of the Crypto API to handle keystore and
- * certificates
- * @return A signed SOAP envelope as <code>Document</code>
- * @throws Exception
- */
- public Document build(Document doc, Crypto crypto)
+ protected String canonAlgo = Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;
+
+ protected WSSAddUsernameToken usernameToken = null;
+
+ static {
+ Transform.init();
+ try {
+ Transform.register(STRTransform.implementedTransformURI,
+ "org.apache.ws.security.transform.STRTransform");
+ } catch (Exception ex) {
+ }
+ ;
+ }
+
+ /**
+ * Constructor.
+ */
+ public WSSignEnvelope() {
+ }
+
+ /**
+ * Constructor. <p/>
+ *
+ * @param actor The actor name of the <code>wsse:Security</code> header
+ */
+ public WSSignEnvelope(String actor) {
+ super(actor);
+ }
+
+ /**
+ * Constructor. <p/>
+ *
+ * @param actor The actor name of the <code>wsse:Security</code> header
+ * @param mu Set <code>mustUnderstand</code> to true or false
+ */
+ public WSSignEnvelope(String actor, boolean mu) {
+ super(actor, mu);
+ }
+
+ /**
+ * Constructor. <p/>
+ *
+ * @param wssConfig Configuration options for processing and building security headers
+ * @param actor The actor name of the <code>wsse:Security</code> header
+ * @param mu Set <code>mustUnderstand</code> to true or false
+ */
+ public WSSignEnvelope(WSSConfig wssConfig, String actor, boolean mu) {
+ super(wssConfig, actor, mu);
+ }
+
+ /**
+ * set the single cert flag. <p/>
+ *
+ * @param useSingleCert
+ */
+ public void setUseSingleCertificate(boolean useSingleCert) {
+ this.useSingleCert = useSingleCert;
+ }
+
+ /**
+ * Get the single cert flag. <p/>
+ *
+ * @return
+ */
+ public boolean isUseSingleCertificate() {
+ return this.useSingleCert;
+ }
+
+ /**
+ * Set the name of the signature encryption algorithm to use <p/>If the
+ * algorithm is not set then Triple RSA is used. Refer to WSConstants which
+ * algorithms are supported. <p/>
+ *
+ * @param algo Is the name of the signature algorithm
+ * @see WSConstants#RSA
+ * @see WSConstants#DSA
+ */
+ public void setSignatureAlgorithm(String algo) {
+ sigAlgo = algo;
+ }
+
+ /**
+ * Get the name of the signature algorithm that is being used <p/>If the
+ * algorithm is not set then RSA is default. <p/>
+ *
+ * @return
+ */
+ public String getSignatureAlgorithm() {
+ return sigAlgo;
+ }
+
+ /**
+ * Set the canonicalization method to use. <p/>If the canonicalization
+ * method is not set then the recommended Exclusive XML Canonicalization is
+ * used by default Refer to WSConstants which algorithms are supported.
+ * <p/>
+ *
+ * @param algo Is the name of the signature algorithm
+ * @see WSConstants#C14N_OMIT_COMMENTS
+ * @see WSConstants#C14N_WITH_COMMENTS
+ * @see WSConstants#C14N_EXCL_OMIT_COMMENTS
+ * @see WSConstants#C14N_EXCL_WITH_COMMENTS
+ */
+ public void setSigCanonicalization(String algo) {
+ canonAlgo = algo;
+ }
+
+ /**
+ * Get the canonicalization method. <p/>If the canonicalization method was
+ * not set then Exclusive XML Canonicalization is used by default. <p/>
+ *
+ * @return
+ */
+ public String getSigCanonicalization() {
+ return canonAlgo;
+ }
+
+ /**
+ * @param usernameToken The usernameToken to set.
+ */
+ public void setUsernameToken(WSSAddUsernameToken usernameToken) {
+ this.usernameToken = usernameToken;
+ }
+ /**
+ * Builds a signed soap envelope. <p/>The method first gets an appropriate
+ * security header. According to the defined parameters for certificate
+ * handling the signature elements are constructed and inserted into the
+ * <code>wsse:Signature</code>
+ *
+ * @param doc The unsigned SOAP envelope as <code>Document</code>
+ * @param crypto An instance of the Crypto API to handle keystore and
+ * certificates
+ * @return A signed SOAP envelope as <code>Document</code>
+ * @throws Exception
+ */
+public Document build(Document doc, Crypto crypto)
throws WSSecurityException {
doDebug = log.isDebugEnabled();
@@ -214,9 +222,9 @@
}
/*
- * Gather some info about the document to process and store it for
- * retrival
- */
+ * Gather some info about the document to process and store it for
+ * retrival
+ */
WSDocInfo wsDocInfo = new WSDocInfo(doc.hashCode());
wsDocInfo.setCrypto(crypto);
@@ -227,24 +235,29 @@
// Set the id of the elements to be used as digest source
// String id = setBodyID(doc);
- X509Certificate[] certs = crypto.getCertificates(user);
- if (certs == null || certs.length <= 0) {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "invalidX509Data",
- new Object[]{"for Signature"});
- }
- if (sigAlgo == null) {
- String pubKeyAlgo = certs[0].getPublicKey().getAlgorithm();
- log.debug("automatic sig algo detection: " + pubKeyAlgo);
- if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
- sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA;
- } else if (pubKeyAlgo.equalsIgnoreCase("RSA")) {
- sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_RSA;
- } else {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "invalidX509Data",
- new Object[]{"for Signature - unkown public key Algo"});
- }
+ String certUri = null;
+ X509Certificate[] certs = null;
+ if (keyIdentifierType != WSConstants.UT_SIGNING) {
+ certs = crypto.getCertificates(user);
+ if (certs == null || certs.length <= 0) {
+ throw new WSSecurityException(WSSecurityException.FAILURE,
+ "invalidX509Data",
+ new Object[]{"for Signature"});
+ }
+ certUri = "CertId-" + certs[0].hashCode();
+ if (sigAlgo == null) {
+ String pubKeyAlgo = certs[0].getPublicKey().getAlgorithm();
+ log.debug("automatic sig algo detection: " + pubKeyAlgo);
+ if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
+ sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA;
+ } else if (pubKeyAlgo.equalsIgnoreCase("RSA")) {
+ sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_RSA;
+ } else {
+ throw new WSSecurityException(WSSecurityException.FAILURE,
+ "invalidX509Data",
+ new Object[]{"for Signature - unkown public key Algo"});
+ }
+ }
}
XMLSignature sig = null;
try {
@@ -254,11 +267,11 @@
"noXMLSig");
}
/*
- * If we don't generate a new Transforms for each addDocument here,
- * then only the last Transforms is put into the according ds:Reference
- * element, i.e. the first ds:Reference does not contain a Transforms
- * element. Thus the verification fails (somehow)
- */
+ * If we don't generate a new Transforms for each addDocument here, then
+ * only the last Transforms is put into the according ds:Reference
+ * element, i.e. the first ds:Reference does not contain a Transforms
+ * element. Thus the verification fails (somehow)
+ */
KeyInfo info = sig.getKeyInfo();
String keyInfoUri = "KeyId-" + info.hashCode();
@@ -268,7 +281,6 @@
String strUri = "STRId-" + secRef.hashCode();
secRef.setID(strUri);
- String certUri = "CertId-" + certs[0].hashCode();
if (tlog.isDebugEnabled()) {
t1 = System.currentTimeMillis();
@@ -291,14 +303,14 @@
String nmSpace = encPart.getNamespace();
/*
- * Set up the elements to sign. There are two resevered element
- * names: "Token" and "STRTransform" "Token": Setup the Signature
- * to either sign the information that points to the security token
- * or the token itself. If its a direct reference sign the token,
- * otherwise sign the KeyInfo Element. "STRTransform": Setup the
- * ds:Reference to use STR Transform
- *
- */
+ * Set up the elements to sign. There are two resevered element
+ * names: "Token" and "STRTransform" "Token": Setup the Signature to
+ * either sign the information that points to the security token or
+ * the token itself. If its a direct reference sign the token,
+ * otherwise sign the KeyInfo Element. "STRTransform": Setup the
+ * ds:Reference to use STR Transform
+ *
+ */
try {
if (elemName.equals("Token")) {
transforms = new Transforms(doc);
@@ -351,6 +363,8 @@
if (tlog.isDebugEnabled()) {
t2 = System.currentTimeMillis();
}
+
+ byte[] secretKey = null;
switch (keyIdentifierType) {
case WSConstants.BST_DIRECT_REFERENCE:
Reference ref = new Reference(wssConfig, doc);
@@ -388,397 +402,35 @@
secRef.setKeyIdentifierSKI(certs[0], crypto);
break;
- default :
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "unsupportedKeyId");
- }
- if (tlog.isDebugEnabled()) {
- t3 = System.currentTimeMillis();
- }
- info.addUnknownElement(secRef.getElement());
-
- WSDocInfoStore.store(wsDocInfo);
- try {
- sig.sign(crypto.getPrivateKey(user, password));
- } catch (XMLSignatureException e1) {
- throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
- null,
- null,
- e1);
- } catch (Exception e1) {
- throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
- null,
- null,
- e1);
- } finally {
- WSDocInfoStore.delete(wsDocInfo);
- }
- if (tlog.isDebugEnabled()) {
- t4 = System.currentTimeMillis();
- tlog.debug("SignEnvelope: cre-Sig= "
- + (t1 - t0)
- + " set transform= "
- + (t2 - t1)
- + " sec-ref= "
- + (t3 - t2)
- + " signature= "
- + (t4 - t3));
- }
- if (doDebug) {
- log.debug("Signing complete.");
- }
- return (doc);
- }
-
- /**
- * Builds a signed soap envelope with SAML token. <p/>The method first
- * gets an appropriate security header. According to the defined parameters
- * for certificate handling the signature elements are constructed and
- * inserted into the <code>wsse:Signature</code>
- *
- * @param doc The unsigned SOAP envelope as <code>Document</code>
- * @param assertion the complete SAML assertion
- * @param issuerCrypto An instance of the Crypto API to handle keystore SAML token
- * issuer and to generate certificates
- * @param issuerKeyName Private key to use in case of "sender-Vouches"
- * @param issuerKeyPW Password for issuer private key
- * @return A signed SOAP envelope as <code>Document</code>
- * @throws Exception
- */
- public Document build(Document doc,
- Crypto userCrypto,
- SAMLAssertion assertion,
- Crypto issuerCrypto,
- String issuerKeyName,
- String issuerKeyPW)
- throws WSSecurityException {
-
- doDebug = log.isDebugEnabled();
-
- long t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0;
- if (tlog.isDebugEnabled()) {
- t0 = System.currentTimeMillis();
- }
- if (doDebug) {
- log.debug("Beginning ST signing...");
- }
- /*
- * Get some information about the SAML token content. This controls how
- * to deal with the whole stuff. First get the Authentication statement
- * (includes Subject), then get the _first_ confirmation method only.
- */
- SAMLSubjectStatement samlSubjS = null;
- Iterator it = assertion.getStatements();
- while (it.hasNext()) {
- SAMLObject so = (SAMLObject) it.next();
- if (so instanceof SAMLSubjectStatement) {
- samlSubjS = (SAMLSubjectStatement) so;
+ case WSConstants.UT_SIGNING:
+ Reference refUt = new Reference(wssConfig, doc);
+ refUt.setValueType(WSConstants.USERNAMETOKEN_NS + "#UsernameToken");
+ String utId = usernameToken.getId();
+ if (utId == null) {
+ utId = "usernameTokenId-" + usernameToken.hashCode();
+ usernameToken.setId(utId);
+ }
+ refUt.setURI("#" + utId);
+ secRef.setReference(refUt);
+ secretKey = usernameToken.getSecretKey();
break;
- }
- }
- SAMLSubject samlSubj = null;
- if (samlSubjS != null) {
- samlSubj = samlSubjS.getSubject();
- }
- if (samlSubj == null) {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "invalidSAMLToken",
- new Object[]{"for Signature"});
- }
-
- String confirmMethod = null;
- it = samlSubj.getConfirmationMethods();
- if (it.hasNext()) {
- confirmMethod = (String) it.next();
- }
- boolean senderVouches = false;
- if (SAMLSubject.CONF_SENDER_VOUCHES.equals(confirmMethod)) {
- senderVouches = true;
- }
- /*
- * Gather some info about the document to process and store it for
- * retrival
- */
- WSDocInfo wsDocInfo = new WSDocInfo(doc.hashCode());
-
- Element envelope = doc.getDocumentElement();
- SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
-
- Element securityHeader = insertSecurityHeader(doc);
- X509Certificate[] certs = null;
-
- if (senderVouches) {
- certs = issuerCrypto.getCertificates(issuerKeyName);
- wsDocInfo.setCrypto(issuerCrypto);
- }
- /*
- * in case of key holder:
- * - get the user's certificate that _must_ be included in the SAML
- * token. To ensure the cert integrity the SAML token must be signed
- * (by the issuer). Just check if its signed, but
- * don't verify this SAML token's signature here (maybe later).
- */
- else {
- if (userCrypto == null || assertion.isSigned() == false) {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "invalidSAMLsecurity",
- new Object[]{"for SAML Signature (Key Holder)"});
- }
- Element e = samlSubj.getKeyInfo();
- try {
- KeyInfo ki = new KeyInfo(e, null);
-
- if (ki.containsX509Data()) {
- X509Data data = ki.itemX509Data(0);
- XMLX509Certificate certElem = null;
- if (data != null && data.containsCertificate()) {
- certElem = data.itemCertificate(0);
- }
- if (certElem != null) {
- X509Certificate cert = certElem.getX509Certificate();
- certs = new X509Certificate[1];
- certs[0] = cert;
- }
- }
- // TODO: get alias name for cert, check against username set by caller
- } catch (XMLSecurityException e3) {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "invalidSAMLsecurity",
- new Object[]{"cannot get certificate (key holder)"},
- e3);
- }
- wsDocInfo.setCrypto(userCrypto);
- }
- // Set the id of the elements to be used as digest source
- // String id = setBodyID(doc);
- if (certs == null || certs.length <= 0) {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "invalidX509Data",
- new Object[]{"for Signature"});
- }
- if (sigAlgo == null) {
- String pubKeyAlgo = certs[0].getPublicKey().getAlgorithm();
- log.debug("automatic sig algo detection: " + pubKeyAlgo);
- if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
- sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA;
- } else if (pubKeyAlgo.equalsIgnoreCase("RSA")) {
- sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_RSA;
- } else {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "invalidX509Data",
- new Object[]{"for Signature - unkown public key Algo"});
- }
- }
- XMLSignature sig = null;
- try {
- sig = new XMLSignature(doc, null, sigAlgo, canonAlgo);
- } catch (XMLSecurityException e) {
- throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
- "noXMLSig");
- }
-
- KeyInfo info = sig.getKeyInfo();
- String keyInfoUri = "KeyId-" + info.hashCode();
- info.setId(keyInfoUri);
-
- SecurityTokenReference secRef = new SecurityTokenReference(wssConfig, doc);
- String strUri = "STRId-" + secRef.hashCode();
- secRef.setID(strUri);
-
- String certUri = "CertId-" + certs[0].hashCode();
-
- if (tlog.isDebugEnabled()) {
- t1 = System.currentTimeMillis();
- }
-
- if (parts == null) {
- parts = new Vector();
- WSEncryptionPart encP =
- new WSEncryptionPart(soapConstants.getBodyQName().getLocalPart(),
- soapConstants.getEnvelopeURI(),
- "Content");
- parts.add(encP);
- }
-
- /*
- * If the sender vouches, then we must sign the SAML token _and_ at
- * least one part of the message (usually the SOAP body). To do so we
- * need to
- * - put in a reference to the SAML token. Thus we create a STR
- * and insert it into the wsse:Security header
- * - set a reference of the created STR to the signature and use STR
- * Transfrom during the signature
- */
- Transforms transforms = null;
- SecurityTokenReference secRefSaml = null;
-
- try {
- if (senderVouches) {
- secRefSaml = new SecurityTokenReference(wssConfig, doc);
- String strSamlUri = "STRSAMLId-" + secRefSaml.hashCode();
- secRefSaml.setID(strSamlUri);
- // Decouple Refernce/KeyInfo setup - quick shot here
- Reference ref = new Reference(wssConfig, doc);
- ref.setURI("#" + assertion.getId());
- ref.setValueType(WSConstants.WSS_SAML_NS + WSConstants.WSS_SAML_ASSERTION);
- secRefSaml.setReference(ref);
- // up to here
- Element ctx = createSTRParameter(doc);
- transforms = new Transforms(doc);
- transforms.addTransform(STRTransform.implementedTransformURI,
- ctx);
- sig.addDocument("#" + strSamlUri, transforms);
- }
- for (int part = 0; part < parts.size(); part++) {
- WSEncryptionPart encPart = (WSEncryptionPart) parts.get(part);
- String elemName = encPart.getName();
- String nmSpace = encPart.getNamespace();
-
- /*
- * Set up the elements to sign. There are two resevered element
- * names: "Token" and "STRTransform" "Token": Setup the
- * Signature to either sign the information that points to the
- * security token or the token itself. If its a direct
- * reference sign the token, otherwise sign the KeyInfo
- * Element. "STRTransform": Setup the ds:Reference to use STR
- * Transform
- *
- */
- if (elemName.equals("Token")) {
- transforms = new Transforms(doc);
- transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
- if (keyIdentifierType
- == WSConstants.BST_DIRECT_REFERENCE) {
- sig.addDocument("#" + certUri, transforms);
- } else {
- sig.addDocument("#" + keyInfoUri, transforms);
- }
- } else if (elemName.equals("STRTransform")) { // STRTransform
- Element ctx = createSTRParameter(doc);
- transforms = new Transforms(doc);
- transforms.addTransform(STRTransform.implementedTransformURI,
- ctx);
- sig.addDocument("#" + strUri, transforms);
- } else {
- Element body =
- (Element) WSSecurityUtil.findElement(envelope,
- elemName,
- nmSpace);
- if (body == null) {
- throw new WSSecurityException(WSSecurityException.FAILURE,
- "noEncElement",
- new Object[]{nmSpace + ", " + elemName});
- }
- transforms = new Transforms(doc);
- transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
- sig.addDocument("#" + setWsuId(body), transforms);
- }
- }
- } catch (TransformationException e1) {
- throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
- "noXMLSig",
- null,
- e1);
- } catch (XMLSignatureException e1) {
- throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
- "noXMLSig",
- null,
- e1);
- }
-
- sig.addResourceResolver(EnvelopeIdResolver.getInstance(wssConfig));
-
- /*
- * The order to prepend is:
- * - signature
- * - BinarySecurityToken (depends on mode)
- * - SecurityTokenRefrence (depends on mode)
- * - SAML token
- */
-
- WSSecurityUtil.prependChildElement(doc,
- securityHeader,
- sig.getElement(),
- false);
-
- if (tlog.isDebugEnabled()) {
- t2 = System.currentTimeMillis();
- }
- switch (keyIdentifierType) {
- case WSConstants.BST_DIRECT_REFERENCE:
- Reference ref = new Reference(wssConfig, doc);
- if (senderVouches) {
- ref.setURI("#" + certUri);
- BinarySecurity bstToken = null;
- bstToken = new X509Security(wssConfig, doc);
- ((X509Security) bstToken).setX509Certificate(certs[0]);
- bstToken.setID(certUri);
- WSSecurityUtil.prependChildElement(doc,
- securityHeader,
- bstToken.getElement(),
- false);
- wsDocInfo.setBst(bstToken.getElement());
- } else {
- ref.setURI("#" + assertion.getId());
- ref.setValueType(WSConstants.WSS_SAML_NS
- + WSConstants.WSS_SAML_ASSERTION);
- }
- secRef.setReference(ref);
- break;
- //
- // case WSConstants.ISSUER_SERIAL :
- // XMLX509IssuerSerial data =
- // new XMLX509IssuerSerial(doc, certs[0]);
- // secRef.setX509IssuerSerial(data);
- // break;
- //
- // case WSConstants.X509_KEY_IDENTIFIER :
- // secRef.setKeyIdentifier(certs[0]);
- // break;
- //
- // case WSConstants.SKI_KEY_IDENTIFIER :
- // secRef.setKeyIdentifierSKI(certs[0], crypto);
- // break;
- //
+
default :
throw new WSSecurityException(WSSecurityException.FAILURE,
"unsupportedKeyId");
}
-
if (tlog.isDebugEnabled()) {
t3 = System.currentTimeMillis();
}
info.addUnknownElement(secRef.getElement());
- Element samlToken = null;
- try {
- samlToken = (Element) assertion.toDOM(doc);
- } catch (SAMLException e2) {
- throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
- "noSAMLdoc",
- null,
- e2);
- }
- if (senderVouches) {
- WSSecurityUtil.prependChildElement(doc,
- securityHeader,
- secRefSaml.getElement(),
- true);
- }
-
- wsDocInfo.setAssertion(samlToken);
- WSSecurityUtil.prependChildElement(doc,
- securityHeader,
- samlToken,
- true);
-
WSDocInfoStore.store(wsDocInfo);
try {
- if (senderVouches) {
- sig.sign(issuerCrypto.getPrivateKey(issuerKeyName, issuerKeyPW));
- } else {
- sig.sign(userCrypto.getPrivateKey(user, password));
- }
+ if (keyIdentifierType == WSConstants.UT_SIGNING) {
+ sig.sign(sig.createSecretKey(secretKey));
+ } else {
+ sig.sign(crypto.getPrivateKey(user, password));
+ }
} catch (XMLSignatureException e1) {
throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
null,
@@ -807,30 +459,377 @@
log.debug("Signing complete.");
}
return (doc);
-
- }
-
- private Element createSTRParameter(Document doc) {
- Element transformParam =
- doc.createElementNS(wssConfig.getWsseNS(),
- WSConstants.WSSE_PREFIX + ":TransformationParameters");
-
- WSSecurityUtil.setNamespace(transformParam,
- wssConfig.getWsseNS(),
- WSConstants.WSSE_PREFIX);
-
- Element canonElem =
- doc.createElementNS(WSConstants.SIG_NS,
- WSConstants.SIG_PREFIX + ":CanonicalizationMethod");
-
- WSSecurityUtil.setNamespace(canonElem,
- WSConstants.SIG_NS,
- WSConstants.SIG_PREFIX);
-
- canonElem.setAttributeNS(null,
- "Algorithm",
- Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
- transformParam.appendChild(canonElem);
- return transformParam;
}
-}
+ /**
+ * Builds a signed soap envelope with SAML token. <p/>The method first
+ * gets an appropriate security header. According to the defined parameters
+ * for certificate handling the signature elements are constructed and
+ * inserted into the <code>wsse:Signature</code>
+ *
+ * @param doc The unsigned SOAP envelope as <code>Document</code>
+ * @param assertion the complete SAML assertion
+ * @param issuerCrypto An instance of the Crypto API to handle keystore SAML token
+ * issuer and to generate certificates
+ * @param issuerKeyName Private key to use in case of "sender-Vouches"
+ * @param issuerKeyPW Password for issuer private key
+ * @return A signed SOAP envelope as <code>Document</code>
+ * @throws Exception
+ */
+ public Document build(Document doc, Crypto userCrypto,
+ SAMLAssertion assertion, Crypto issuerCrypto, String issuerKeyName,
+ String issuerKeyPW) throws WSSecurityException {
+
+ doDebug = log.isDebugEnabled();
+
+ long t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0;
+ if (tlog.isDebugEnabled()) {
+ t0 = System.currentTimeMillis();
+ }
+ if (doDebug) {
+ log.debug("Beginning ST signing...");
+ }
+ /*
+ * Get some information about the SAML token content. This controls how
+ * to deal with the whole stuff. First get the Authentication statement
+ * (includes Subject), then get the _first_ confirmation method only.
+ */
+ SAMLSubjectStatement samlSubjS = null;
+ Iterator it = assertion.getStatements();
+ while (it.hasNext()) {
+ SAMLObject so = (SAMLObject) it.next();
+ if (so instanceof SAMLSubjectStatement) {
+ samlSubjS = (SAMLSubjectStatement) so;
+ break;
+ }
+ }
+ SAMLSubject samlSubj = null;
+ if (samlSubjS != null) {
+ samlSubj = samlSubjS.getSubject();
+ }
+ if (samlSubj == null) {
+ throw new WSSecurityException(WSSecurityException.FAILURE,
+ "invalidSAMLToken", new Object[] { "for Signature" });
+ }
+
+ String confirmMethod = null;
+ it = samlSubj.getConfirmationMethods();
+ if (it.hasNext()) {
+ confirmMethod = (String) it.next();
+ }
+ boolean senderVouches = false;
+ if (SAMLSubject.CONF_SENDER_VOUCHES.equals(confirmMethod)) {
+ senderVouches = true;
+ }
+ /*
+ * Gather some info about the document to process and store it for
+ * retrival
+ */
+ WSDocInfo wsDocInfo = new WSDocInfo(doc.hashCode());
+
+ Element envelope = doc.getDocumentElement();
+ SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(envelope);
+
+ Element securityHeader = insertSecurityHeader(doc);
+ X509Certificate[] certs = null;
+
+ if (senderVouches) {
+ certs = issuerCrypto.getCertificates(issuerKeyName);
+ wsDocInfo.setCrypto(issuerCrypto);
+ }
+ /*
+ * in case of key holder:
+ * - get the user's certificate that _must_ be included in the SAML
+ * token. To ensure the cert integrity the SAML token must be signed
+ * (by the issuer). Just check if its signed, but
+ * don't verify this SAML token's signature here (maybe later).
+ */
+ else {
+ if (userCrypto == null || assertion.isSigned() == false) {
+ throw new WSSecurityException(WSSecurityException.FAILURE,
+ "invalidSAMLsecurity",
+ new Object[] { "for SAML Signature (Key Holder)" });
+ }
+ Element e = samlSubj.getKeyInfo();
+ try {
+ KeyInfo ki = new KeyInfo(e, null);
+
+ if (ki.containsX509Data()) {
+ X509Data data = ki.itemX509Data(0);
+ XMLX509Certificate certElem = null;
+ if (data != null && data.containsCertificate()) {
+ certElem = data.itemCertificate(0);
+ }
+ if (certElem != null) {
+ X509Certificate cert = certElem.getX509Certificate();
+ certs = new X509Certificate[1];
+ certs[0] = cert;
+ }
+ }
+ // TODO: get alias name for cert, check against username set by caller
+ } catch (XMLSecurityException e3) {
+ throw new WSSecurityException(WSSecurityException.FAILURE,
+ "invalidSAMLsecurity",
+ new Object[] { "cannot get certificate (key holder)" },
+ e3);
+ }
+ wsDocInfo.setCrypto(userCrypto);
+ }
+ // Set the id of the elements to be used as digest source
+ // String id = setBodyID(doc);
+ if (certs == null || certs.length <= 0) {
+ throw new WSSecurityException(WSSecurityException.FAILURE,
+ "invalidX509Data", new Object[] { "for Signature" });
+ }
+ if (sigAlgo == null) {
+ String pubKeyAlgo = certs[0].getPublicKey().getAlgorithm();
+ log.debug("automatic sig algo detection: " + pubKeyAlgo);
+ if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
+ sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA;
+ } else if (pubKeyAlgo.equalsIgnoreCase("RSA")) {
+ sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_RSA;
+ } else {
+ throw new WSSecurityException(
+ WSSecurityException.FAILURE,
+ "invalidX509Data",
+ new Object[] { "for Signature - unkown public key Algo" });
+ }
+ }
+ XMLSignature sig = null;
+ try {
+ sig = new XMLSignature(doc, null, sigAlgo, canonAlgo);
+ } catch (XMLSecurityException e) {
+ throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+ "noXMLSig");
+ }
+
+ KeyInfo info = sig.getKeyInfo();
+ String keyInfoUri = "KeyId-" + info.hashCode();
+ info.setId(keyInfoUri);
+
+ SecurityTokenReference secRef = new SecurityTokenReference(wssConfig,
+ doc);
+ String strUri = "STRId-" + secRef.hashCode();
+ secRef.setID(strUri);
+
+ String certUri = "CertId-" + certs[0].hashCode();
+
+ if (tlog.isDebugEnabled()) {
+ t1 = System.currentTimeMillis();
+ }
+
+ if (parts == null) {
+ parts = new Vector();
+ WSEncryptionPart encP = new WSEncryptionPart(soapConstants
+ .getBodyQName().getLocalPart(), soapConstants
+ .getEnvelopeURI(), "Content");
+ parts.add(encP);
+ }
+
+ /*
+ * If the sender vouches, then we must sign the SAML token _and_ at
+ * least one part of the message (usually the SOAP body). To do so we
+ * need to
+ * - put in a reference to the SAML token. Thus we create a STR
+ * and insert it into the wsse:Security header
+ * - set a reference of the created STR to the signature and use STR
+ * Transfrom during the signature
+ */
+ Transforms transforms = null;
+ SecurityTokenReference secRefSaml = null;
+
+ try {
+ if (senderVouches) {
+ secRefSaml = new SecurityTokenReference(wssConfig, doc);
+ String strSamlUri = "STRSAMLId-" + secRefSaml.hashCode();
+ secRefSaml.setID(strSamlUri);
+ // Decouple Refernce/KeyInfo setup - quick shot here
+ Reference ref = new Reference(wssConfig, doc);
+ ref.setURI("#" + assertion.getId());
+ ref.setValueType(WSConstants.WSS_SAML_NS
+ + WSConstants.WSS_SAML_ASSERTION);
+ secRefSaml.setReference(ref);
+ // up to here
+ Element ctx = createSTRParameter(doc);
+ transforms = new Transforms(doc);
+ transforms.addTransform(STRTransform.implementedTransformURI,
+ ctx);
+ sig.addDocument("#" + strSamlUri, transforms);
+ }
+ for (int part = 0; part < parts.size(); part++) {
+ WSEncryptionPart encPart = (WSEncryptionPart) parts.get(part);
+ String elemName = encPart.getName();
+ String nmSpace = encPart.getNamespace();
+
+ /*
+ * Set up the elements to sign. There are two resevered element
+ * names: "Token" and "STRTransform" "Token": Setup the
+ * Signature to either sign the information that points to the
+ * security token or the token itself. If its a direct
+ * reference sign the token, otherwise sign the KeyInfo
+ * Element. "STRTransform": Setup the ds:Reference to use STR
+ * Transform
+ *
+ */
+ if (elemName.equals("Token")) {
+ transforms = new Transforms(doc);
+ transforms
+ .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+ if (keyIdentifierType == WSConstants.BST_DIRECT_REFERENCE) {
+ sig.addDocument("#" + certUri, transforms);
+ } else {
+ sig.addDocument("#" + keyInfoUri, transforms);
+ }
+ } else if (elemName.equals("STRTransform")) { // STRTransform
+ Element ctx = createSTRParameter(doc);
+ transforms = new Transforms(doc);
+ transforms.addTransform(
+ STRTransform.implementedTransformURI, ctx);
+ sig.addDocument("#" + strUri, transforms);
+ } else {
+ Element body = (Element) WSSecurityUtil.findElement(
+ envelope, elemName, nmSpace);
+ if (body == null) {
+ throw new WSSecurityException(
+ WSSecurityException.FAILURE, "noEncElement",
+ new Object[] { nmSpace + ", " + elemName });
+ }
+ transforms = new Transforms(doc);
+ transforms
+ .addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+ sig.addDocument("#" + setWsuId(body), transforms);
+ }
+ }
+ } catch (TransformationException e1) {
+ throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+ "noXMLSig", null, e1);
+ } catch (XMLSignatureException e1) {
+ throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+ "noXMLSig", null, e1);
+ }
+
+ sig.addResourceResolver(EnvelopeIdResolver.getInstance(wssConfig));
+
+ /*
+ * The order to prepend is:
+ * - signature
+ * - BinarySecurityToken (depends on mode)
+ * - SecurityTokenRefrence (depends on mode)
+ * - SAML token
+ */
+
+ WSSecurityUtil.prependChildElement(doc, securityHeader, sig
+ .getElement(), false);
+
+ if (tlog.isDebugEnabled()) {
+ t2 = System.currentTimeMillis();
+ }
+ switch (keyIdentifierType) {
+ case WSConstants.BST_DIRECT_REFERENCE:
+ Reference ref = new Reference(wssConfig, doc);
+ if (senderVouches) {
+ ref.setURI("#" + certUri);
+ BinarySecurity bstToken = null;
+ bstToken = new X509Security(wssConfig, doc);
+ ((X509Security) bstToken).setX509Certificate(certs[0]);
+ bstToken.setID(certUri);
+ WSSecurityUtil.prependChildElement(doc, securityHeader,
+ bstToken.getElement(), false);
+ wsDocInfo.setBst(bstToken.getElement());
+ } else {
+ ref.setURI("#" + assertion.getId());
+ ref.setValueType(WSConstants.WSS_SAML_NS
+ + WSConstants.WSS_SAML_ASSERTION);
+ }
+ secRef.setReference(ref);
+ break;
+ //
+ // case WSConstants.ISSUER_SERIAL :
+ // XMLX509IssuerSerial data =
+ // new XMLX509IssuerSerial(doc, certs[0]);
+ // secRef.setX509IssuerSerial(data);
+ // break;
+ //
+ // case WSConstants.X509_KEY_IDENTIFIER :
+ // secRef.setKeyIdentifier(certs[0]);
+ // break;
+ //
+ // case WSConstants.SKI_KEY_IDENTIFIER :
+ // secRef.setKeyIdentifierSKI(certs[0], crypto);
+ // break;
+ //
+ default:
+ throw new WSSecurityException(WSSecurityException.FAILURE,
+ "unsupportedKeyId");
+ }
+
+ if (tlog.isDebugEnabled()) {
+ t3 = System.currentTimeMillis();
+ }
+ info.addUnknownElement(secRef.getElement());
+
+ Element samlToken = null;
+ try {
+ samlToken = (Element) assertion.toDOM(doc);
+ } catch (SAMLException e2) {
+ throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+ "noSAMLdoc", null, e2);
+ }
+ if (senderVouches) {
+ WSSecurityUtil.prependChildElement(doc, securityHeader, secRefSaml
+ .getElement(), true);
+ }
+
+ wsDocInfo.setAssertion(samlToken);
+ WSSecurityUtil
+ .prependChildElement(doc, securityHeader, samlToken, true);
+
+ WSDocInfoStore.store(wsDocInfo);
+ try {
+ if (senderVouches) {
+ sig
+ .sign(issuerCrypto.getPrivateKey(issuerKeyName,
+ issuerKeyPW));
+ } else {
+ sig.sign(userCrypto.getPrivateKey(user, password));
+ }
+ } catch (XMLSignatureException e1) {
+ throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+ null, null, e1);
+ } catch (Exception e1) {
+ throw new WSSecurityException(WSSecurityException.FAILED_SIGNATURE,
+ null, null, e1);
+ } finally {
+ WSDocInfoStore.delete(wsDocInfo);
+ }
+ if (tlog.isDebugEnabled()) {
+ t4 = System.currentTimeMillis();
+ tlog.debug("SignEnvelope: cre-Sig= " + (t1 - t0)
+ + " set transform= " + (t2 - t1) + " sec-ref= " + (t3 - t2)
+ + " signature= " + (t4 - t3));
+ }
+ if (doDebug) {
+ log.debug("Signing complete.");
+ }
+ return (doc);
+
+ }
+
+ private Element createSTRParameter(Document doc) {
+ Element transformParam = doc.createElementNS(wssConfig.getWsseNS(),
+ WSConstants.WSSE_PREFIX + ":TransformationParameters");
+
+ WSSecurityUtil.setNamespace(transformParam, wssConfig.getWsseNS(),
+ WSConstants.WSSE_PREFIX);
+
+ Element canonElem = doc.createElementNS(WSConstants.SIG_NS,
+ WSConstants.SIG_PREFIX + ":CanonicalizationMethod");
+
+ WSSecurityUtil.setNamespace(canonElem, WSConstants.SIG_NS,
+ WSConstants.SIG_PREFIX);
+
+ canonElem.setAttributeNS(null, "Algorithm",
+ Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);
+ transformParam.appendChild(canonElem);
+ return transformParam;
+ }
+}
\ No newline at end of file
1.24 +1 -1 ws-fx/wss4j/src/org/apache/ws/security/message/WSEncryptBody.java
Index: WSEncryptBody.java
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/message/WSEncryptBody.java,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -r1.23 -r1.24
--- WSEncryptBody.java 10 Aug 2004 02:58:29 -0000 1.23
+++ WSEncryptBody.java 24 Oct 2004 12:41:13 -0000 1.24
@@ -336,7 +336,7 @@
if (body == null) {
throw new WSSecurityException(WSSecurityException.FAILURE,
"noEncElement",
- new Object[]{nmSpace, elemName});
+ new Object[]{"{" + nmSpace + "}" + elemName});
}
boolean content = modifier.equals("Content") ? true : false;
1.9 +4 -4 ws-fx/wss4j/src/org/apache/ws/security/message/token/UsernameToken.java
Index: UsernameToken.java
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/message/token/UsernameToken.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- UsernameToken.java 2 Sep 2004 02:27:03 -0000 1.8
+++ UsernameToken.java 24 Oct 2004 12:41:13 -0000 1.9
@@ -60,7 +60,6 @@
protected Element elementCreated = null;
protected boolean hashed = true;
private static SecureRandom random = null;
- String password = null;
protected WSSConfig wssConfig = WSSConfig.getDefaultWSConfig();
public static String TOKEN = "UsernameToken";
@@ -302,7 +301,6 @@
* @param pwd the password to use
*/
public void setPassword(String pwd) {
- this.password = pwd;
if (pwd == null) {
throw new IllegalArgumentException("pwd == null");
}
@@ -433,7 +431,7 @@
byte[] key = null;
try {
Mac mac = Mac.getInstance("HMACSHA1");
- byte[] password = this.password.getBytes("UTF-8");
+ byte[] password = getPassword().getBytes("UTF-8");
byte[] label = "WS-Security".getBytes("UTF-8");
byte[] nonce = Base64.decode(getNonce());
byte[] created = getCreated().getBytes("UTF-8");
@@ -450,14 +448,16 @@
seed[count++] = created[i];
}
key = P_hash(password, seed, mac, 128);
+ /*
System.out.println("password :" + Base64.encode(password));
System.out.println("label :" + Base64.encode(label));
System.out.println("nonce :" + Base64.encode(nonce));
System.out.println("created :" + Base64.encode(created));
System.out.println("seed :" + Base64.encode(seed));
System.out.println("Key :" + Base64.encode(key));
+ */
} catch (Exception e) {
- e.printStackTrace();
+ return null;
}
return key;
}
1.22 +1 -0 ws-fx/wss4j/src/org/apache/ws/security/util/WSSecurityUtil.java
Index: WSSecurityUtil.java
===================================================================
RCS file: /home/cvs/ws-fx/wss4j/src/org/apache/ws/security/util/WSSecurityUtil.java,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- WSSecurityUtil.java 30 Aug 2004 09:39:24 -0000 1.21
+++ WSSecurityUtil.java 24 Oct 2004 12:41:13 -0000 1.22
@@ -1,3 +1,4 @@
+
/*
* Copyright 2003-2004 The Apache Software Foundation.
*