Implemented securing Authentication and Session Tokens using
WS-Security.
This commit is contained in:
		| @@ -265,6 +265,7 @@ package/linux/Makefile | ||||
| package/linux/CASA_auth_token_svc.spec | ||||
| server/Makefile | ||||
| server/Svc/Makefile | ||||
| server/Svc/external/Makefile | ||||
| server/Svc/src/Makefile | ||||
| server/Svc/src/com/Makefile | ||||
| server/Svc/src/com/novell/Makefile | ||||
|   | ||||
| @@ -20,7 +20,7 @@ | ||||
| ####################################################################### | ||||
|  | ||||
| SUBDIRS = src | ||||
| DIST_SUBDIRS = src | ||||
| DIST_SUBDIRS = src external | ||||
|  | ||||
| EXTRA_DIST = authtoken.settings \ | ||||
| 		identoken.settings \ | ||||
| @@ -34,6 +34,7 @@ ROOT = ../.. | ||||
| LIBDIR = $(ROOT)/$(LIB) | ||||
|  | ||||
| IDENT_ABSTRACTION_DIR = /usr/share/java/identity-abstraction | ||||
| AXIS_JARS_DIR = external | ||||
|  | ||||
| JAVAROOT = . | ||||
| JAVAC= javac | ||||
| @@ -50,6 +51,8 @@ JAVAFILES = src/com/novell/casa/authtoksvc/ProtoDefs.java \ | ||||
| 	src/com/novell/casa/authtoksvc/AuthTokenConfig.java \ | ||||
| 	src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java \ | ||||
| 	src/com/novell/casa/authtoksvc/AuthMechanism.java \ | ||||
| 	src/com/novell/casa/authtoksvc/WSSecurity.java \ | ||||
| 	src/com/novell/casa/authtoksvc/SessionToken.java \ | ||||
| 	src/com/novell/casa/authtoksvc/Authenticate.java \ | ||||
| 	src/com/novell/casa/authtoksvc/RpcMethod.java \ | ||||
| 	src/com/novell/casa/authtoksvc/Rpc.java \ | ||||
| @@ -66,8 +69,7 @@ JAVAFILES = src/com/novell/casa/authtoksvc/ProtoDefs.java \ | ||||
| 	src/com/novell/casa/authtoksvc/GetAuthTokReqMsg.java \ | ||||
| 	src/com/novell/casa/authtoksvc/GetAuthTokRespMsg.java \ | ||||
| 	src/com/novell/casa/authtoksvc/Krb5Authenticate.java \ | ||||
| 	src/com/novell/casa/authtoksvc/PwdAuthenticate.java \ | ||||
| 	src/com/novell/casa/authtoksvc/SessionToken.java | ||||
| 	src/com/novell/casa/authtoksvc/PwdAuthenticate.java | ||||
|  | ||||
| BUILDDIR = build | ||||
|  | ||||
| @@ -77,8 +79,12 @@ AUTHTOKEN_FILES = -C $(BUILDDIR)/webapp/WEB-INF/classes com | ||||
|  | ||||
| CLASSES = $(addprefix $(BUILDDIR)/, $(JAVAFILES:%.java=%.class)) | ||||
|  | ||||
| #AXIS_LIBS = $(AXIS_JARS_DIR)/axis.jar:$(AXIS_JARS_DIR)/axis-ant.jar:$(AXIS_JARS_DIR)/commons-discovery-0.2.jar:$(AXIS_JARS_DIR)/commons-logging-1.0.4.jar:$(AXIS_JARS_DIR)/commons-logging-api.jar:$(AXIS_JARS_DIR)/jaxrpc.jar:$(AXIS_JARS_DIR)/log4j-1.2.8.jar:$(AXIS_JARS_DIR)/saaj.jar:$(AXIS_JARS_DIR)/wsdl4j-1.5.1.jar:$(AXIS_JARS_DIR)/wss4j-1.5.0.jar:$(AXIS_JARS_DIR)/xalan.jar:$(AXIS_JARS_DIR)/xercesImpl.jar:$(AXIS_JARS_DIR)/xml-apis.jar:$(AXIS_JARS_DIR)/xmlsec-1.2.1.jar | ||||
| AXIS_LIBS = $(AXIS_JARS_DIR)/axis.jar:$(AXIS_JARS_DIR)/saaj.jar:$(AXIS_JARS_DIR)/wss4j-1.5.0.jar:$(AXIS_JARS_DIR)/xmlsec-1.2.1.jar | ||||
| #AXIS_LIBS = $(AXIS_JARS_DIR)/wss4j-1.5.0.jar | ||||
|  | ||||
| LIBS = /usr/share/java/servletapi5.jar | ||||
| CLASSPATH = $(IDENT_ABSTRACTION_DIR)/identity-abstraction.jar:$(LIBS) | ||||
| CLASSPATH = $(AXIS_LIBS):$(IDENT_ABSTRACTION_DIR)/identity-abstraction.jar:$(LIBS) | ||||
|  | ||||
| CUR_DIR := $(shell pwd) | ||||
|  | ||||
| @@ -98,6 +104,7 @@ $(BUILDDIR)/$(WEBAPP): $(BUILDDIR) $(CLASSES) | ||||
| 	cp src/com/novell/casa/authtoksvc/Pwd_mechanism.settings $(BUILDDIR)/webapp/WEB-INF/conf/installed_auth_mechanisms/PwdAuthenticate/mechanism.settings | ||||
| 	cp $(IDENT_ABSTRACTION_DIR)/*.jar $(BUILDDIR)/webapp/WEB-INF/lib/ | ||||
| 	rm $(BUILDDIR)/webapp/WEB-INF/lib/identity-abstraction.jar | ||||
| 	cp $(AXIS_JARS_DIR)/*.jar $(BUILDDIR)/webapp/WEB-INF/lib/ | ||||
| 	ls $(BUILDDIR)/webapp/WEB-INF/lib/ | ||||
| 	jar cvf $(BUILDDIR)/$(WEBAPP) -C $(BUILDDIR)/webapp . | ||||
| 	cp $(BUILDDIR)/$(WEBAPP) $(LIBDIR)/java/ | ||||
|   | ||||
| @@ -69,6 +69,8 @@ Thhe following is an example svc.settings file: | ||||
| 	<IAConfigFile>/home/jluciani/jakarta-tomcat-5.0.28/webapps/CasaAuthTokenSvc/WEB-INF/conf/iaRealms.xml</IAConfigFile> | ||||
| 	<ReconfigureInterval>60</ReconfigureInterval> | ||||
| 	<startSearchContext>o=novell</startSearchContext> | ||||
| 	<KeyStoreUser>privKey<KeyStoreUser> | ||||
| 	<KeyStorePwd>foobar<KeyStorePwd> | ||||
| </settings> | ||||
|  | ||||
| Note the following about the sample svc.settings file: | ||||
| @@ -102,6 +104,12 @@ Note the following about the sample svc.settings file: | ||||
|   from the root of the tree. This setting or an equivalent setting will be moved | ||||
|   to the identity abstraction configuration file where it belongs. Once this is done, | ||||
|   the setting will no longer be recognized within the svc.settings file.  | ||||
|  | ||||
| - The KeyStoreUses setting specifies the user's alias name in the keystore that identifies | ||||
|   the private key that is to be used to sign tokens. | ||||
|  | ||||
| - The KeyStorePwd setting specifies the password of the user specified by KeyStoreUser to get | ||||
|   the private signing key from the keystore. | ||||
|   | ||||
| CONFIGURING SERVICES TO CONSUME CASA AUTHENTICATION TOKENS | ||||
|  | ||||
|   | ||||
							
								
								
									
										52
									
								
								CASA-auth-token/java/server/Svc/external/Makefile.am
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								CASA-auth-token/java/server/Svc/external/Makefile.am
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| ####################################################################### | ||||
| # | ||||
| #  Copyright (C) 2006 Novell, Inc. | ||||
| # | ||||
| #  This program is free software; you can redistribute it and/or | ||||
| #  modify it under the terms of the GNU General Public | ||||
| #  License as published by the Free Software Foundation; either | ||||
| #  version 2 of the License, or (at your option) any later version. | ||||
| # | ||||
| #  This program 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 | ||||
| #  General Public License for more details. | ||||
| # | ||||
| #  You should have received a copy of the GNU General Public | ||||
| #  License along with this program; if not, write to the Free | ||||
| #  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| # | ||||
| #  Author: Juan Carlos Luciani <jluciani@novell.com> | ||||
| # | ||||
| ####################################################################### | ||||
|  | ||||
| SUBDIRS = | ||||
|  | ||||
| DIST_SUBDIRS = | ||||
|  | ||||
| CFILES = | ||||
|  | ||||
| EXTRA_DIST = axis.jar \ | ||||
| 		axis-ant.jar \ | ||||
| 		commons-discovery-0.2.jar \ | ||||
| 		commons-logging-1.0.4.jar \ | ||||
| 		commons-logging-api.jar \ | ||||
| 		jaxrpc.jar \ | ||||
| 		log4j.properties \ | ||||
| 		log4j-1.2.8.jar \ | ||||
| 		README \ | ||||
| 		saaj.jar \ | ||||
| 		wsdl4j-1.5.1.jar \ | ||||
| 		wss4j-1.5.0.jar \ | ||||
| 		xalan.jar \ | ||||
| 		xercesImpl.jar \ | ||||
| 		xml-apis.jar \ | ||||
| 		xmlsec-1.2.1.jar | ||||
|  | ||||
| .PHONY: package package-clean package-install package-uninstall | ||||
| package package-clean package-install package-uninstall: | ||||
| 	$(MAKE) -C $(TARGET_OS) $@ | ||||
|  | ||||
| maintainer-clean-local: | ||||
| 	rm -f Makefile.in | ||||
|  | ||||
							
								
								
									
										25
									
								
								CASA-auth-token/java/server/Svc/external/README
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								CASA-auth-token/java/server/Svc/external/README
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| The following describes the source of the files present in this folder. | ||||
|  | ||||
| axis-1_4 ----> axis-ant.jar | ||||
| axis-1_4 ----> axis.jar | ||||
| axis-1_4 ----> commons-discovery-0.2.jar | ||||
| axis-1_4 ----> commons-logging-1.0.4.jar | ||||
| xml-security-1_2_1 ----> commons-logging-api.jar | ||||
| axis-1_4 ----> jaxrpc.jar | ||||
| axis-1_4 ----> log4j-1.2.8.jar | ||||
| axis-1_4 ----> log4j.properties | ||||
| axis-1_4 ----> saaj.jar | ||||
| axis-1_4 ----> wsdl4j-1.5.1.jar | ||||
| wss4j-1.5 ----> wss4j-1.5.0.jar | ||||
| xml-security-1_2_1 ----> xalan.jar | ||||
| xml-security-1_2_1 ----> xercesImpl.jar | ||||
| xml-security-1_2_1 ----> xml-apis.jar | ||||
| xml-security-1_2_1 ----> xmlsec-1.2.1.jar | ||||
|  | ||||
| xml-security-1_2_1 - URL: http://xml.apache.org/security/dist/java-library/ - File: xml-security-bin-1_2_1.zip | ||||
|  | ||||
| axis-1_4 - URL: http://www.apache.org/dyn/closer.cgi/ws/axis/1_4 - File: axis-bin-1_4.tar.gz | ||||
|  | ||||
| wss4j-1.5 - URL: http://www.apache.org/dyn/dyn/closer.cgi/ws/wss4j/ - File: wss4j-bin-1.5.0.zip  | ||||
|  | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/axis-ant.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/axis-ant.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/axis.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/axis.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/commons-discovery-0.2.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/commons-discovery-0.2.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/commons-logging-1.0.4.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/commons-logging-1.0.4.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/commons-logging-api.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/commons-logging-api.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/jaxrpc.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/jaxrpc.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/log4j-1.2.8.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/log4j-1.2.8.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										20
									
								
								CASA-auth-token/java/server/Svc/external/log4j.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								CASA-auth-token/java/server/Svc/external/log4j.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| # Set root category priority to INFO and its only appender to CONSOLE. | ||||
| log4j.rootCategory=INFO, CONSOLE | ||||
| #log4j.rootCategory=INFO, CONSOLE, LOGFILE | ||||
|  | ||||
| # Set the enterprise logger category to FATAL and its only appender to CONSOLE. | ||||
| log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE | ||||
|  | ||||
| # CONSOLE is set to be a ConsoleAppender using a PatternLayout. | ||||
| log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender | ||||
| log4j.appender.CONSOLE.Threshold=INFO | ||||
| log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout | ||||
| log4j.appender.CONSOLE.layout.ConversionPattern=- %m%n | ||||
|  | ||||
| # LOGFILE is set to be a File appender using a PatternLayout. | ||||
| log4j.appender.LOGFILE=org.apache.log4j.FileAppender | ||||
| log4j.appender.LOGFILE.File=axis.log | ||||
| log4j.appender.LOGFILE.Append=true | ||||
| log4j.appender.LOGFILE.Threshold=INFO | ||||
| log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout | ||||
| log4j.appender.LOGFILE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n | ||||
							
								
								
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/saaj.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/saaj.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/wsdl4j-1.5.1.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/wsdl4j-1.5.1.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/wss4j-1.5.0.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/wss4j-1.5.0.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/xalan.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/xalan.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/xercesImpl.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/xercesImpl.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/xml-apis.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/xml-apis.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/xmlsec-1.2.1.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								CASA-auth-token/java/server/Svc/external/xmlsec-1.2.1.jar
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -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