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 2005/12/22 12:14:36 UTC

svn commit: r358557 - in /webservices/wss4j/trunk/src/org/apache/ws/security: message/WSEncryptBody.java message/token/KeyInfo.java message/token/SecurityTokenReference.java processor/EncryptedKeyProcessor.java

Author: werner
Date: Thu Dec 22 03:14:27 2005
New Revision: 358557

URL: http://svn.apache.org/viewcvs?rev=358557&view=rev
Log:
Prepare for some more WSS 1.1 functions and upcoming SecurityPolicy 

Added:
    webservices/wss4j/trunk/src/org/apache/ws/security/message/token/KeyInfo.java
Modified:
    webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java
    webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java
    webservices/wss4j/trunk/src/org/apache/ws/security/processor/EncryptedKeyProcessor.java

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java?rev=358557&r1=358556&r2=358557&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/WSEncryptBody.java Thu Dec 22 03:14:27 2005
@@ -541,10 +541,6 @@
             log.debug("Beginning Encryption embedded...");
         }
 
-        if (embeddedKey == null) {
-            throw new WSSecurityException(WSSecurityException.FAILURE,
-                    "noKeySupplied");
-        }
 
         /*
          * Second step: generate a symmetric key from the specified
@@ -553,6 +549,10 @@
          */
         this.encryptionKey = this.symmetricKey;
         if (this.encryptionKey == null) {
+            if (embeddedKey == null) {
+                throw new WSSecurityException(WSSecurityException.FAILURE,
+                        "noKeySupplied");
+            }
             this.encryptionKey = WSSecurityUtil.prepareSecretKey(
                     symEncAlgo,
                     embeddedKey);

Added: webservices/wss4j/trunk/src/org/apache/ws/security/message/token/KeyInfo.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/message/token/KeyInfo.java?rev=358557&view=auto
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/token/KeyInfo.java (added)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/token/KeyInfo.java Thu Dec 22 03:14:27 2005
@@ -0,0 +1,236 @@
+package org.apache.ws.security.message.token;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.security.PrivateKey;
+import javax.crypto.SecretKey;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.xml.namespace.QName;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.ws.security.WSConstants;
+import org.apache.ws.security.WSPasswordCallback;
+import org.apache.ws.security.WSSecurityEngine;
+import org.apache.ws.security.WSSecurityException;
+import org.apache.ws.security.components.crypto.Crypto;
+import org.apache.ws.security.util.WSSecurityUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class KeyInfo {
+	private static Log log = LogFactory.getLog(KeyInfo.class.getName());
+
+	public static final QName TOKEN = new QName(WSConstants.SIG_NS, "KeyInfo");
+
+	protected Element element = null;
+
+	protected CallbackHandler callBack = null;
+
+	protected Crypto crypto = null;
+
+	private PrivateKey privateKey = null;
+
+	private SecretKey secretKey = null;
+
+	private SecurityTokenReference secRef = null;
+
+	private boolean containsSecRef = true;
+	
+	private boolean containsKeyName = false;
+
+	/**
+	 * Constructor. Sets up the KeyInfo data structure from a DOM element.
+	 * 
+	 * @param elem
+	 *            The KeyInfo DOM element
+	 * @param cb
+	 *            The callback handler to get the password to unlock a private
+	 *            key. Maybe <code>null</code> if no password is required for
+	 *            this instance of keyinfo
+	 * @param c
+	 *            An object implementing the Crypto interface to handle
+	 *            certificates. Maybe <code>null</code> if no certificate is
+	 *            required for this instance of keyinfo
+	 * @throws WSSecurityException
+	 */
+
+	public KeyInfo(Element elem, CallbackHandler cb, Crypto c)
+			throws WSSecurityException {
+		if (elem == null) {
+			throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
+					"noKeyInfo");
+		}
+		this.element = elem;
+		QName el = new QName(this.element.getNamespaceURI(), this.element
+				.getLocalName());
+		if (!el.equals(TOKEN)) {
+			throw new WSSecurityException(WSSecurityException.FAILURE,
+					"badElement", new Object[] { TOKEN, el });
+		}
+		crypto = c;
+		callBack = cb;
+		parseKeyInfo(elem);
+	}
+
+	private void parseKeyInfo(Element keyInfo) throws WSSecurityException {
+		Element child;
+
+		child = (Element) WSSecurityUtil.getDirectChild(keyInfo,
+				"SecurityTokenReference", WSConstants.WSSE_NS);
+
+		if (child == null) {
+			containsSecRef = false;
+			child = (Element) WSSecurityUtil.getDirectChild(keyInfo, "KeyName",
+					WSConstants.SIG_NS);
+			containsKeyName = true;
+		}
+		if (child == null) {
+			containsKeyName = false;
+			throw new WSSecurityException(WSSecurityException.INVALID_SECURITY,
+					"noSecTokRef");
+		}
+		/*
+		 * The securityTokenReference handles both the normal STR and the simple
+		 * KeyName value
+		 */
+		secRef = new SecurityTokenReference(child);
+	}
+
+	public PrivateKey getPrivateKey() throws WSSecurityException {
+		String alias;
+		Document doc = element.getOwnerDocument();
+
+		/*
+		 * Well, at this point there are several ways to get the key. Try to
+		 * handle all of them :-).
+		 */
+		alias = null;
+		/*
+		 * handle X509IssuerSerial here. First check if all elements are
+		 * available, get the appropriate data, check if all data is available.
+		 * If all is ok up to that point, look up the certificate alias
+		 * according to issuer name and serial number. This method is
+		 * recommended by OASIS WS-S specification, X509 profile
+		 */
+		if (secRef.containsX509Data() || secRef.containsX509IssuerSerial()) {
+			alias = secRef.getX509IssuerSerialAlias(crypto);
+			if (log.isDebugEnabled()) {
+				log.debug("X509IssuerSerial alias: " + alias);
+			}
+		}
+		/*
+		 * If wsse:KeyIdentifier found, then the public key of the attached cert
+		 * was used to encrypt the session (symmetric) key that encrypts the
+		 * data. Extract the certificate using the BinarySecurity token (was
+		 * enhanced to handle KeyIdentifier too). This method is _not_
+		 * recommended by OASIS WS-S specification, X509 profile
+		 */
+		else if (secRef.containsKeyIdentifier()) {
+			X509Certificate[] certs = secRef.getKeyIdentifier(crypto);
+			if (certs == null || certs.length < 1 || certs[0] == null) {
+				throw new WSSecurityException(WSSecurityException.FAILURE,
+						"invalidX509Data",
+						new Object[] { "for decryption (KeyId)" });
+			}
+			/*
+			 * Here we have the certificate. Now find the alias for it. Needed
+			 * to identify the private key associated with this certificate
+			 */
+			alias = crypto.getAliasForX509Cert(certs[0]);
+			if (log.isDebugEnabled()) {
+				log.debug("cert: " + certs[0]);
+				log.debug("KeyIdentifier Alias: " + alias);
+			}
+		} else if (secRef.containsReference()) {
+			Element bstElement = secRef.getTokenElement(doc, null);
+
+			// at this point ... check token type: Binary
+			QName el = new QName(bstElement.getNamespaceURI(), bstElement
+					.getLocalName());
+			if (el.equals(WSSecurityEngine.binaryToken)) {
+				X509Security token = null;
+				String value = bstElement
+						.getAttribute(WSSecurityEngine.VALUE_TYPE);
+				if (!X509Security.getType().equals(value)
+						|| ((token = new X509Security(bstElement)) == null)) {
+					throw new WSSecurityException(
+							WSSecurityException.UNSUPPORTED_SECURITY_TOKEN,
+							"unsupportedBinaryTokenType",
+							new Object[] { "for decryption (BST)" });
+				}
+				X509Certificate cert = token.getX509Certificate(crypto);
+				if (cert == null) {
+					throw new WSSecurityException(WSSecurityException.FAILURE,
+							"invalidX509Data",
+							new Object[] { "for decryption" });
+				}
+				/*
+				 * Here we have the certificate. Now find the alias for it.
+				 * Needed to identify the private key associated with this
+				 * certificate
+				 */
+				alias = crypto.getAliasForX509Cert(cert);
+				if (log.isDebugEnabled()) {
+					log.debug("BST Alias: " + alias);
+				}
+			} else {
+				throw new WSSecurityException(
+						WSSecurityException.INVALID_SECURITY,
+						"unsupportedToken", null);
+			}
+			/*
+			 * The following code is somewhat strange: the called crypto method gets
+			 * the keyname and searches for a certificate with an issuer's name that is
+			 * equal to this keyname. No serialnumber is used - IMHO this does
+			 * not identifies a certificate. In addition neither the WSS4J encryption
+			 * nor signature methods use this way to identify a certificate. Because of that
+			 * the next lines of code are disabled.  
+			 */
+//		} else if (secRef.containsKeyName()) {
+//			alias = crypto.getAliasForX509Cert(secRef.getKeyNameValue());
+//			if (log.isDebugEnabled()) {
+//				log.debug("KeyName alias: " + alias);
+//			}
+		} else {
+			throw new WSSecurityException(WSSecurityException.FAILURE,
+					"unsupportedKeyId");
+		}
+		return getPrivateKeyForName(alias, callBack, crypto);
+	}
+
+	static public PrivateKey getPrivateKeyForName(String name,
+			CallbackHandler cb, Crypto crypto) throws WSSecurityException {
+
+		WSPasswordCallback pwCb = new WSPasswordCallback(name,
+				WSPasswordCallback.DECRYPT);
+		Callback[] callbacks = new Callback[1];
+		callbacks[0] = pwCb;
+		try {
+			cb.handle(callbacks);
+		} catch (IOException e) {
+			throw new WSSecurityException(WSSecurityException.FAILURE,
+					"noPassword", new Object[] { name });
+		} catch (UnsupportedCallbackException e) {
+			throw new WSSecurityException(WSSecurityException.FAILURE,
+					"noPassword", new Object[] { name });
+		}
+		String password = pwCb.getPassword();
+		if (password == null) {
+			throw new WSSecurityException(WSSecurityException.FAILURE,
+					"noPassword", new Object[] { name });
+		}
+
+		try {
+			return crypto.getPrivateKey(name, password);
+		} catch (Exception e) {
+			throw new WSSecurityException(WSSecurityException.FAILED_ENC_DEC,
+					null, null, e);
+		}
+
+	}
+
+}

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java?rev=358557&r1=358556&r2=358557&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/message/token/SecurityTokenReference.java Thu Dec 22 03:14:27 2005
@@ -71,8 +71,8 @@
         boolean goodElement = false;
         if (SECURITY_TOKEN_REFERENCE.equals(element.getLocalName())) {
             goodElement = WSConstants.WSSE_NS.equals(element.getNamespaceURI());
-        } else if (KEY_NAME.equals(element.getLocalName())) {
-            goodElement = WSConstants.SIG_NS.equals(element.getNamespaceURI());
+//        } else if (KEY_NAME.equals(element.getLocalName())) {
+//            goodElement = WSConstants.SIG_NS.equals(element.getNamespaceURI());
         }
         if (!goodElement) {
             throw new WSSecurityException(WSSecurityException.FAILURE,
@@ -463,13 +463,13 @@
      * @return true if the <code>SecurtityTokenReference</code> contains
      *         a <code>wsse:KeyName</code> element
      */
-    public boolean containsKeyName() {
-        return element.getLocalName().equals(KEY_NAME);
-    }
-
-    public String getKeyNameValue() {
-        return element.getFirstChild().getNodeValue();
-    }
+//    public boolean containsKeyName() {
+//        return element.getLocalName().equals(KEY_NAME);
+//    }
+//
+//    public String getKeyNameValue() {
+//        return element.getFirstChild().getNodeValue();
+//    }
 
     /**
      * Method containsReference

Modified: webservices/wss4j/trunk/src/org/apache/ws/security/processor/EncryptedKeyProcessor.java
URL: http://svn.apache.org/viewcvs/webservices/wss4j/trunk/src/org/apache/ws/security/processor/EncryptedKeyProcessor.java?rev=358557&r1=358556&r2=358557&view=diff
==============================================================================
--- webservices/wss4j/trunk/src/org/apache/ws/security/processor/EncryptedKeyProcessor.java (original)
+++ webservices/wss4j/trunk/src/org/apache/ws/security/processor/EncryptedKeyProcessor.java Thu Dec 22 03:14:27 2005
@@ -218,11 +218,19 @@
                                 "unsupportedToken",
                                 null);
                     }
-                } else if (secRef.containsKeyName()) {
-                    alias = crypto.getAliasForX509Cert(secRef.getKeyNameValue());
-                    if (log.isDebugEnabled()) {
-                        log.debug("KeyName alias: " + alias);
-                    }
+        			/*
+        			 * The following code is somewhat strange: the called crypto method gets
+        			 * the keyname and searches for a certificate with an issuer's name that is
+        			 * equal to this keyname. No serialnumber is used - IMHO this does
+        			 * not identifies a certificate. In addition neither the WSS4J encryption
+        			 * nor signature methods use this way to identify a certificate. Because of that
+        			 * the next lines of code are disabled.  
+        			 */
+//                } else if (secRef.containsKeyName()) {
+//                    alias = crypto.getAliasForX509Cert(secRef.getKeyNameValue());
+//                    if (log.isDebugEnabled()) {
+//                        log.debug("KeyName alias: " + alias);
+//                    }
                 } else {
                     throw new WSSecurityException(WSSecurityException.FAILURE, "unsupportedKeyId");
                 }



---------------------------------------------------------------------
To unsubscribe, e-mail: wss4j-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: wss4j-dev-help@ws.apache.org