Implemented securing Authentication and Session Tokens using
WS-Security.
This commit is contained in:
		@@ -256,6 +256,11 @@ public class AuthReqMsg
 | 
			
		||||
               m_state = AWAITING_REALM_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_REALM_ELEMENT_END:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_authReqMsg.m_realm = m_authReqMsg.m_realm.concat(new String(ch, start, length));
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_MECH_DATA:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_authReqMsg.m_authMechanism = new String(ch, start, length);
 | 
			
		||||
@@ -264,6 +269,11 @@ public class AuthReqMsg
 | 
			
		||||
               m_state = AWAITING_MECH_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_MECH_ELEMENT_END:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_authReqMsg.m_authMechanism = m_authReqMsg.m_authMechanism.concat(new String(ch, start, length));
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_AUTH_MECH_TOKEN_DATA:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_authReqMsg.m_authMechToken = new String(ch, start, length);
 | 
			
		||||
@@ -272,6 +282,11 @@ public class AuthReqMsg
 | 
			
		||||
               m_state = AWAITING_AUTH_MECH_TOKEN_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_AUTH_MECH_TOKEN_ELEMENT_END:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_authReqMsg.m_authMechToken = m_authReqMsg.m_authMechToken.concat(new String(ch, start, length));
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
               // Do nothing
 | 
			
		||||
               break;
 | 
			
		||||
 
 | 
			
		||||
@@ -26,20 +26,26 @@ package com.novell.casa.authtoksvc;
 | 
			
		||||
 | 
			
		||||
import java.io.ByteArrayInputStream;
 | 
			
		||||
 | 
			
		||||
import org.xml.sax.InputSource;
 | 
			
		||||
import org.xml.sax.SAXException;
 | 
			
		||||
import org.xml.sax.XMLReader;
 | 
			
		||||
import org.xml.sax.helpers.XMLReaderFactory;
 | 
			
		||||
import org.apache.axis.Message;
 | 
			
		||||
import org.apache.axis.MessageContext;
 | 
			
		||||
import org.apache.axis.client.AxisClient;
 | 
			
		||||
import org.apache.axis.configuration.NullProvider;
 | 
			
		||||
import org.apache.axis.message.SOAPEnvelope;
 | 
			
		||||
import org.apache.axis.message.SOAPBody;
 | 
			
		||||
import org.apache.axis.message.MessageElement;
 | 
			
		||||
 | 
			
		||||
import javax.xml.namespace.QName;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * AuthToken Class.
 | 
			
		||||
 * 
 | 
			
		||||
 * This class constructs authentication tokens that clients can present
 | 
			
		||||
 * to services for authentication. The format of the authentication token
 | 
			
		||||
 * is as follows:
 | 
			
		||||
 * 
 | 
			
		||||
 * <?xml version="1.0" encoding="ISO-8859-1"?>
 | 
			
		||||
 * to services for authentication. The authentication token consists of
 | 
			
		||||
 * a SOAP message secured with WSSecurity with the appropriate elements signed
 | 
			
		||||
 * and with a timestamp. The body of the SOAP message is as follows:
 | 
			
		||||
 *
 | 
			
		||||
 * <auth_token>
 | 
			
		||||
 * <signature>signature value</signature>
 | 
			
		||||
 * <lifetime>lifetime value</lifetime>
 | 
			
		||||
