Implemented securing Authentication and Session Tokens using
WS-Security.
This commit is contained in:
parent
2ec99203a2
commit
b06912c332
@ -265,6 +265,7 @@ package/linux/Makefile
|
|||||||
package/linux/CASA_auth_token_svc.spec
|
package/linux/CASA_auth_token_svc.spec
|
||||||
server/Makefile
|
server/Makefile
|
||||||
server/Svc/Makefile
|
server/Svc/Makefile
|
||||||
|
server/Svc/external/Makefile
|
||||||
server/Svc/src/Makefile
|
server/Svc/src/Makefile
|
||||||
server/Svc/src/com/Makefile
|
server/Svc/src/com/Makefile
|
||||||
server/Svc/src/com/novell/Makefile
|
server/Svc/src/com/novell/Makefile
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
SUBDIRS = src
|
SUBDIRS = src
|
||||||
DIST_SUBDIRS = src
|
DIST_SUBDIRS = src external
|
||||||
|
|
||||||
EXTRA_DIST = authtoken.settings \
|
EXTRA_DIST = authtoken.settings \
|
||||||
identoken.settings \
|
identoken.settings \
|
||||||
@ -34,6 +34,7 @@ ROOT = ../..
|
|||||||
LIBDIR = $(ROOT)/$(LIB)
|
LIBDIR = $(ROOT)/$(LIB)
|
||||||
|
|
||||||
IDENT_ABSTRACTION_DIR = /usr/share/java/identity-abstraction
|
IDENT_ABSTRACTION_DIR = /usr/share/java/identity-abstraction
|
||||||
|
AXIS_JARS_DIR = external
|
||||||
|
|
||||||
JAVAROOT = .
|
JAVAROOT = .
|
||||||
JAVAC= javac
|
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/AuthTokenConfig.java \
|
||||||
src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java \
|
src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java \
|
||||||
src/com/novell/casa/authtoksvc/AuthMechanism.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/Authenticate.java \
|
||||||
src/com/novell/casa/authtoksvc/RpcMethod.java \
|
src/com/novell/casa/authtoksvc/RpcMethod.java \
|
||||||
src/com/novell/casa/authtoksvc/Rpc.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/GetAuthTokReqMsg.java \
|
||||||
src/com/novell/casa/authtoksvc/GetAuthTokRespMsg.java \
|
src/com/novell/casa/authtoksvc/GetAuthTokRespMsg.java \
|
||||||
src/com/novell/casa/authtoksvc/Krb5Authenticate.java \
|
src/com/novell/casa/authtoksvc/Krb5Authenticate.java \
|
||||||
src/com/novell/casa/authtoksvc/PwdAuthenticate.java \
|
src/com/novell/casa/authtoksvc/PwdAuthenticate.java
|
||||||
src/com/novell/casa/authtoksvc/SessionToken.java
|
|
||||||
|
|
||||||
BUILDDIR = build
|
BUILDDIR = build
|
||||||
|
|
||||||
@ -77,8 +79,12 @@ AUTHTOKEN_FILES = -C $(BUILDDIR)/webapp/WEB-INF/classes com
|
|||||||
|
|
||||||
CLASSES = $(addprefix $(BUILDDIR)/, $(JAVAFILES:%.java=%.class))
|
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
|
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)
|
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 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/
|
cp $(IDENT_ABSTRACTION_DIR)/*.jar $(BUILDDIR)/webapp/WEB-INF/lib/
|
||||||
rm $(BUILDDIR)/webapp/WEB-INF/lib/identity-abstraction.jar
|
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/
|
ls $(BUILDDIR)/webapp/WEB-INF/lib/
|
||||||
jar cvf $(BUILDDIR)/$(WEBAPP) -C $(BUILDDIR)/webapp .
|
jar cvf $(BUILDDIR)/$(WEBAPP) -C $(BUILDDIR)/webapp .
|
||||||
cp $(BUILDDIR)/$(WEBAPP) $(LIBDIR)/java/
|
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>
|
<IAConfigFile>/home/jluciani/jakarta-tomcat-5.0.28/webapps/CasaAuthTokenSvc/WEB-INF/conf/iaRealms.xml</IAConfigFile>
|
||||||
<ReconfigureInterval>60</ReconfigureInterval>
|
<ReconfigureInterval>60</ReconfigureInterval>
|
||||||
<startSearchContext>o=novell</startSearchContext>
|
<startSearchContext>o=novell</startSearchContext>
|
||||||
|
<KeyStoreUser>privKey<KeyStoreUser>
|
||||||
|
<KeyStorePwd>foobar<KeyStorePwd>
|
||||||
</settings>
|
</settings>
|
||||||
|
|
||||||
Note the following about the sample svc.settings file:
|
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
|
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,
|
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 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
|
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;
|
m_state = AWAITING_REALM_ELEMENT_END;
|
||||||
break;
|
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:
|
case AWAITING_MECH_DATA:
|
||||||
// Consume the data
|
// Consume the data
|
||||||
m_authReqMsg.m_authMechanism = new String(ch, start, length);
|
m_authReqMsg.m_authMechanism = new String(ch, start, length);
|
||||||
@ -264,6 +269,11 @@ public class AuthReqMsg
|
|||||||
m_state = AWAITING_MECH_ELEMENT_END;
|
m_state = AWAITING_MECH_ELEMENT_END;
|
||||||
break;
|
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:
|
case AWAITING_AUTH_MECH_TOKEN_DATA:
|
||||||
// Consume the data
|
// Consume the data
|
||||||
m_authReqMsg.m_authMechToken = new String(ch, start, length);
|
m_authReqMsg.m_authMechToken = new String(ch, start, length);
|
||||||
@ -272,6 +282,11 @@ public class AuthReqMsg
|
|||||||
m_state = AWAITING_AUTH_MECH_TOKEN_ELEMENT_END;
|
m_state = AWAITING_AUTH_MECH_TOKEN_ELEMENT_END;
|
||||||
break;
|
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:
|
default:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
|
@ -26,20 +26,26 @@ package com.novell.casa.authtoksvc;
|
|||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
|
||||||
import org.xml.sax.InputSource;
|
import org.apache.axis.Message;
|
||||||
import org.xml.sax.SAXException;
|
import org.apache.axis.MessageContext;
|
||||||
import org.xml.sax.XMLReader;
|
import org.apache.axis.client.AxisClient;
|
||||||
import org.xml.sax.helpers.XMLReaderFactory;
|
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.
|
* AuthToken Class.
|
||||||
*
|
*
|
||||||
* This class constructs authentication tokens that clients can present
|
* This class constructs authentication tokens that clients can present
|
||||||
* to services for authentication. The format of the authentication token
|
* to services for authentication. The authentication token consists of
|
||||||
* is as follows:
|
* a SOAP message secured with WSSecurity with the appropriate elements signed
|
||||||
*
|
* and with a timestamp. The body of the SOAP message is as follows:
|
||||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
*
|
||||||
* <auth_token>
|
* <auth_token>
|
||||||
* <signature>signature value</signature>
|
* <signature>signature value</signature>
|
||||||
* <lifetime>lifetime value</lifetime>
|
* <lifetime>lifetime value</lifetime>
|
||||||
@ -51,280 +57,23 @@ public class AuthToken
|
|||||||
{
|
{
|
||||||
|
|
||||||
private String m_token;
|
private String m_token;
|
||||||
private String m_lifetime;
|
private String m_lifetime = "";
|
||||||
private String m_lifetimeShorter;
|
private String m_lifetimeShorter = "";
|
||||||
private String m_identityTokenType;
|
private String m_identityTokenType = null;
|
||||||
private StringBuffer m_identityToken;
|
private String m_identityToken = null;
|
||||||
private String m_signature;
|
|
||||||
|
|
||||||
/*
|
static final String authTokenSoapMsg =
|
||||||
* Class for handling parsing events.
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
||||||
*/
|
"<SOAP-ENV:Envelope" +
|
||||||
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
|
" xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\"\n" +
|
||||||
{
|
" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" +
|
||||||
private final static int AWAITING_ROOT_ELEMENT_START = 0;
|
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
||||||
private final static int AWAITING_ROOT_ELEMENT_END = 1;
|
" <SOAP-ENV:Body>" +
|
||||||
private final static int AWAITING_SIGNATURE_ELEMENT_START = 2;
|
" <auth_token><ident_token><type></type></ident_token></auth_token>" +
|
||||||
private final static int AWAITING_SIGNATURE_ELEMENT_END = 3;
|
" </SOAP-ENV:Body>" +
|
||||||
private final static int AWAITING_SIGNATURE_DATA = 4;
|
"</SOAP-ENV:Envelope>";
|
||||||
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;
|
|
||||||
|
|
||||||
private AuthToken m_AuthToken;
|
static final private MessageContext axisMsgContext = new MessageContext(new AxisClient(new NullProvider()));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@ -354,37 +103,28 @@ public class AuthToken
|
|||||||
targetHost,
|
targetHost,
|
||||||
svcConfig);
|
svcConfig);
|
||||||
|
|
||||||
m_identityToken = new StringBuffer();
|
m_identityToken = identityToken.getEncodedToken();
|
||||||
m_identityToken.append(identityToken.getEncodedToken());
|
|
||||||
m_identityTokenType = identityToken.getProviderType();
|
m_identityTokenType = identityToken.getProviderType();
|
||||||
|
|
||||||
m_lifetime = authTokenConfig.getSetting(AuthTokenConfig.TokenLifetime);
|
m_lifetime = authTokenConfig.getSetting(AuthTokenConfig.TokenLifetime);
|
||||||
m_lifetimeShorter = authTokenConfig.getSetting(AuthTokenConfig.LifetimeShorter);
|
m_lifetimeShorter = authTokenConfig.getSetting(AuthTokenConfig.LifetimeShorter);
|
||||||
|
|
||||||
// Generate a signature
|
// Create AuthTokenMessage
|
||||||
// tbd - Over identToken, identToken type, and lifetime data.
|
Message authTokenMessage = getMessage(identityToken.getEncodedToken(),
|
||||||
m_signature = "tbd";
|
identityToken.getProviderType(),
|
||||||
|
Integer.valueOf(m_lifetime).intValue(),
|
||||||
|
svcConfig);
|
||||||
|
|
||||||
// Get a StringBuffer to help us with the construction of the token
|
// Now save the message as a string
|
||||||
StringBuffer sb = new StringBuffer();
|
OutputStream outStream = new ByteArrayOutputStream();
|
||||||
|
authTokenMessage.writeTo(outStream);
|
||||||
// Start building the message
|
m_token = outStream.toString();
|
||||||
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
|
outStream.close();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
// tbd
|
// tbd
|
||||||
System.err.println("AuthToken()- Exception: " + e.toString());
|
System.err.println("AuthToken()- Exception: " + e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -402,33 +142,102 @@ public class AuthToken
|
|||||||
// Decode the token string
|
// Decode the token string
|
||||||
m_token = Base64Coder.decode(token);
|
m_token = Base64Coder.decode(token);
|
||||||
|
|
||||||
// Instantiate string buffer for the identity token
|
// Now instantiate a SOAP message with the string
|
||||||
m_identityToken = new StringBuffer();
|
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
|
try
|
||||||
{
|
{
|
||||||
// Parse the AuthToken
|
// Build SOAP Message with an identity token in the body
|
||||||
XMLReader xr = XMLReaderFactory.createXMLReader();
|
//
|
||||||
SAXHandler handler = new SAXHandler(this);
|
// First create a message and obtain its body
|
||||||
xr.setContentHandler(handler);
|
InputStream inStream = new ByteArrayInputStream(authTokenSoapMsg.getBytes());
|
||||||
xr.setErrorHandler(handler);
|
Message message = new Message(inStream);
|
||||||
|
message.setMessageContext(axisMsgContext);
|
||||||
|
SOAPBody body = (SOAPBody) message.getSOAPBody();
|
||||||
|
|
||||||
ByteArrayInputStream inStream = new ByteArrayInputStream(m_token.getBytes());
|
// Get access to the auth_token element
|
||||||
InputSource source = new InputSource(inStream);
|
QName authTokenElementName = new QName("auth_token");
|
||||||
xr.parse(source);
|
MessageElement authTokenElement = body.getChildElement(authTokenElementName);
|
||||||
|
|
||||||
// Verify the signature
|
// Get access to the ident_token element and set its value
|
||||||
// tbd
|
QName identTokenElementName = new QName("ident_token");
|
||||||
|
MessageElement identTokenElement = authTokenElement.getChildElement(identTokenElementName);
|
||||||
|
identTokenElement.addTextNode(identityToken);
|
||||||
|
|
||||||
// Verify that the token has not expired
|
// Get access to the identity token type element element and set its value
|
||||||
// tbd
|
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());
|
System.out.println("AuthToken.getMessage() - Exception caught building message, error: " + e.getMessage());
|
||||||
throw new Exception("Protocol error");
|
secureMessage = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return secureMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -441,11 +250,20 @@ public class AuthToken
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the lifetime of the token.
|
* 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
|
// Throw exeption if the lifetime parameter is not set
|
||||||
return "60";
|
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()
|
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.
|
// An identity was resolved, get a SessionToken for it.
|
||||||
SessionToken sessionToken = new SessionToken(identId,
|
SessionToken sessionToken = new SessionToken(identId,
|
||||||
authReqMsg.getRealm(),
|
authReqMsg.getRealm(),
|
||||||
m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime));
|
m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime),
|
||||||
|
m_svcConfig);
|
||||||
|
|
||||||
// Write out the response
|
// 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,
|
AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpOkStatusMsg,
|
||||||
ProtoDefs.httpOkStatusCode,
|
ProtoDefs.httpOkStatusCode,
|
||||||
sessionToken.toString(),
|
sessionToken.toString(),
|
||||||
m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime));
|
respLifetime);
|
||||||
// tbd - Convert to ints, perform calculation, and then convert result to string
|
|
||||||
//m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime)
|
|
||||||
//- m_svcConfig.getSetting(SvcConfig.LifetimeShorter));
|
|
||||||
out.println(authRespMsg.toString());
|
out.println(authRespMsg.toString());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -102,7 +102,6 @@ public class GetAuthPolicyReqMsg
|
|||||||
// Proceed based on our state
|
// Proceed based on our state
|
||||||
switch (m_state)
|
switch (m_state)
|
||||||
{
|
{
|
||||||
|
|
||||||
case AWAITING_ROOT_ELEMENT_START:
|
case AWAITING_ROOT_ELEMENT_START:
|
||||||
// Verify that we are processing the expected tag
|
// Verify that we are processing the expected tag
|
||||||
if (ProtoDefs.getAuthPolicyRequestElementName.equals(qName))
|
if (ProtoDefs.getAuthPolicyRequestElementName.equals(qName))
|
||||||
@ -160,7 +159,6 @@ public class GetAuthPolicyReqMsg
|
|||||||
// Proceed based on our state
|
// Proceed based on our state
|
||||||
switch (m_state)
|
switch (m_state)
|
||||||
{
|
{
|
||||||
|
|
||||||
case AWAITING_ROOT_ELEMENT_END:
|
case AWAITING_ROOT_ELEMENT_END:
|
||||||
// Verify that we are processing the expected tag
|
// Verify that we are processing the expected tag
|
||||||
if (ProtoDefs.getAuthPolicyRequestElementName.equals(qName))
|
if (ProtoDefs.getAuthPolicyRequestElementName.equals(qName))
|
||||||
@ -217,7 +215,6 @@ public class GetAuthPolicyReqMsg
|
|||||||
// Proceed based on our state
|
// Proceed based on our state
|
||||||
switch (m_state)
|
switch (m_state)
|
||||||
{
|
{
|
||||||
|
|
||||||
case AWAITING_SERVICE_DATA:
|
case AWAITING_SERVICE_DATA:
|
||||||
// Consume the data
|
// Consume the data
|
||||||
m_GetAuthPolicyReqMsg.m_serviceName = new String(ch, start, length);
|
m_GetAuthPolicyReqMsg.m_serviceName = new String(ch, start, length);
|
||||||
@ -226,6 +223,11 @@ public class GetAuthPolicyReqMsg
|
|||||||
m_state = AWAITING_SERVICE_ELEMENT_END;
|
m_state = AWAITING_SERVICE_ELEMENT_END;
|
||||||
break;
|
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:
|
case AWAITING_HOST_DATA:
|
||||||
// Consume the data
|
// Consume the data
|
||||||
m_GetAuthPolicyReqMsg.m_hostName = new String(ch, start, length);
|
m_GetAuthPolicyReqMsg.m_hostName = new String(ch, start, length);
|
||||||
@ -234,6 +236,11 @@ public class GetAuthPolicyReqMsg
|
|||||||
m_state = AWAITING_HOST_ELEMENT_END;
|
m_state = AWAITING_HOST_ELEMENT_END;
|
||||||
break;
|
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:
|
default:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
|
@ -107,7 +107,6 @@ public class GetAuthTokReqMsg
|
|||||||
// Proceed based on our state
|
// Proceed based on our state
|
||||||
switch (m_state)
|
switch (m_state)
|
||||||
{
|
{
|
||||||
|
|
||||||
case AWAITING_ROOT_ELEMENT_START:
|
case AWAITING_ROOT_ELEMENT_START:
|
||||||
// Verify that we are processing the expected tag
|
// Verify that we are processing the expected tag
|
||||||
if (ProtoDefs.getAuthTokRequestElementName.equals(qName))
|
if (ProtoDefs.getAuthTokRequestElementName.equals(qName))
|
||||||
@ -179,7 +178,6 @@ public class GetAuthTokReqMsg
|
|||||||
// Proceed based on our state
|
// Proceed based on our state
|
||||||
switch (m_state)
|
switch (m_state)
|
||||||
{
|
{
|
||||||
|
|
||||||
case AWAITING_ROOT_ELEMENT_END:
|
case AWAITING_ROOT_ELEMENT_END:
|
||||||
// Verify that we are processing the expected tag
|
// Verify that we are processing the expected tag
|
||||||
if (ProtoDefs.getAuthTokRequestElementName.equals(qName))
|
if (ProtoDefs.getAuthTokRequestElementName.equals(qName))
|
||||||
@ -250,7 +248,6 @@ public class GetAuthTokReqMsg
|
|||||||
// Proceed based on our state
|
// Proceed based on our state
|
||||||
switch (m_state)
|
switch (m_state)
|
||||||
{
|
{
|
||||||
|
|
||||||
case AWAITING_SERVICE_DATA:
|
case AWAITING_SERVICE_DATA:
|
||||||
// Consume the data
|
// Consume the data
|
||||||
m_GetAuthTokReqMsg.m_serviceName = new String(ch, start, length);
|
m_GetAuthTokReqMsg.m_serviceName = new String(ch, start, length);
|
||||||
@ -259,6 +256,11 @@ public class GetAuthTokReqMsg
|
|||||||
m_state = AWAITING_SERVICE_ELEMENT_END;
|
m_state = AWAITING_SERVICE_ELEMENT_END;
|
||||||
break;
|
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:
|
case AWAITING_HOST_DATA:
|
||||||
// Consume the data
|
// Consume the data
|
||||||
m_GetAuthTokReqMsg.m_hostName = new String(ch, start, length);
|
m_GetAuthTokReqMsg.m_hostName = new String(ch, start, length);
|
||||||
@ -267,6 +269,11 @@ public class GetAuthTokReqMsg
|
|||||||
m_state = AWAITING_HOST_ELEMENT_END;
|
m_state = AWAITING_HOST_ELEMENT_END;
|
||||||
break;
|
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:
|
case AWAITING_SESSION_TOKEN_DATA:
|
||||||
// Consume the data
|
// Consume the data
|
||||||
m_GetAuthTokReqMsg.m_sessionToken = new String(ch, start, length);
|
m_GetAuthTokReqMsg.m_sessionToken = new String(ch, start, length);
|
||||||
@ -275,6 +282,11 @@ public class GetAuthTokReqMsg
|
|||||||
m_state = AWAITING_SESSION_TOKEN_ELEMENT_END;
|
m_state = AWAITING_SESSION_TOKEN_ELEMENT_END;
|
||||||
break;
|
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:
|
default:
|
||||||
// Do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
|
@ -48,7 +48,8 @@ JAVAFILES = ProtoDefs.java \
|
|||||||
GetAuthTokRespMsg.java \
|
GetAuthTokRespMsg.java \
|
||||||
Krb5Authenticate.java \
|
Krb5Authenticate.java \
|
||||||
PwdAuthenticate.java \
|
PwdAuthenticate.java \
|
||||||
SessionToken.java
|
SessionToken.java \
|
||||||
|
WSSecurity.java
|
||||||
|
|
||||||
EXTRA_DIST = $(JAVAFILES) \
|
EXTRA_DIST = $(JAVAFILES) \
|
||||||
Krb5_mechanism.settings \
|
Krb5_mechanism.settings \
|
||||||
|
@ -26,20 +26,26 @@ package com.novell.casa.authtoksvc;
|
|||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
|
||||||
import org.xml.sax.InputSource;
|
import org.apache.axis.Message;
|
||||||
import org.xml.sax.SAXException;
|
import org.apache.axis.MessageContext;
|
||||||
import org.xml.sax.XMLReader;
|
import org.apache.axis.client.AxisClient;
|
||||||
import org.xml.sax.helpers.XMLReaderFactory;
|
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.
|
* SessionToken class.
|
||||||
*
|
*
|
||||||
* This class constructs session tokens that Casa clients can present to
|
* This class constructs sessions tokens that clients can present to an ATS
|
||||||
* the Casa server to prove that an entity has been authenticated to
|
* to prove that an entity has been authenticated to a particular realm.
|
||||||
* a particular realm. The format of the session token is as follows:
|
* The session token consists of a SOAP message secured with WSSecurity
|
||||||
*
|
* with the appropriate elements signed and with a timestamp. The body of
|
||||||
* <?xml version="1.0" encoding="ISO-8859-1"?>
|
* the SOAP message is as follows:
|
||||||
|
*
|
||||||
* <session_token>
|
* <session_token>
|
||||||
* <signature>signature value</signature>
|
* <signature>signature value</signature>
|
||||||
* <lifetime>lifetime value</lifetime>
|
* <lifetime>lifetime value</lifetime>
|
||||||
@ -51,308 +57,47 @@ import org.xml.sax.helpers.XMLReaderFactory;
|
|||||||
public class SessionToken
|
public class SessionToken
|
||||||
{
|
{
|
||||||
|
|
||||||
private String m_id;
|
private String m_id = null;
|
||||||
private String m_realm;
|
private String m_realm = null;
|
||||||
private String m_lifetime;
|
|
||||||
private String m_signature;
|
|
||||||
private String m_token;
|
private String m_token;
|
||||||
|
|
||||||
/*
|
static final String sessionTokenSoapMsg =
|
||||||
* Class for handling parsing events.
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
||||||
*/
|
"<SOAP-ENV:Envelope" +
|
||||||
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
|
" xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\"\n" +
|
||||||
{
|
" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" +
|
||||||
private final static int AWAITING_ROOT_ELEMENT_START = 0;
|
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
||||||
private final static int AWAITING_ROOT_ELEMENT_END = 1;
|
" <SOAP-ENV:Body>" +
|
||||||
private final static int AWAITING_SIGNATURE_ELEMENT_START = 2;
|
" <session_token><realm></realm><ident_id></ident_id></session_token>" +
|
||||||
private final static int AWAITING_SIGNATURE_ELEMENT_END = 3;
|
" </SOAP-ENV:Body>" +
|
||||||
private final static int AWAITING_SIGNATURE_DATA = 4;
|
"</SOAP-ENV:Envelope>";
|
||||||
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;
|
|
||||||
|
|
||||||
private SessionToken m_SessionToken;
|
static final private MessageContext axisMsgContext = new MessageContext(new AxisClient(new NullProvider()));
|
||||||
private int m_state;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
* 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
|
// Save copies of the input parameters
|
||||||
m_id = id;
|
m_id = id;
|
||||||
m_realm = realm;
|
m_realm = realm;
|
||||||
m_lifetime = lifetime;
|
|
||||||
|
|
||||||
// Generate a signature
|
// Create SessionTokenMessage
|
||||||
// tbd - Over id, realm, and lifetime data.
|
Message sessionTokenMessage = getMessage(realm,
|
||||||
m_signature = "tbd";
|
id,
|
||||||
|
Integer.valueOf(lifetime).intValue(),
|
||||||
|
svcConfig);
|
||||||
|
|
||||||
// Get a StringBuffer to help us with the construction of the token
|
// Now save the message as a string
|
||||||
StringBuffer sb = new StringBuffer();
|
OutputStream outStream = new ByteArrayOutputStream();
|
||||||
|
sessionTokenMessage.writeTo(outStream);
|
||||||
// Start building the message
|
m_token = outStream.toString();
|
||||||
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
|
outStream.close();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -364,30 +109,102 @@ public class SessionToken
|
|||||||
// Decode the token string
|
// Decode the token string
|
||||||
m_token = Base64Coder.decode(token);
|
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
|
try
|
||||||
{
|
{
|
||||||
// Parse the SessionToken
|
// Build SOAP Message with an identity token in the body
|
||||||
XMLReader xr = XMLReaderFactory.createXMLReader();
|
//
|
||||||
SAXHandler handler = new SAXHandler(this);
|
// First create a message and obtain its body
|
||||||
xr.setContentHandler(handler);
|
InputStream inStream = new ByteArrayInputStream(sessionTokenSoapMsg.getBytes());
|
||||||
xr.setErrorHandler(handler);
|
Message message = new Message(inStream);
|
||||||
|
message.setMessageContext(axisMsgContext);
|
||||||
|
SOAPBody body = (SOAPBody) message.getSOAPBody();
|
||||||
|
|
||||||
ByteArrayInputStream inStream = new ByteArrayInputStream(m_token.getBytes());
|
// Get access to the session_token element
|
||||||
InputSource source = new InputSource(inStream);
|
QName sessionTokenElementName = new QName("session_token");
|
||||||
xr.parse(source);
|
MessageElement sessionTokenElement = body.getChildElement(sessionTokenElementName);
|
||||||
|
|
||||||
// Verify the signature
|
// Get access to the realm element and set its value
|
||||||
// tbd
|
QName realmElementName = new QName("realm");
|
||||||
|
MessageElement realmElement = sessionTokenElement.getChildElement(realmElementName);
|
||||||
|
realmElement.addTextNode(realm);
|
||||||
|
|
||||||
// Verify that the token has not expired
|
// Get access to the ident_id element and set its value
|
||||||
// tbd
|
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());
|
System.out.println("SessionToken.getMessage() - Exception caught building message, error: " + e.getMessage());
|
||||||
throw new Exception("Protocol error");
|
secureMessage = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return secureMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -53,6 +53,8 @@ public class SvcConfig
|
|||||||
public final static String ConfigFolderPath = "ConfigFolderPath";
|
public final static String ConfigFolderPath = "ConfigFolderPath";
|
||||||
public final static String AppRootPath = "AppRootPath";
|
public final static String AppRootPath = "AppRootPath";
|
||||||
public final static String ReconfigureInterval = "ReconfigureInterval";
|
public final static String ReconfigureInterval = "ReconfigureInterval";
|
||||||
|
public final static String KeyStoreUser = "KeyStoreUser";
|
||||||
|
public final static String KeyStorePwd = "KeyStorePwd";
|
||||||
|
|
||||||
// Default configuration values
|
// Default configuration values
|
||||||
public final static String DefaultSessionTokenLifetimeValue = "43200"; // Seconds
|
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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user