@@ -51,280 +57,23 @@ public class AuthToken
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
   private String       m_token;
 | 
			
		||||
   private String       m_lifetime;
 | 
			
		||||
   private String       m_lifetimeShorter;
 | 
			
		||||
   private String       m_identityTokenType;
 | 
			
		||||
   private StringBuffer m_identityToken;
 | 
			
		||||
   private String       m_signature;
 | 
			
		||||
   private String       m_lifetime = "";
 | 
			
		||||
   private String       m_lifetimeShorter = "";
 | 
			
		||||
   private String       m_identityTokenType = null;
 | 
			
		||||
   private String       m_identityToken = null;
 | 
			
		||||
 | 
			
		||||
   /*
 | 
			
		||||
    * Class for handling parsing events.
 | 
			
		||||
    */
 | 
			
		||||
   private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
 | 
			
		||||
   {
 | 
			
		||||
      private final static int AWAITING_ROOT_ELEMENT_START = 0;
 | 
			
		||||
      private final static int AWAITING_ROOT_ELEMENT_END = 1;
 | 
			
		||||
      private final static int AWAITING_SIGNATURE_ELEMENT_START = 2;
 | 
			
		||||
      private final static int AWAITING_SIGNATURE_ELEMENT_END = 3;
 | 
			
		||||
      private final static int AWAITING_SIGNATURE_DATA = 4;
 | 
			
		||||
      private final static int AWAITING_LIFETIME_ELEMENT_START = 5;
 | 
			
		||||
      private final static int AWAITING_LIFETIME_ELEMENT_END = 6;
 | 
			
		||||
      private final static int AWAITING_LIFETIME_DATA = 7;
 | 
			
		||||
      private final static int AWAITING_IDENT_TOKEN_ELEMENT_START = 8;
 | 
			
		||||
      private final static int AWAITING_IDENT_TOKEN_ELEMENT_END = 9;
 | 
			
		||||
      private final static int AWAITING_IDENT_TOKEN_DATA = 10;
 | 
			
		||||
      private final static int AWAITING_TYPE_ELEMENT_START = 11;
 | 
			
		||||
      private final static int AWAITING_TYPE_ELEMENT_END = 12;
 | 
			
		||||
      private final static int AWAITING_TYPE_DATA = 13;
 | 
			
		||||
      private final static int DONE_PARSING = 14;
 | 
			
		||||
   static final String authTokenSoapMsg =
 | 
			
		||||
      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
 | 
			
		||||
      "<SOAP-ENV:Envelope" +
 | 
			
		||||
      "    xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\"\n" +
 | 
			
		||||
      "    xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" +
 | 
			
		||||
      "    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
 | 
			
		||||
      "    <SOAP-ENV:Body>" +
 | 
			
		||||
      "        <auth_token><ident_token><type></type></ident_token></auth_token>" +
 | 
			
		||||
      "    </SOAP-ENV:Body>" +
 | 
			
		||||
      "</SOAP-ENV:Envelope>";
 | 
			
		||||
 | 
			
		||||
      private AuthToken m_AuthToken;
 | 
			
		||||
      private int    m_state;
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
       * Constructor
 | 
			
		||||
       */
 | 
			
		||||
      public SAXHandler (AuthToken AuthToken)
 | 
			
		||||
      {
 | 
			
		||||
         super();
 | 
			
		||||
 | 
			
		||||
         // Initialize our members
 | 
			
		||||
         m_AuthToken = AuthToken;
 | 
			
		||||
         m_state = AWAITING_ROOT_ELEMENT_START;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
       * endDocument() implementation.
 | 
			
		||||
       */
 | 
			
		||||
      public void endDocument () throws SAXException
 | 
			
		||||
      {
 | 
			
		||||
         // Verify that we obtained all of the required elements
 | 
			
		||||
         if (m_state != DONE_PARSING)
 | 
			
		||||
         {
 | 
			
		||||
            System.err.println("AuthToken SAXHandler.endDocument()- Missing element"); 
 | 
			
		||||
            throw new SAXException("Missing element");
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
       * startElement() implementation.
 | 
			
		||||
       */
 | 
			
		||||
      public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
 | 
			
		||||
      {
 | 
			
		||||
         // Proceed based on our state
 | 
			
		||||
         switch (m_state)
 | 
			
		||||
         {
 | 
			
		||||
            
 | 
			
		||||
            case AWAITING_ROOT_ELEMENT_START:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.authTokenElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_SIGNATURE_ELEMENT_START;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("AuthToken SAXHandler.startElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_SIGNATURE_ELEMENT_START:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.signatureElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_SIGNATURE_DATA;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("AuthToken SAXHandler.startElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_LIFETIME_ELEMENT_START:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.lifetimeElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_LIFETIME_DATA;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("AuthToken SAXHandler.startElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_IDENT_TOKEN_ELEMENT_START:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.identTokenElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_TYPE_ELEMENT_START;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("AuthToken SAXHandler.startElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_TYPE_ELEMENT_START:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.typeElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_TYPE_DATA;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("AuthToken SAXHandler.startElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
               System.err.println("AuthToken SAXHandler.startElement()- State error"); 
 | 
			
		||||
               throw new SAXException("State error");
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
       * endElement() immplementation.
 | 
			
		||||
       */
 | 
			
		||||
      public void endElement (String uri, String name, String qName) throws SAXException
 | 
			
		||||
      {
 | 
			
		||||
         // Proceed based on our state
 | 
			
		||||
         switch (m_state)
 | 
			
		||||
         {
 | 
			
		||||
            
 | 
			
		||||
            case AWAITING_ROOT_ELEMENT_END:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.authTokenElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = DONE_PARSING;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("AuthToken SAXHandler.endElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_SIGNATURE_ELEMENT_END:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.signatureElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_LIFETIME_ELEMENT_START;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("AuthToken SAXHandler.endElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_LIFETIME_ELEMENT_END:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.lifetimeElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_IDENT_TOKEN_ELEMENT_START;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("AuthToken SAXHandler.endElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_TYPE_ELEMENT_END:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.typeElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_IDENT_TOKEN_DATA;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("AuthToken SAXHandler.endElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_IDENT_TOKEN_ELEMENT_END:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.identTokenElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_ROOT_ELEMENT_END;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("AuthToken SAXHandler.endElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
               System.err.println("AuthToken SAXHandler.startElement()- State error"); 
 | 
			
		||||
               throw new SAXException("State error");
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
       * character() implementation.
 | 
			
		||||
       */
 | 
			
		||||
      public void characters (char ch[], int start, int length) throws SAXException
 | 
			
		||||
      {
 | 
			
		||||
         // Proceed based on our state
 | 
			
		||||
         switch (m_state)
 | 
			
		||||
         {
 | 
			
		||||
            
 | 
			
		||||
            case AWAITING_SIGNATURE_DATA:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_AuthToken.m_signature = new String(ch, start, length);
 | 
			
		||||
 | 
			
		||||
               // Advance to the next state
 | 
			
		||||
               m_state = AWAITING_SIGNATURE_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_LIFETIME_DATA:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_AuthToken.m_lifetime = new String(ch, start, length);
 | 
			
		||||
 | 
			
		||||
               // Advance to the next state
 | 
			
		||||
               m_state = AWAITING_LIFETIME_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_TYPE_DATA:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_AuthToken.m_identityTokenType = new String(ch, start, length);
 | 
			
		||||
 | 
			
		||||
               // Advance to the next state
 | 
			
		||||
               m_state = AWAITING_TYPE_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_IDENT_TOKEN_DATA:
 | 
			
		||||
            case AWAITING_IDENT_TOKEN_ELEMENT_END:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_AuthToken.m_identityToken.append(ch, start, length);
 | 
			
		||||
 | 
			
		||||
               // Advance to the next state
 | 
			
		||||
               m_state = AWAITING_IDENT_TOKEN_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
               // Do nothing
 | 
			
		||||
               break;
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
   static final private MessageContext axisMsgContext = new MessageContext(new AxisClient(new NullProvider()));
 | 
			
		||||
 | 
			
		||||
   /*
 | 
			
		||||
    * Constructor.
 | 
			
		||||
@@ -354,37 +103,28 @@ public class AuthToken
 | 
			
		||||
                                     targetHost,
 | 
			
		||||
                                     svcConfig);
 | 
			
		||||
 | 
			
		||||
            m_identityToken = new StringBuffer();
 | 
			
		||||
            m_identityToken.append(identityToken.getEncodedToken());
 | 
			
		||||
            m_identityToken = identityToken.getEncodedToken();
 | 
			
		||||
            m_identityTokenType = identityToken.getProviderType();
 | 
			
		||||
 | 
			
		||||
            m_lifetime = authTokenConfig.getSetting(AuthTokenConfig.TokenLifetime);
 | 
			
		||||
            m_lifetimeShorter = authTokenConfig.getSetting(AuthTokenConfig.LifetimeShorter);
 | 
			
		||||
 | 
			
		||||
            // Generate a signature
 | 
			
		||||
            // tbd - Over identToken, identToken type, and lifetime data.
 | 
			
		||||
            m_signature = "tbd";
 | 
			
		||||
            // Create AuthTokenMessage
 | 
			
		||||
            Message authTokenMessage = getMessage(identityToken.getEncodedToken(),
 | 
			
		||||
                                                  identityToken.getProviderType(),
 | 
			
		||||
                                                  Integer.valueOf(m_lifetime).intValue(),
 | 
			
		||||
                                                  svcConfig);
 | 
			
		||||
 | 
			
		||||
            // Get a StringBuffer to help us with the construction of the token
 | 
			
		||||
            StringBuffer sb = new StringBuffer();
 | 
			
		||||
 | 
			
		||||
            // Start building the message
 | 
			
		||||
            sb.append(ProtoDefs.xmlDeclaration + "\r\n");
 | 
			
		||||
            sb.append("<" + ProtoDefs.authTokenElementName + ">" + "\r\n");
 | 
			
		||||
            sb.append("<" + ProtoDefs.signatureElementName + ">" + m_signature + "</" + ProtoDefs.signatureElementName + ">" + "\r\n");
 | 
			
		||||
            sb.append("<" + ProtoDefs.lifetimeElementName + ">" + m_lifetime + "</" + ProtoDefs.lifetimeElementName + ">" + "\r\n");
 | 
			
		||||
            sb.append("<" + ProtoDefs.identTokenElementName + ">"
 | 
			
		||||
                      + "<" + ProtoDefs.typeElementName + ">" + m_identityTokenType + "</" + ProtoDefs.typeElementName + ">"
 | 
			
		||||
                      + m_identityToken + "</" + ProtoDefs.identTokenElementName + ">" + "\r\n");
 | 
			
		||||
            sb.append("</" + ProtoDefs.authTokenElementName + ">" + "\r\n");
 | 
			
		||||
 | 
			
		||||
            // Save the token
 | 
			
		||||
            m_token = sb.toString();
 | 
			
		||||
            // Now save the message as a string
 | 
			
		||||
            OutputStream outStream = new ByteArrayOutputStream();
 | 
			
		||||
            authTokenMessage.writeTo(outStream);
 | 
			
		||||
            m_token = outStream.toString();
 | 
			
		||||
            outStream.close();
 | 
			
		||||
         }
 | 
			
		||||
         catch (Exception e)
 | 
			
		||||
         {
 | 
			
		||||
            // tbd
 | 
			
		||||
            System.err.println("AuthToken()- Exception: " + e.toString()); 
 | 
			
		||||
            System.err.println("AuthToken()- Exception: " + e.toString());
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
@@ -402,33 +142,102 @@ public class AuthToken
 | 
			
		||||
      // Decode the token string
 | 
			
		||||
      m_token = Base64Coder.decode(token);
 | 
			
		||||
 | 
			
		||||
      // Instantiate string buffer for the identity token
 | 
			
		||||
      m_identityToken = new StringBuffer();
 | 
			
		||||
      // Now instantiate a SOAP message with the string
 | 
			
		||||
      InputStream inStream = new ByteArrayInputStream(m_token.getBytes());
 | 
			
		||||
      Message message = new Message(inStream);
 | 
			
		||||
 | 
			
		||||
      // Get access to the SOAP Envelope
 | 
			
		||||
      SOAPEnvelope envelope = message.getSOAPEnvelope();
 | 
			
		||||
 | 
			
		||||
      // Verify the message
 | 
			
		||||
      if (WSSecurity.verifyMessage(envelope))
 | 
			
		||||
      {
 | 
			
		||||
         // Message verification succeded, now obtain the identity token
 | 
			
		||||
         // and its type from the message body.
 | 
			
		||||
         SOAPBody body = (SOAPBody) envelope.getBody();
 | 
			
		||||
         QName authTokenElementName = new QName("auth_token");
 | 
			
		||||
         MessageElement authTokenElement = body.getChildElement(authTokenElementName);
 | 
			
		||||
         QName identTokenElementName = new QName("ident_token");
 | 
			
		||||
         MessageElement identTokenElement = authTokenElement.getChildElement(identTokenElementName);
 | 
			
		||||
         if (identTokenElement != null)
 | 
			
		||||
         {
 | 
			
		||||
            QName identTokenTypeElementName = new QName("type");
 | 
			
		||||
            MessageElement identTokenTypeElement = identTokenElement.getChildElement(identTokenTypeElementName);
 | 
			
		||||
            if (identTokenTypeElement != null)
 | 
			
		||||
            {
 | 
			
		||||
               m_identityToken = identTokenElement.getChildNodes().item(1).getNodeValue();
 | 
			
		||||
               m_identityTokenType = identTokenTypeElement.getValue();
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         if (m_identityToken == null || m_identityTokenType == null)
 | 
			
		||||
         {
 | 
			
		||||
            System.out.println("AuthToken()- Required data missing from authentication token");
 | 
			
		||||
            throw new Exception("Error: Required data missing from Authentication Token");
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
         // Message verification failed
 | 
			
		||||
         System.err.println("AuthToken()- Invalid Authentication Token");
 | 
			
		||||
         throw new Exception("Invalid Authentication Token");
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Get AuthToken SOAP Message
 | 
			
		||||
    *
 | 
			
		||||
    * @param identityToken          String containing the identity token that should be part of the message
 | 
			
		||||
    * @param identityTokenType      String containing the identity token type
 | 
			
		||||
    * @param lifetime               Lifetime that should be specified in the message timestamp (seconds)
 | 
			
		||||
    * @param svcConfig              Service configuratio object
 | 
			
		||||
    * @return <code>Message<code>   AuthToken message, null if the method fails.
 | 
			
		||||
    */
 | 
			
		||||
   private Message getMessage(String identityToken,
 | 
			
		||||
                              String identityTokenType,
 | 
			
		||||
                              int lifetime,
 | 
			
		||||
                              SvcConfig svcConfig)
 | 
			
		||||
   {
 | 
			
		||||
      Message secureMessage;
 | 
			
		||||
 | 
			
		||||
      // Now parse the token into its elements
 | 
			
		||||
      try
 | 
			
		||||
      {
 | 
			
		||||
         // Parse the AuthToken
 | 
			
		||||
         XMLReader xr = XMLReaderFactory.createXMLReader();
 | 
			
		||||
         SAXHandler handler = new SAXHandler(this);
 | 
			
		||||
         xr.setContentHandler(handler);
 | 
			
		||||
         xr.setErrorHandler(handler);
 | 
			
		||||
         // Build SOAP Message with an identity token in the body
 | 
			
		||||
         //
 | 
			
		||||
         // First create a message and obtain its body
 | 
			
		||||
         InputStream inStream = new ByteArrayInputStream(authTokenSoapMsg.getBytes());
 | 
			
		||||
         Message message = new Message(inStream);
 | 
			
		||||
         message.setMessageContext(axisMsgContext);
 | 
			
		||||
         SOAPBody body = (SOAPBody) message.getSOAPBody();
 | 
			
		||||
 | 
			
		||||
         ByteArrayInputStream inStream = new ByteArrayInputStream(m_token.getBytes());
 | 
			
		||||
         InputSource source = new InputSource(inStream);
 | 
			
		||||
         xr.parse(source);
 | 
			
		||||
         // Get access to the auth_token element
 | 
			
		||||
         QName authTokenElementName = new QName("auth_token");
 | 
			
		||||
         MessageElement authTokenElement = body.getChildElement(authTokenElementName);
 | 
			
		||||
 | 
			
		||||
         // Verify the signature
 | 
			
		||||
         // tbd
 | 
			
		||||
         // Get access to the ident_token element and set its value
 | 
			
		||||
         QName identTokenElementName = new QName("ident_token");
 | 
			
		||||
         MessageElement identTokenElement = authTokenElement.getChildElement(identTokenElementName);
 | 
			
		||||
         identTokenElement.addTextNode(identityToken);
 | 
			
		||||
 | 
			
		||||
         // Verify that the token has not expired
 | 
			
		||||
         // tbd
 | 
			
		||||
         // Get access to the identity token type element element and set its value
 | 
			
		||||
         QName identTokenTypeElementName = new QName("type");
 | 
			
		||||
         MessageElement identTokenTypeElement = identTokenElement.getChildElement(identTokenTypeElementName);
 | 
			
		||||
         identTokenTypeElement.setValue(identityTokenType);
 | 
			
		||||
 | 
			
		||||
         // Now we need to secure the SOAP message that we created, we are doing to
 | 
			
		||||
         // do so by adding a timestamp and signing the timestamp as well as the body.
 | 
			
		||||
         // To do this we are going to leverage WS-Security.
 | 
			
		||||
         secureMessage = WSSecurity.secureSOAPEnvelope(message.getSOAPEnvelope(),
 | 
			
		||||
                                                       lifetime,
 | 
			
		||||
                                                       svcConfig);
 | 
			
		||||
      }
 | 
			
		||||
      catch (SAXException e)
 | 
			
		||||
      catch (Exception e)
 | 
			
		||||
      {
 | 
			
		||||
         System.err.println("AuthToken()- Parse exception: " + e.toString()); 
 | 
			
		||||
         throw new Exception("Protocol error");
 | 
			
		||||
         System.out.println("AuthToken.getMessage() - Exception caught building message, error: " + e.getMessage());
 | 
			
		||||
         secureMessage = null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return secureMessage;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /*
 | 
			
		||||
@@ -441,11 +250,20 @@ public class AuthToken
 | 
			
		||||
 | 
			
		||||
   /*
 | 
			
		||||
    * Returns the lifetime of the token.
 | 
			
		||||
    *
 | 
			
		||||
    * Note: It is only valid to execute this procedure if its called on an object
 | 
			
		||||
    * instantiated via the constructor which takes a lifetime parameter.
 | 
			
		||||
    */
 | 
			
		||||
   public String getLifetime()
 | 
			
		||||
   public String getLifetime() throws Exception
 | 
			
		||||
   {
 | 
			
		||||
      // tbd - Convert to tokenLifetime and lifetimeShorter to ints, substractand then convert result to string
 | 
			
		||||
      return "60";
 | 
			
		||||
      // Throw exeption if the lifetime parameter is not set
 | 
			
		||||
      if (m_lifetime.length() == 0)
 | 
			
		||||
      {
 | 
			
		||||
         System.out.println("AuthToken.getLifetime() - Called when lifetime is not set");
 | 
			
		||||
         throw new Exception("Error: Called getLifetime while not set");
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return Integer.toString(Integer.valueOf(m_lifetime).intValue() - Integer.valueOf(m_lifetimeShorter).intValue());
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /*
 | 
			
		||||
@@ -453,7 +271,7 @@ public class AuthToken
 | 
			
		||||
    */
 | 
			
		||||
   public String getIdentityToken()
 | 
			
		||||
   {
 | 
			
		||||
      return m_identityToken.toString();
 | 
			
		||||
      return m_identityToken;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /*
 | 
			
		||||
 
 | 
			
		||||
@@ -281,16 +281,16 @@ public class Authenticate implements RpcMethod
 | 
			
		||||
               // An identity was resolved, get a SessionToken for it.
 | 
			
		||||
               SessionToken sessionToken = new SessionToken(identId,
 | 
			
		||||
                                                            authReqMsg.getRealm(),
 | 
			
		||||
                                                            m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime));
 | 
			
		||||
                                                            m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime),
 | 
			
		||||
                                                            m_svcConfig);
 | 
			
		||||
 | 
			
		||||
               // Write out the response
 | 
			
		||||
               String respLifetime = Integer.toString(Integer.valueOf(m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime)).intValue()
 | 
			
		||||
                                                      - Integer.valueOf(m_svcConfig.getSetting(SvcConfig.LifetimeShorter)).intValue());
 | 
			
		||||
               AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpOkStatusMsg,
 | 
			
		||||
                                                         ProtoDefs.httpOkStatusCode,
 | 
			
		||||
                                                         sessionToken.toString(),
 | 
			
		||||
                                                         m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime));
 | 
			
		||||
               // tbd - Convert to ints, perform calculation, and then convert result to string
 | 
			
		||||
               //m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime)
 | 
			
		||||
               //- m_svcConfig.getSetting(SvcConfig.LifetimeShorter));
 | 
			
		||||
                                                         respLifetime);
 | 
			
		||||
               out.println(authRespMsg.toString());
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
 
 | 
			
		||||
@@ -102,7 +102,6 @@ public class GetAuthPolicyReqMsg
 | 
			
		||||
         // Proceed based on our state
 | 
			
		||||
         switch (m_state)
 | 
			
		||||
         {
 | 
			
		||||
            
 | 
			
		||||
            case AWAITING_ROOT_ELEMENT_START:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.getAuthPolicyRequestElementName.equals(qName))
 | 
			
		||||
@@ -160,7 +159,6 @@ public class GetAuthPolicyReqMsg
 | 
			
		||||
         // Proceed based on our state
 | 
			
		||||
         switch (m_state)
 | 
			
		||||
         {
 | 
			
		||||
            
 | 
			
		||||
            case AWAITING_ROOT_ELEMENT_END:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.getAuthPolicyRequestElementName.equals(qName))
 | 
			
		||||
@@ -217,7 +215,6 @@ public class GetAuthPolicyReqMsg
 | 
			
		||||
         // Proceed based on our state
 | 
			
		||||
         switch (m_state)
 | 
			
		||||
         {
 | 
			
		||||
            
 | 
			
		||||
            case AWAITING_SERVICE_DATA:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_GetAuthPolicyReqMsg.m_serviceName = new String(ch, start, length);
 | 
			
		||||
@@ -226,6 +223,11 @@ public class GetAuthPolicyReqMsg
 | 
			
		||||
               m_state = AWAITING_SERVICE_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_SERVICE_ELEMENT_END:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_GetAuthPolicyReqMsg.m_serviceName = m_GetAuthPolicyReqMsg.m_serviceName.concat(new String(ch, start, length));
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_HOST_DATA:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_GetAuthPolicyReqMsg.m_hostName = new String(ch, start, length);
 | 
			
		||||
@@ -234,6 +236,11 @@ public class GetAuthPolicyReqMsg
 | 
			
		||||
               m_state = AWAITING_HOST_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_HOST_ELEMENT_END:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_GetAuthPolicyReqMsg.m_hostName = m_GetAuthPolicyReqMsg.m_hostName.concat(new String(ch, start, length));
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
               // Do nothing
 | 
			
		||||
               break;
 | 
			
		||||
 
 | 
			
		||||
@@ -107,7 +107,6 @@ public class GetAuthTokReqMsg
 | 
			
		||||
         // Proceed based on our state
 | 
			
		||||
         switch (m_state)
 | 
			
		||||
         {
 | 
			
		||||
            
 | 
			
		||||
            case AWAITING_ROOT_ELEMENT_START:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.getAuthTokRequestElementName.equals(qName))
 | 
			
		||||
@@ -179,7 +178,6 @@ public class GetAuthTokReqMsg
 | 
			
		||||
         // Proceed based on our state
 | 
			
		||||
         switch (m_state)
 | 
			
		||||
         {
 | 
			
		||||
            
 | 
			
		||||
            case AWAITING_ROOT_ELEMENT_END:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.getAuthTokRequestElementName.equals(qName))
 | 
			
		||||
@@ -250,7 +248,6 @@ public class GetAuthTokReqMsg
 | 
			
		||||
         // Proceed based on our state
 | 
			
		||||
         switch (m_state)
 | 
			
		||||
         {
 | 
			
		||||
            
 | 
			
		||||
            case AWAITING_SERVICE_DATA:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_GetAuthTokReqMsg.m_serviceName = new String(ch, start, length);
 | 
			
		||||
@@ -259,6 +256,11 @@ public class GetAuthTokReqMsg
 | 
			
		||||
               m_state = AWAITING_SERVICE_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_SERVICE_ELEMENT_END:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_GetAuthTokReqMsg.m_serviceName = m_GetAuthTokReqMsg.m_serviceName.concat(new String(ch, start, length));
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_HOST_DATA:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_GetAuthTokReqMsg.m_hostName = new String(ch, start, length);
 | 
			
		||||
@@ -267,6 +269,11 @@ public class GetAuthTokReqMsg
 | 
			
		||||
               m_state = AWAITING_HOST_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_HOST_ELEMENT_END:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_GetAuthTokReqMsg.m_hostName = m_GetAuthTokReqMsg.m_hostName.concat(new String(ch, start, length));
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_SESSION_TOKEN_DATA:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_GetAuthTokReqMsg.m_sessionToken = new String(ch, start, length);
 | 
			
		||||
@@ -275,6 +282,11 @@ public class GetAuthTokReqMsg
 | 
			
		||||
               m_state = AWAITING_SESSION_TOKEN_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_SESSION_TOKEN_ELEMENT_END:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_GetAuthTokReqMsg.m_sessionToken = m_GetAuthTokReqMsg.m_sessionToken.concat(new String(ch, start, length));
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
               // Do nothing
 | 
			
		||||
               break;
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,8 @@ JAVAFILES = ProtoDefs.java \
 | 
			
		||||
	GetAuthTokRespMsg.java \
 | 
			
		||||
	Krb5Authenticate.java \
 | 
			
		||||
	PwdAuthenticate.java \
 | 
			
		||||
	SessionToken.java
 | 
			
		||||
	SessionToken.java \
 | 
			
		||||
	WSSecurity.java
 | 
			
		||||
 | 
			
		||||
EXTRA_DIST = $(JAVAFILES) \
 | 
			
		||||
		Krb5_mechanism.settings \
 | 
			
		||||
 
 | 
			
		||||
@@ -26,20 +26,26 @@ package com.novell.casa.authtoksvc;
 | 
			
		||||
 | 
			
		||||
import java.io.ByteArrayInputStream;
 | 
			
		||||
 | 
			
		||||
import org.xml.sax.InputSource;
 | 
			
		||||
import org.xml.sax.SAXException;
 | 
			
		||||
import org.xml.sax.XMLReader;
 | 
			
		||||
import org.xml.sax.helpers.XMLReaderFactory;
 | 
			
		||||
import org.apache.axis.Message;
 | 
			
		||||
import org.apache.axis.MessageContext;
 | 
			
		||||
import org.apache.axis.client.AxisClient;
 | 
			
		||||
import org.apache.axis.configuration.NullProvider;
 | 
			
		||||
import org.apache.axis.message.SOAPEnvelope;
 | 
			
		||||
import org.apache.axis.message.SOAPBody;
 | 
			
		||||
import org.apache.axis.message.MessageElement;
 | 
			
		||||
 | 
			
		||||
import javax.xml.namespace.QName;
 | 
			
		||||
import java.io.*;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
* SessionToken class.
 | 
			
		||||
* 
 | 
			
		||||
* This class constructs session tokens that Casa clients can present to
 | 
			
		||||
* the Casa server to prove that an entity has been authenticated to
 | 
			
		||||
* a particular realm. The format of the session token is as follows:
 | 
			
		||||
* 
 | 
			
		||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
 | 
			
		||||
* This class constructs sessions tokens that clients can present to an ATS
 | 
			
		||||
* to prove that an entity has been authenticated to a particular realm.
 | 
			
		||||
* The session token consists of a SOAP message secured with WSSecurity
 | 
			
		||||
* with the appropriate elements signed and with a timestamp. The body of
 | 
			
		||||
* the SOAP message is as follows:
 | 
			
		||||
*
 | 
			
		||||
* <session_token>
 | 
			
		||||
* <signature>signature value</signature>
 | 
			
		||||
* <lifetime>lifetime value</lifetime>
 | 
			
		||||
@@ -51,308 +57,47 @@ import org.xml.sax.helpers.XMLReaderFactory;
 | 
			
		||||
public class SessionToken
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
   private String m_id;
 | 
			
		||||
   private String m_realm;
 | 
			
		||||
   private String m_lifetime;
 | 
			
		||||
   private String m_signature;
 | 
			
		||||
   private String m_id = null;
 | 
			
		||||
   private String m_realm = null;
 | 
			
		||||
   private String m_token;
 | 
			
		||||
 | 
			
		||||
   /*
 | 
			
		||||
    * Class for handling parsing events.
 | 
			
		||||
    */
 | 
			
		||||
   private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
 | 
			
		||||
   {
 | 
			
		||||
      private final static int AWAITING_ROOT_ELEMENT_START = 0;
 | 
			
		||||
      private final static int AWAITING_ROOT_ELEMENT_END = 1;
 | 
			
		||||
      private final static int AWAITING_SIGNATURE_ELEMENT_START = 2;
 | 
			
		||||
      private final static int AWAITING_SIGNATURE_ELEMENT_END = 3;
 | 
			
		||||
      private final static int AWAITING_SIGNATURE_DATA = 4;
 | 
			
		||||
      private final static int AWAITING_LIFETIME_ELEMENT_START = 5;
 | 
			
		||||
      private final static int AWAITING_LIFETIME_ELEMENT_END = 6;
 | 
			
		||||
      private final static int AWAITING_LIFETIME_DATA = 7;
 | 
			
		||||
      private final static int AWAITING_REALM_ELEMENT_START = 8;
 | 
			
		||||
      private final static int AWAITING_REALM_ELEMENT_END = 9;
 | 
			
		||||
      private final static int AWAITING_REALM_DATA = 10;
 | 
			
		||||
      private final static int AWAITING_IDENT_ID_ELEMENT_START = 11;
 | 
			
		||||
      private final static int AWAITING_IDENT_ID_ELEMENT_END = 12;
 | 
			
		||||
      private final static int AWAITING_IDENT_ID_DATA = 13;
 | 
			
		||||
      private final static int DONE_PARSING = 14;
 | 
			
		||||
   static final String sessionTokenSoapMsg =
 | 
			
		||||
      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
 | 
			
		||||
      "<SOAP-ENV:Envelope" +
 | 
			
		||||
      "    xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\"\n" +
 | 
			
		||||
      "    xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" +
 | 
			
		||||
      "    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
 | 
			
		||||
      "    <SOAP-ENV:Body>" +
 | 
			
		||||
      "        <session_token><realm></realm><ident_id></ident_id></session_token>" +
 | 
			
		||||
      "    </SOAP-ENV:Body>" +
 | 
			
		||||
      "</SOAP-ENV:Envelope>";
 | 
			
		||||
 | 
			
		||||
      private SessionToken m_SessionToken;
 | 
			
		||||
      private int       m_state;
 | 
			
		||||
   static final private MessageContext axisMsgContext = new MessageContext(new AxisClient(new NullProvider()));
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
       * Constructor
 | 
			
		||||
       */
 | 
			
		||||
      public SAXHandler (SessionToken SessionToken)
 | 
			
		||||
      {
 | 
			
		||||
         super();
 | 
			
		||||
 | 
			
		||||
         // Initialize our members
 | 
			
		||||
         m_SessionToken = SessionToken;
 | 
			
		||||
         m_state = AWAITING_ROOT_ELEMENT_START;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
       * endDocument() implementation.
 | 
			
		||||
       */
 | 
			
		||||
      public void endDocument () throws SAXException
 | 
			
		||||
      {
 | 
			
		||||
         // Verify that we obtained all of the required elements
 | 
			
		||||
         if (m_state != DONE_PARSING)
 | 
			
		||||
         {
 | 
			
		||||
            System.err.println("SessionToken SAXHandler.endDocument()- Missing element"); 
 | 
			
		||||
            throw new SAXException("Missing element");
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
       * startElement() implementation.
 | 
			
		||||
       */
 | 
			
		||||
      public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
 | 
			
		||||
      {
 | 
			
		||||
         // Proceed based on our state
 | 
			
		||||
         switch (m_state)
 | 
			
		||||
         {
 | 
			
		||||
            
 | 
			
		||||
            case AWAITING_ROOT_ELEMENT_START:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.sessionTokenElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_SIGNATURE_ELEMENT_START;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("SessionToken SAXHandler.startElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_SIGNATURE_ELEMENT_START:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.signatureElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_SIGNATURE_DATA;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("SessionToken SAXHandler.startElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_LIFETIME_ELEMENT_START:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.lifetimeElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_LIFETIME_DATA;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("SessionToken SAXHandler.startElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_REALM_ELEMENT_START:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.realmElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_REALM_DATA;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("SessionToken SAXHandler.startElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_IDENT_ID_ELEMENT_START:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.identIdElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_IDENT_ID_DATA;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("SessionToken SAXHandler.startElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
               System.err.println("SessionToken SAXHandler.startElement()- State error"); 
 | 
			
		||||
               throw new SAXException("State error");
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
       * endElement() immplementation.
 | 
			
		||||
       */
 | 
			
		||||
      public void endElement (String uri, String name, String qName) throws SAXException
 | 
			
		||||
      {
 | 
			
		||||
         // Proceed based on our state
 | 
			
		||||
         switch (m_state)
 | 
			
		||||
         {
 | 
			
		||||
            
 | 
			
		||||
            case AWAITING_ROOT_ELEMENT_END:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.sessionTokenElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = DONE_PARSING;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("SessionToken SAXHandler.endElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_SIGNATURE_ELEMENT_END:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.signatureElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_LIFETIME_ELEMENT_START;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("SessionToken SAXHandler.endElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_LIFETIME_ELEMENT_END:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.lifetimeElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_REALM_ELEMENT_START;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("SessionToken SAXHandler.endElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_REALM_ELEMENT_END:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.realmElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_IDENT_ID_ELEMENT_START;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("SessionToken SAXHandler.endElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_IDENT_ID_ELEMENT_END:
 | 
			
		||||
               // Verify that we are processing the expected tag
 | 
			
		||||
               if (ProtoDefs.identIdElementName.equals(qName))
 | 
			
		||||
               {
 | 
			
		||||
                  // Advance to the next state
 | 
			
		||||
                  m_state = AWAITING_ROOT_ELEMENT_END;
 | 
			
		||||
               }
 | 
			
		||||
               else
 | 
			
		||||
               {
 | 
			
		||||
                  System.err.println("SessionToken SAXHandler.endElement()- Un-expected element"); 
 | 
			
		||||
                  throw new SAXException("Un-expected element");
 | 
			
		||||
               }
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
               System.err.println("SessionToken SAXHandler.startElement()- State error"); 
 | 
			
		||||
               throw new SAXException("State error");
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      /*
 | 
			
		||||
       * character() implementation.
 | 
			
		||||
       */
 | 
			
		||||
      public void characters (char ch[], int start, int length) throws SAXException
 | 
			
		||||
      {
 | 
			
		||||
         // Proceed based on our state
 | 
			
		||||
         switch (m_state)
 | 
			
		||||
         {
 | 
			
		||||
            
 | 
			
		||||
            case AWAITING_SIGNATURE_DATA:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_SessionToken.m_signature = new String(ch, start, length);
 | 
			
		||||
 | 
			
		||||
               // Advance to the next state
 | 
			
		||||
               m_state = AWAITING_SIGNATURE_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_LIFETIME_DATA:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_SessionToken.m_lifetime = new String(ch, start, length);
 | 
			
		||||
 | 
			
		||||
               // Advance to the next state
 | 
			
		||||
               m_state = AWAITING_LIFETIME_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_REALM_DATA:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_SessionToken.m_realm = new String(ch, start, length);
 | 
			
		||||
 | 
			
		||||
               // Advance to the next state
 | 
			
		||||
               m_state = AWAITING_REALM_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            case AWAITING_IDENT_ID_DATA:
 | 
			
		||||
               // Consume the data
 | 
			
		||||
               m_SessionToken.m_id = new String(ch, start, length);
 | 
			
		||||
 | 
			
		||||
               // Advance to the next state
 | 
			
		||||
               m_state = AWAITING_IDENT_ID_ELEMENT_END;
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
               // Do nothing
 | 
			
		||||
               break;
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /*
 | 
			
		||||
    * Constructor
 | 
			
		||||
    */
 | 
			
		||||
   public SessionToken(String id, String realm, String lifetime) throws Exception
 | 
			
		||||
   public SessionToken(String id,
 | 
			
		||||
                       String realm,
 | 
			
		||||
                       String lifetime,
 | 
			
		||||
                       SvcConfig svcConfig) throws Exception
 | 
			
		||||
   {
 | 
			
		||||
      // Save copies of the input parameters
 | 
			
		||||
      m_id = id;
 | 
			
		||||
      m_realm = realm;
 | 
			
		||||
      m_lifetime = lifetime;
 | 
			
		||||
 | 
			
		||||
      // Generate a signature
 | 
			
		||||
      // tbd - Over id, realm, and lifetime data.
 | 
			
		||||
      m_signature = "tbd";
 | 
			
		||||
      // Create SessionTokenMessage
 | 
			
		||||
      Message sessionTokenMessage = getMessage(realm,
 | 
			
		||||
                                               id,
 | 
			
		||||
                                               Integer.valueOf(lifetime).intValue(),
 | 
			
		||||
                                               svcConfig);
 | 
			
		||||
 | 
			
		||||
      // Get a StringBuffer to help us with the construction of the token
 | 
			
		||||
      StringBuffer sb = new StringBuffer();
 | 
			
		||||
 | 
			
		||||
      // Start building the message
 | 
			
		||||
      sb.append(ProtoDefs.xmlDeclaration + "\r\n");
 | 
			
		||||
      sb.append("<" + ProtoDefs.sessionTokenElementName + ">" + "\r\n");
 | 
			
		||||
      sb.append("<" + ProtoDefs.signatureElementName + ">" + m_signature + "</" + ProtoDefs.signatureElementName + ">" + "\r\n");
 | 
			
		||||
      sb.append("<" + ProtoDefs.lifetimeElementName + ">" + m_lifetime + "</" + ProtoDefs.lifetimeElementName + ">" + "\r\n");
 | 
			
		||||
      sb.append("<" + ProtoDefs.realmElementName + ">" + m_realm + "</" + ProtoDefs.realmElementName + ">" + "\r\n");
 | 
			
		||||
      sb.append("<" + ProtoDefs.identIdElementName + ">" + m_id + "</" + ProtoDefs.identIdElementName + ">" + "\r\n");
 | 
			
		||||
      sb.append("</" + ProtoDefs.sessionTokenElementName + ">" + "\r\n");
 | 
			
		||||
 | 
			
		||||
      // Save the token
 | 
			
		||||
      m_token = sb.toString();
 | 
			
		||||
      // Now save the message as a string
 | 
			
		||||
      OutputStream outStream = new ByteArrayOutputStream();
 | 
			
		||||
      sessionTokenMessage.writeTo(outStream);
 | 
			
		||||
      m_token = outStream.toString();
 | 
			
		||||
      outStream.close();
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /*
 | 
			
		||||
@@ -364,30 +109,102 @@ public class SessionToken
 | 
			
		||||
      // Decode the token string
 | 
			
		||||
      m_token = Base64Coder.decode(token);
 | 
			
		||||
 | 
			
		||||
      // Now parse the token into its elements
 | 
			
		||||
      // Now instantiate a SOAP message with the string
 | 
			
		||||
      InputStream inStream = new ByteArrayInputStream(m_token.getBytes());
 | 
			
		||||
      Message message = new Message(inStream);
 | 
			
		||||
 | 
			
		||||
      // Get access to the SOAP Envelope
 | 
			
		||||
      SOAPEnvelope envelope = message.getSOAPEnvelope();
 | 
			
		||||
 | 
			
		||||
      // Verify the message
 | 
			
		||||
      if (WSSecurity.verifyMessage(envelope))
 | 
			
		||||
      {
 | 
			
		||||
         // Message verification succeded, now obtain the realm and identity id
 | 
			
		||||
         // from the message body.
 | 
			
		||||
         SOAPBody body = (SOAPBody) envelope.getBody();
 | 
			
		||||
         QName sessionTokenElementName = new QName("session_token");
 | 
			
		||||
         MessageElement sessionTokenElement = body.getChildElement(sessionTokenElementName);
 | 
			
		||||
         QName realmElementName = new QName("realm");
 | 
			
		||||
         MessageElement realmElement = sessionTokenElement.getChildElement(realmElementName);
 | 
			
		||||
         if (realmElement != null)
 | 
			
		||||
         {
 | 
			
		||||
            m_realm = realmElement.getChildNodes().item(0).getNodeValue();
 | 
			
		||||
         }
 | 
			
		||||
         QName identIdElementName = new QName("ident_id");
 | 
			
		||||
         MessageElement identIdElement = sessionTokenElement.getChildElement(identIdElementName);
 | 
			
		||||
         if (identIdElement != null)
 | 
			
		||||
         {
 | 
			
		||||
            m_id = identIdElement.getChildNodes().item(0).getNodeValue();
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         if (m_realm == null || m_id == null)
 | 
			
		||||
         {
 | 
			
		||||
            System.out.println("SessionToken()- Required data missing from session token");
 | 
			
		||||
            throw new Exception("Error: Required data missing from session Token");
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
         // Message verification failed
 | 
			
		||||
         System.err.println("SessionToken()- Invalid Session Token");
 | 
			
		||||
         throw new Exception("Invalid Session Token");
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Get SessionToken SOAP Message
 | 
			
		||||
    *
 | 
			
		||||
    * @param realm         String containing the identity token that should be part of the message
 | 
			
		||||
    * @param identityId    String containing the identity token type
 | 
			
		||||
    * @param lifetime      Lifetime that should be specified in the message timestamp (seconds)
 | 
			
		||||
    * @param svcConfig              Service Config object
 | 
			
		||||
    * @return <code>Message<code>   SessionToken message, null if the method fails.
 | 
			
		||||
    */
 | 
			
		||||
   private Message getMessage(String realm,
 | 
			
		||||
                              String identityId,
 | 
			
		||||
                              int lifetime,
 | 
			
		||||
                              SvcConfig svcConfig)
 | 
			
		||||
   {
 | 
			
		||||
      Message secureMessage;
 | 
			
		||||
 | 
			
		||||
      try
 | 
			
		||||
      {
 | 
			
		||||
         // Parse the SessionToken
 | 
			
		||||
         XMLReader xr = XMLReaderFactory.createXMLReader();
 | 
			
		||||
         SAXHandler handler = new SAXHandler(this);
 | 
			
		||||
         xr.setContentHandler(handler);
 | 
			
		||||
         xr.setErrorHandler(handler);
 | 
			
		||||
         // Build SOAP Message with an identity token in the body
 | 
			
		||||
         //
 | 
			
		||||
         // First create a message and obtain its body
 | 
			
		||||
         InputStream inStream = new ByteArrayInputStream(sessionTokenSoapMsg.getBytes());
 | 
			
		||||
         Message message = new Message(inStream);
 | 
			
		||||
         message.setMessageContext(axisMsgContext);
 | 
			
		||||
         SOAPBody body = (SOAPBody) message.getSOAPBody();
 | 
			
		||||
 | 
			
		||||
         ByteArrayInputStream inStream = new ByteArrayInputStream(m_token.getBytes());
 | 
			
		||||
         InputSource source = new InputSource(inStream);
 | 
			
		||||
         xr.parse(source);
 | 
			
		||||
         // Get access to the session_token element
 | 
			
		||||
         QName sessionTokenElementName = new QName("session_token");
 | 
			
		||||
         MessageElement sessionTokenElement = body.getChildElement(sessionTokenElementName);
 | 
			
		||||
 | 
			
		||||
         // Verify the signature
 | 
			
		||||
         // tbd
 | 
			
		||||
         // Get access to the realm element and set its value
 | 
			
		||||
         QName realmElementName = new QName("realm");
 | 
			
		||||
         MessageElement realmElement = sessionTokenElement.getChildElement(realmElementName);
 | 
			
		||||
         realmElement.addTextNode(realm);
 | 
			
		||||
 | 
			
		||||
         // Verify that the token has not expired
 | 
			
		||||
         // tbd
 | 
			
		||||
         // Get access to the ident_id element and set its value
 | 
			
		||||
         QName identIdElementName = new QName("ident_id");
 | 
			
		||||
         MessageElement identIdElement = sessionTokenElement.getChildElement(identIdElementName);
 | 
			
		||||
         identIdElement.addTextNode(identityId);
 | 
			
		||||
 | 
			
		||||
         // Now we need to secure the SOAP message that we created, we are doing to
 | 
			
		||||
         // do so by adding a timestamp and signing the timestamp as well as the body.
 | 
			
		||||
         // To do this we are going to leverage WS-Security.
 | 
			
		||||
         secureMessage = WSSecurity.secureSOAPEnvelope(message.getSOAPEnvelope(),
 | 
			
		||||
                                                       lifetime,
 | 
			
		||||
                                                       svcConfig);
 | 
			
		||||
      }
 | 
			
		||||
      catch (SAXException e)
 | 
			
		||||
      catch (Exception e)
 | 
			
		||||
      {
 | 
			
		||||
         System.err.println("SessionToken()- Parse exception: " + e.toString()); 
 | 
			
		||||
         throw new Exception("Protocol error");
 | 
			
		||||
         System.out.println("SessionToken.getMessage() - Exception caught building message, error: " + e.getMessage());
 | 
			
		||||
         secureMessage = null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return secureMessage;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /*
 | 
			
		||||
 
 | 
			
		||||
@@ -53,6 +53,8 @@ public class SvcConfig
 | 
			
		||||
   public final static String ConfigFolderPath = "ConfigFolderPath";
 | 
			
		||||
   public final static String AppRootPath = "AppRootPath";
 | 
			
		||||
   public final static String ReconfigureInterval = "ReconfigureInterval";
 | 
			
		||||
   public final static String KeyStoreUser = "KeyStoreUser";
 | 
			
		||||
   public final static String KeyStorePwd = "KeyStorePwd";
 | 
			
		||||
 | 
			
		||||
   // Default configuration values
 | 
			
		||||
   public final static  String DefaultSessionTokenLifetimeValue = "43200";    // Seconds
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,274 @@
 | 
			
		||||
/***********************************************************************
 | 
			
		||||
 * 
 | 
			
		||||
 *  Copyright (C) 2006 Novell, Inc. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 *  This library is free software; you can redistribute it and/or
 | 
			
		||||
 *  modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
 *  License as published by the Free Software Foundation; version 2.1
 | 
			
		||||
 *  of the License.
 | 
			
		||||
 *
 | 
			
		||||
 *  This library is distributed in the hope that it will be useful,
 | 
			
		||||
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 *  Library Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *  You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 *  License along with this library; if not, Novell, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 *  To contact Novell about this file by physical or electronic mail, 
 | 
			
		||||
 *  you may find current contact information at www.novell.com.
 | 
			
		||||
 * 
 | 
			
		||||
 *  Author: Juan Carlos Luciani <jluciani@novell.com>
 | 
			
		||||
 *  
 | 
			
		||||
 ***********************************************************************/
 | 
			
		||||
 | 
			
		||||
package com.novell.casa.authtoksvc;
 | 
			
		||||
 | 
			
		||||
import java.io.ByteArrayInputStream;
 | 
			
		||||
 | 
			
		||||
import org.apache.axis.Message;
 | 
			
		||||
import org.apache.axis.message.SOAPEnvelope;
 | 
			
		||||
import org.apache.ws.security.*;
 | 
			
		||||
import org.apache.ws.security.components.crypto.Crypto;
 | 
			
		||||
import org.apache.ws.security.components.crypto.CryptoFactory;
 | 
			
		||||
import org.apache.ws.security.message.WSSecHeader;
 | 
			
		||||
import org.apache.ws.security.message.WSSecSignature;
 | 
			
		||||
import org.apache.ws.security.message.WSSecTimestamp;
 | 
			
		||||
import org.apache.xml.security.c14n.Canonicalizer;
 | 
			
		||||
import org.w3c.dom.Document;
 | 
			
		||||
import org.w3c.dom.Element;
 | 
			
		||||
import org.w3c.dom.Node;
 | 
			
		||||
 | 
			
		||||
import javax.xml.soap.MessageFactory;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.Vector;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * WSSecurity Class.
 | 
			
		||||
 * 
 | 
			
		||||
 * This class provides static methods for securing and verifying SOAP messages. SOAP messages
 | 
			
		||||
 * are secured by adding a timestamp and signing the appropriate elements using methods and
 | 
			
		||||
 * headers defined by WS* specifications.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
public class WSSecurity
 | 
			
		||||
{
 | 
			
		||||
   static final private WSSecurityEngine secEngine = new WSSecurityEngine();
 | 
			
		||||
   static final private Crypto crypto = CryptoFactory.getInstance();
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Creates a SOAP message from a document.
 | 
			
		||||
    *
 | 
			
		||||
    */
 | 
			
		||||
   private static Message toSOAPMessage(Document doc) throws Exception
 | 
			
		||||
   {
 | 
			
		||||
       Canonicalizer c14n = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS);
 | 
			
		||||
       byte[] canonicalMessage = c14n.canonicalizeSubtree(doc);
 | 
			
		||||
       ByteArrayInputStream in = new ByteArrayInputStream(canonicalMessage);
 | 
			
		||||
       MessageFactory factory = MessageFactory.newInstance();
 | 
			
		||||
       return (org.apache.axis.Message) factory.createMessage(null, in);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /***
 | 
			
		||||
    * Returns the first element that containes an Id with value
 | 
			
		||||
    * <code>uri</code> and <code>namespace</code>.
 | 
			
		||||
    * <p/>
 | 
			
		||||
    *
 | 
			
		||||
    * Copyright Note: The code for this function was copied from file
 | 
			
		||||
    * WSSecurityUtil.java from package org.apache.ws.security.util.
 | 
			
		||||
    * The Copyright notice on this file is as follows:
 | 
			
		||||
    *
 | 
			
		||||
    *    Copyright  2003-2006 The Apache Software Foundation, or their licensors, as
 | 
			
		||||
    *    appropriate.
 | 
			
		||||
    *
 | 
			
		||||
    *    Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
    *    you may not use this file except in compliance with the License.
 | 
			
		||||
    *    You may obtain a copy of the License at
 | 
			
		||||
    *
 | 
			
		||||
    *       http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
    *
 | 
			
		||||
    *    Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
    *    distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
    *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
    *    See the License for the specific language governing permissions and
 | 
			
		||||
    *    limitations under the License.
 | 
			
		||||
    *
 | 
			
		||||
    * @param startNode Where to start the search
 | 
			
		||||
    * @param value     Value of the Id attribute
 | 
			
		||||
    * @param namespace Namespace URI of the Id
 | 
			
		||||
    * @return The found element or <code>null</code>
 | 
			
		||||
    */
 | 
			
		||||
   private static Element findElementById(Node startNode,
 | 
			
		||||
                                          String value,
 | 
			
		||||
                                          String namespace)
 | 
			
		||||
   {
 | 
			
		||||
      // Just return null if startNode is set to null
 | 
			
		||||
      if (startNode == null)
 | 
			
		||||
      {
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      Node startParent = startNode.getParentNode();
 | 
			
		||||
      Node processedNode;
 | 
			
		||||
      while (startNode != null)
 | 
			
		||||
      {
 | 
			
		||||
         // start node processing at this point
 | 
			
		||||
         if (startNode.getNodeType() == Node.ELEMENT_NODE)
 | 
			
		||||
         {
 | 
			
		||||
            Element se = (Element) startNode;
 | 
			
		||||
            if (se.hasAttributeNS(namespace, "Id")
 | 
			
		||||
                && value.equals(se.getAttributeNS(namespace, "Id")))
 | 
			
		||||
            {
 | 
			
		||||
               return se;
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         processedNode = startNode;
 | 
			
		||||
         startNode = startNode.getFirstChild();
 | 
			
		||||
 | 
			
		||||
         // no child, this node is done.
 | 
			
		||||
         if (startNode == null)
 | 
			
		||||
         {
 | 
			
		||||
            // close node processing, get sibling
 | 
			
		||||
            startNode = processedNode.getNextSibling();
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         // no more siblings, get parent, all children
 | 
			
		||||
         // of parent are processed.
 | 
			
		||||
         while (startNode == null)
 | 
			
		||||
         {
 | 
			
		||||
            processedNode = processedNode.getParentNode();
 | 
			
		||||
            if (processedNode == startParent)
 | 
			
		||||
            {
 | 
			
		||||
               return null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // close parent node processing (processed node now)
 | 
			
		||||
            startNode = processedNode.getNextSibling();
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return null;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Verifies SOAP envelope timestamp and signatures.
 | 
			
		||||
    *
 | 
			
		||||
    * @param envelope               SOAP envelope with timestamp
 | 
			
		||||
    * @return <code>boolean</code>  True if verification succeeds
 | 
			
		||||
    * @throws Exception on error
 | 
			
		||||
    */
 | 
			
		||||
   public static boolean verifyMessage(SOAPEnvelope envelope) throws Exception
 | 
			
		||||
   {
 | 
			
		||||
      boolean msgVerificationStatus = false;
 | 
			
		||||
 | 
			
		||||
      try
 | 
			
		||||
      {
 | 
			
		||||
         boolean timeStampProcessed = false;
 | 
			
		||||
         boolean signatureProcessed = false;
 | 
			
		||||
         Vector<WSSecurityEngineResult> results;
 | 
			
		||||
         Document signedDoc = envelope.getAsDocument();
 | 
			
		||||
         results = secEngine.processSecurityHeader(signedDoc, null, null, crypto);
 | 
			
		||||
         if (results != null)
 | 
			
		||||
         {
 | 
			
		||||
            for (WSSecurityEngineResult result : results)
 | 
			
		||||
            {
 | 
			
		||||
               if (result.getAction() == WSConstants.TS)
 | 
			
		||||
               {
 | 
			
		||||
                  timeStampProcessed = true;
 | 
			
		||||
               }
 | 
			
		||||
               else if (result.getAction() == WSConstants.SIGN)
 | 
			
		||||
               {
 | 
			
		||||
                  // A signature was processed, verify that the signature was over the timestamp
 | 
			
		||||
                  // and the body.
 | 
			
		||||
                  boolean timeStampSigned = false;
 | 
			
		||||
                  boolean bodySigned = false;
 | 
			
		||||
                  Set signedElements = result.getSignedElements();
 | 
			
		||||
                  for (Object signedElement : signedElements)
 | 
			
		||||
                  {
 | 
			
		||||
                     String elementId = (String) signedElement;
 | 
			
		||||
                     Element element = findElementById(signedDoc.getDocumentElement(), elementId, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
 | 
			
		||||
                     if (element != null)
 | 
			
		||||
                     {
 | 
			
		||||
                        if ("wsu:Timestamp".equalsIgnoreCase(element.getNodeName()))
 | 
			
		||||
                        {
 | 
			
		||||
                           timeStampSigned = true;
 | 
			
		||||
                        }
 | 
			
		||||
                        else if ("SOAP-ENV:Body".equalsIgnoreCase(element.getNodeName()))
 | 
			
		||||
                        {
 | 
			
		||||
                           bodySigned = true;
 | 
			
		||||
                        }
 | 
			
		||||
                     }
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
                  if (timeStampSigned && bodySigned)
 | 
			
		||||
                  {
 | 
			
		||||
                     signatureProcessed = true;
 | 
			
		||||
                  }
 | 
			
		||||
               }
 | 
			
		||||
            }
 | 
			
		||||
         }
 | 
			
		||||
 | 
			
		||||
         if (timeStampProcessed && signatureProcessed)
 | 
			
		||||
         {
 | 
			
		||||
            System.out.println("WSSecurity.verifyMessage() - Validation succeded");
 | 
			
		||||
            msgVerificationStatus = true;
 | 
			
		||||
         }
 | 
			
		||||
         else
 | 
			
		||||
         {
 | 
			
		||||
            System.out.println("WSSecurity.verifyMessage() - validation failed");
 | 
			
		||||
         }
 | 
			
		||||
      }
 | 
			
		||||
      catch (WSSecurityException e)
 | 
			
		||||
      {
 | 
			
		||||
         System.out.println("WSSecurity.verifyMessage() - Verification failed with error:" + e.getMessage() + " code = " + e.getErrorCode());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return msgVerificationStatus;
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Add timestamp and sign SOAP message in compliance with WS-Security.
 | 
			
		||||
    *
 | 
			
		||||
    * @param envelope               String containing a SOAP envelope
 | 
			
		||||
    * @param timeToLive             Value to set the timestamp timeToLive parameter in seconds
 | 
			
		||||
    * @param svcConfig              Service Config object
 | 
			
		||||
    * @return <code>Message</code>  Signed and timestamped SOAP message
 | 
			
		||||
    * @throws Exception on error
 | 
			
		||||
    */
 | 
			
		||||
   public static Message secureSOAPEnvelope(SOAPEnvelope envelope,
 | 
			
		||||
                                            int timeToLive,
 | 
			
		||||
                                            SvcConfig svcConfig) throws Exception
 | 
			
		||||
   {
 | 
			
		||||
      WSSecSignature signer = new WSSecSignature();
 | 
			
		||||
      signer.setUserInfo(svcConfig.getSetting(SvcConfig.KeyStoreUser),
 | 
			
		||||
                         svcConfig.getSetting(SvcConfig.KeyStorePwd));
 | 
			
		||||
      signer.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER); // Include X509 Cert in message
 | 
			
		||||
 | 
			
		||||
      Document doc = envelope.getAsDocument();
 | 
			
		||||
 | 
			
		||||
      WSSecHeader secHeader = new WSSecHeader();
 | 
			
		||||
      secHeader.insertSecurityHeader(doc);
 | 
			
		||||
 | 
			
		||||
      WSSecTimestamp timeStamper = new WSSecTimestamp();
 | 
			
		||||
      timeStamper.setTimeToLive(timeToLive);
 | 
			
		||||
      timeStamper.build(doc, secHeader);
 | 
			
		||||
 | 
			
		||||
      Vector<WSEncryptionPart> parts = new Vector<WSEncryptionPart>();
 | 
			
		||||
 | 
			
		||||
      String soapNamespace = doc.getDocumentElement().getNamespaceURI();
 | 
			
		||||
      WSEncryptionPart bodyPart = new WSEncryptionPart("Body", soapNamespace, "");
 | 
			
		||||
      parts.add(bodyPart);
 | 
			
		||||
 | 
			
		||||
      WSEncryptionPart timeStampPart = new WSEncryptionPart(timeStamper.getId());
 | 
			
		||||
      parts.add(timeStampPart);
 | 
			
		||||
 | 
			
		||||
      signer.setParts(parts);
 | 
			
		||||
 | 
			
		||||
      Document signedDoc = signer.build(doc, crypto, secHeader);
 | 
			
		||||
 | 
			
		||||
      // Convert the signed document into a SOAP message and return it.
 | 
			
		||||
      return toSOAPMessage(signedDoc);
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user