diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthMechanism.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthMechanism.java new file mode 100644 index 00000000..cc89181b --- /dev/null +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthMechanism.java @@ -0,0 +1,49 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +/* + * AuthMechanism Interface. + * + * This is the interface implemented by Authentication Mechanisms. + */ +public interface AuthMechanism +{ + /* + * Initialize the authentication mechanism. + */ + void init(SvcConfig svcConfig) throws Exception; + + /* + * Process authenticate request. If successful, return the Id of the + * authenticated identity. + */ + String invoke(AuthReqMsg authReqMsg) throws Exception; + + /* + * Return the mechanism id. + */ + String getId(); +} diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthReqMsg.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthReqMsg.java index 2a501fdd..c220efd0 100644 --- a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthReqMsg.java +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthReqMsg.java @@ -42,6 +42,7 @@ import org.xml.sax.helpers.XMLReaderFactory; * * * realm value + * mechanism id * mechanism token data * * @@ -51,6 +52,7 @@ public class AuthReqMsg protected String m_realm = null; protected String m_authMechToken = null; + protected String m_authMechanism = null; /* * Class for handling Authentication Request parsing events. @@ -62,13 +64,16 @@ public class AuthReqMsg private final static int AWAITING_REALM_ELEMENT_START = 2; private final static int AWAITING_REALM_ELEMENT_END = 3; private final static int AWAITING_REALM_DATA = 4; - private final static int AWAITING_AUTH_MECH_TOKEN_ELEMENT_START = 5; - private final static int AWAITING_AUTH_MECH_TOKEN_ELEMENT_END = 6; - private final static int AWAITING_AUTH_MECH_TOKEN_DATA = 7; - private final static int DONE_PARSING = 8; + private final static int AWAITING_MECH_ELEMENT_START = 5; + private final static int AWAITING_MECH_ELEMENT_END = 6; + private final static int AWAITING_MECH_DATA = 7; + private final static int AWAITING_AUTH_MECH_TOKEN_ELEMENT_START = 8; + private final static int AWAITING_AUTH_MECH_TOKEN_ELEMENT_END = 9; + private final static int AWAITING_AUTH_MECH_TOKEN_DATA = 10; + private final static int DONE_PARSING = 11; - private AuthReqMsg m_authReqMsg; - private int m_state; + private AuthReqMsg m_authReqMsg; + private int m_state; /* * Constructor @@ -103,7 +108,6 @@ public class AuthReqMsg // Proceed based on our state switch (m_state) { - case AWAITING_ROOT_ELEMENT_START: // Verify that we are processing the expected tag if (ProtoDefs.authRequestElementName.equals(qName)) @@ -132,6 +136,20 @@ public class AuthReqMsg } break; + case AWAITING_MECH_ELEMENT_START: + // Verify that we are processing the expected tag + if (ProtoDefs.mechanismElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_MECH_DATA; + } + else + { + System.err.println("AuthReqMsg SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + case AWAITING_AUTH_MECH_TOKEN_ELEMENT_START: // Verify that we are processing the expected tag if (ProtoDefs.authMechTokenElementName.equals(qName)) @@ -160,7 +178,6 @@ public class AuthReqMsg // Proceed based on our state switch (m_state) { - case AWAITING_ROOT_ELEMENT_END: // Verify that we are processing the expected tag if (ProtoDefs.authRequestElementName.equals(qName)) @@ -178,6 +195,20 @@ public class AuthReqMsg 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_MECH_ELEMENT_START; + } + else + { + System.err.println("AuthReqMsg SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_MECH_ELEMENT_END: + // Verify that we are processing the expected tag + if (ProtoDefs.mechanismElementName.equals(qName)) { // Advance to the next state m_state = AWAITING_AUTH_MECH_TOKEN_ELEMENT_START; @@ -217,7 +248,6 @@ public class AuthReqMsg // Proceed based on our state switch (m_state) { - case AWAITING_REALM_DATA: // Consume the data m_authReqMsg.m_realm = new String(ch, start, length); @@ -226,6 +256,14 @@ public class AuthReqMsg m_state = AWAITING_REALM_ELEMENT_END; break; + case AWAITING_MECH_DATA: + // Consume the data + m_authReqMsg.m_authMechanism = new String(ch, start, length); + + // Advance to the next state + m_state = AWAITING_MECH_ELEMENT_END; + break; + case AWAITING_AUTH_MECH_TOKEN_DATA: // Consume the data m_authReqMsg.m_authMechToken = new String(ch, start, length); @@ -279,4 +317,12 @@ public class AuthReqMsg { return m_authMechToken; } + + /* + * Method to get the authentication mechanism id. + */ + public String getMechanismId() throws Exception + { + return m_authMechanism; + } } diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthToken.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthToken.java index f4512d1b..b081ea8a 100644 --- a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthToken.java +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthToken.java @@ -52,6 +52,7 @@ 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; @@ -328,58 +329,67 @@ public class AuthToken /* * Constructor. */ - public AuthToken ( - String identityId, + public AuthToken(String identityId, String realm, String targetService, - String targetHost) throws Exception + String targetHost, + SvcConfig svcConfig, + EnabledSvcsConfig enabledSvcsConfig) throws Exception { - try + // Get access to the authentication token configuration for this service + AuthTokenConfig authTokenConfig = enabledSvcsConfig.getAuthTokenConfig(targetHost, targetService); + if (authTokenConfig != null) { - // Verify that we have support for the specified service. - // tbd + try + { + // For now lets use the services of the only IdentityToken provider + // that we have. + // + // tbd - Add code to allow for the consumption of tokens + // from different providers. + CasaIdentityToken identityToken = new CasaIdentityToken(enabledSvcsConfig.getIdenTokenConfig(targetHost, targetService)); + identityToken.initialize(identityId, + realm, + targetService, + targetHost, + svcConfig); - // For now lets use the services of the only IdentityToken provider - // that we have. - // - // tbd - Add code to allow for the consumption of tokens - // from different providers. - CasaIdentityToken identityToken = new CasaIdentityToken(); - identityToken.initialize(identityId, - realm, - targetService, - targetHost); + m_identityToken = new StringBuffer(); + m_identityToken.append(identityToken.getEncodedToken()); + m_identityTokenType = identityToken.getProviderType(); - m_identityToken = new StringBuffer(); - m_identityToken.append(identityToken.getEncodedToken()); - m_identityTokenType = identityToken.getProviderType(); + m_lifetime = authTokenConfig.getSetting(AuthTokenConfig.TokenLifetime); + m_lifetimeShorter = authTokenConfig.getSetting(AuthTokenConfig.LifetimeShorter); - m_lifetime = "56"; // tbd + // Generate a signature + // tbd - Over identToken, identToken type, and lifetime data. + m_signature = "tbd"; - // Generate a signature - // tbd - Over identToken, identToken type, and lifetime data. - m_signature = "tbd"; + // Get a StringBuffer to help us with the construction of the token + StringBuffer sb = new StringBuffer(); - // 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 + "" + "\r\n"); + sb.append("<" + ProtoDefs.lifetimeElementName + ">" + m_lifetime + "" + "\r\n"); + sb.append("<" + ProtoDefs.identTokenElementName + ">" + + "<" + ProtoDefs.typeElementName + ">" + m_identityTokenType + "" + + m_identityToken + "" + "\r\n"); + sb.append("" + "\r\n"); - // Start building the message - sb.append(ProtoDefs.xmlDeclaration + "\r\n"); - sb.append("<" + ProtoDefs.authTokenElementName + ">" + "\r\n"); - sb.append("<" + ProtoDefs.signatureElementName + ">" + m_signature + "" + "\r\n"); - sb.append("<" + ProtoDefs.lifetimeElementName + ">" + m_lifetime + "" + "\r\n"); - sb.append("<" + ProtoDefs.identTokenElementName + ">" - + "<" + ProtoDefs.typeElementName + ">" + m_identityTokenType + "" - + m_identityToken + "" + "\r\n"); - sb.append("" + "\r\n"); - - // Save the token - m_token = sb.toString(); + // Save the token + m_token = sb.toString(); + } + catch (Exception e) + { + // tbd + System.err.println("AuthToken()- Exception: " + e.toString()); + } } - catch (Exception e) + else { - // tbd - System.err.println("AuthToken()- Exception: " + e.toString()); + throw new Exception("Error: Missing authentication token config for " + targetService); } } @@ -434,7 +444,7 @@ public class AuthToken */ public String getLifetime() { - // tbd + // tbd - Convert to tokenLifetime and lifetimeShorter to ints, substractand then convert result to string return "60"; } diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthTokenConfig.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthTokenConfig.java new file mode 100644 index 00000000..29aa6fbe --- /dev/null +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/AuthTokenConfig.java @@ -0,0 +1,297 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.*; +import java.util.*; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * AuthTokenConfig Class. + * + * This class obtains and maintains authentication token configuration. + * + */ +public class AuthTokenConfig +{ + // Well known authentication token configuration settings + public final static String TokenLifetime = "TokenLifetime"; + public final static String LifetimeShorter = "LifetimeShorter"; + public final static String IdentityTokenType = "IdentityTokenType"; + + // Default configuration values + private String m_defaultTokenLifetimeValue = "360"; // Seconds + private String m_defaultLifetimeShorterValue = "5"; // Seconds + private String m_defaultIdentityTokenTypeValue = "CasaIdentityToken"; + + private Map m_tokenSettingsMap; + + /* + * 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_SETTING_ELEMENT_START = 1; + private final static int AWAITING_SETTING_ELEMENT_DATA = 2; + private final static int AWAITING_SETTING_ELEMENT_END = 3; + private final static int DONE_PARSING = 4; + + private final static String m_rootElementName = "settings"; + + private Map m_keyMap; + private int m_state; + private String m_currentKey; + + /* + * Constructor + */ + public SAXHandler(Map keyMap) + { + super(); + + // Initialize our members + m_keyMap = keyMap; + m_state = AWAITING_ROOT_ELEMENT_START; + } + + /* + * endDocument() implementation. + */ + public void endDocument () throws SAXException + { + // Verify that we are not in an invalid state + if (m_state != DONE_PARSING) + { + System.err.println("AuthTokenConfig SAXHandler.endDocument()- Invalid state" + m_state); + throw new SAXException("Invalid state at endDocument"); + } + } + + /* + * 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 (m_rootElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_START; + } + else + { + System.err.println("AuthTokenConfig SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SETTING_ELEMENT_START: + // Keep track of the key name + m_currentKey = qName; + + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_DATA; + break; + + default: + System.err.println("AuthTokenConfig SAXHandler.startElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at startElement"); + } + } + + /* + * endElement() immplementation. + */ + public void endElement (String uri, String name, String qName) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_SETTING_ELEMENT_END: + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_START; + break; + + case AWAITING_SETTING_ELEMENT_START: + // Verify that we are processing the expected tag + if (m_rootElementName.equals(qName)) + { + // Advance to the next state + m_state = DONE_PARSING; + } + else + { + System.err.println("AuthTokenConfig SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("AuthTokenConfig SAXHandler.endElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at endElement"); + } + } + + /* + * character() implementation. + */ + public void characters (char ch[], int start, int length) throws SAXException + { + // Consume the data if in the right state + if (m_state == AWAITING_SETTING_ELEMENT_DATA) + { + // Consume the data and add the key to map + m_keyMap.put(m_currentKey, new String(ch, start, length)); + + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_END; + } + } + } + + /* + * Constructor which sets default configuration values. + */ + public AuthTokenConfig() throws Exception + { + System.err.println("AuthTokenConfig()- Default"); + + // Create a map to keep track of the token settings + m_tokenSettingsMap = new HashMap(); + + // Set the default settings in our map + m_tokenSettingsMap.put(TokenLifetime, m_defaultTokenLifetimeValue); + m_tokenSettingsMap.put(LifetimeShorter, m_defaultLifetimeShorterValue); + m_tokenSettingsMap.put(IdentityTokenType, m_defaultIdentityTokenTypeValue); + } + + /* + * Constructor. + */ + public AuthTokenConfig(String authTokenSettingsFileName) throws Exception + { + System.err.println("AuthTokenConfig()-"); + + // Create a map to keep track of the token settings + m_tokenSettingsMap = new HashMap(); + + try + { + // Get an input stream to read from the token settings file + File f = new File(authTokenSettingsFileName); + FileInputStream inStream = new FileInputStream(f); + + // Parse the file + XMLReader xr = XMLReaderFactory.createXMLReader(); + SAXHandler handler = new SAXHandler(m_tokenSettingsMap); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + + InputSource source = new InputSource(inStream); + xr.parse(source); + + inStream.close(); + } + catch (SAXException e) + { + System.err.println("AuthTokenConfig()- " + authTokenSettingsFileName + " format error, exception: " + e.toString()); + throw new Exception("AuthTokenConfig()- authtoken.settings format error"); + } + catch (SecurityException e) + { + System.err.println("AuthTokenConfig()- SecurityException accessing " + authTokenSettingsFileName + " Exception=" + e.toString()); + throw new Exception("AuthTokenConfig()- Not able to access file"); + } + catch (FileNotFoundException e) + { + System.err.println("AuthTokenConfig()- File " + authTokenSettingsFileName + " not found"); + throw new Exception("AuthTokenConfig()- File not found"); + } + catch (IOException e) + { + System.err.println("AuthTokenConfig()- IOException accessing " + authTokenSettingsFileName + " Exception=" + e.toString()); + throw new Exception("AuthTokenConfig()- Read error"); + } + } + + /* + * Returns the value associated with the specified setting. + */ + public String getSetting(String settingName) throws Exception + { + // Try to find the setting in our map + String value = (String) m_tokenSettingsMap.get(settingName); + if (value == null) + { + System.err.println("AuthTokenConfig.getSetting()- Did not find setting " + settingName); + + // The setting is not in our map, check if it is one to + // which we have defaults. + if (settingName.equals(TokenLifetime) == true) + { + value = m_defaultTokenLifetimeValue; + System.err.println("AuthTokenConfig.getSetting()- Assigning default value " + value); + + // Add the key to the map so that it can be found quicker next time + m_tokenSettingsMap.put(TokenLifetime, m_defaultTokenLifetimeValue); + } + else if (settingName.equals(LifetimeShorter) == true) + { + value = m_defaultLifetimeShorterValue; + System.err.println("AuthTokenConfig.getSetting()- Assigning default value " + value); + + // Add the key to the map so that it can be found quicker next time + m_tokenSettingsMap.put(LifetimeShorter, m_defaultLifetimeShorterValue); + } + else if (settingName.equals(IdentityTokenType) == true) + { + value = m_defaultLifetimeShorterValue; + System.err.println("AuthTokenConfig.getSetting()- Assigning default value " + value); + + // Add the key to the map so that it can be found quicker next time + m_tokenSettingsMap.put(IdentityTokenType, m_defaultIdentityTokenTypeValue); + } + } + else + { + System.err.println("AuthTokenConfig.getSetting()- Found setting " + settingName); + System.err.println("AuthTokenConfig.getSetting()- Setting value = " + value); + + // Do some sanity checking + // tbd - Make sure that the token lifetime values are greater than the LifetimeShorter + } + + return value; + } +} \ No newline at end of file diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/CasaIdentityToken.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/CasaIdentityToken.java index 47590978..5c799fe2 100644 --- a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/CasaIdentityToken.java +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/CasaIdentityToken.java @@ -85,6 +85,7 @@ public class CasaIdentityToken implements IdentityToken private final static String targetHostElementName = "target_host"; private final static String attributesElementName = "attributes"; + private IdenTokenConfig m_idenTokenConfig; private String m_identityId = null; private String m_sourceName = null; @@ -441,7 +442,10 @@ public class CasaIdentityToken implements IdentityToken // At this point we now have the target service and host names, // check if our configuration says that the attributes have been // encrypted. - m_encryptedAttrs = EncryptAttributes(m_service, m_host); + // tbd - Need to come up with a solution for obtaining configuration + // information when instanstiated using a stream. May be the token should + // carry an indication that the attributes are encrypted. + m_encryptedAttrs = false; // Advance to the next state m_state = AWAITING_TARGET_HOST_ELEMENT_END; @@ -476,26 +480,27 @@ public class CasaIdentityToken implements IdentityToken /* * Constructor. */ - public CasaIdentityToken () + public CasaIdentityToken(IdenTokenConfig idenTokenConfig) { // Initialize our members m_token = null; m_attributes = new javax.naming.directory.BasicAttributes(); + m_idenTokenConfig = idenTokenConfig; } /* * Initialize with parameters. */ - public void initialize ( - String identityId, + public void initialize(String identityId, String sourceName, String targetService, - String targetHost) throws Exception + String targetHost, + SvcConfig svcConfig) throws Exception { // Save input parameters m_identityId = identityId; m_sourceName = sourceName; - m_sourceUrl = "ldap://jcserver.provo.novell.com:389"; // tbd - Obtain from config or Higgins + m_sourceUrl = "ldap://myldaphost.novell.com:389"; // tbd - Obtain from Identity Abstraction layer m_service = targetService; m_host = targetHost; @@ -506,8 +511,8 @@ public class CasaIdentityToken implements IdentityToken // Open a directory context and use it to read the identity attributes. Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory"); - env.put(IAContext.IA_REALM_CONFIG_LOCATION, "/home/jluciani/workspace/IdentityAbstraction/realms.xml"); -// env.put(IAContext.IA_REALM_SELECTOR, ""); + env.put(IAContext.IA_REALM_CONFIG_LOCATION, svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile)); + env.put(IAContext.IA_REALM_SELECTOR, sourceName); DirContext ctx = new InitialDirContext(env); @@ -524,28 +529,47 @@ public class CasaIdentityToken implements IdentityToken sb.append("<" + attributesElementName + ">" + "\r\n"); // Get the necessary attributes of the specified services in the identity token - Set attributesNeeded = getAttributesNeededByService(m_service, m_host); - boolean encryptAttributes = EncryptAttributes(m_service, m_host); - Attributes attrs = ctx.getAttributes(identityId); + String[] attributesNeeded = m_idenTokenConfig.getAttributes(); + boolean encryptAttributes = "true".equals(m_idenTokenConfig.getSetting(IdenTokenConfig.EncryptAttributes)); + Attributes attrs = ctx.getAttributes(identityId, attributesNeeded); + + // Now append the attributes to the token for (NamingEnumeration ae = attrs.getAll(); ae.hasMore();) { javax.naming.directory.Attribute attr = (javax.naming.directory.Attribute) ae.next(); - // Append the attribute if it is one that we want. - // tbd - This needs to be customized on a per service basis. - if (attributesNeeded.contains(attr.getID())) + NamingEnumeration enumeration = attr.getAll(); + while (enumeration.hasMore()) { - NamingEnumeration enumeration = attr.getAll(); - while (enumeration.hasMore()) + String attrValue = null; + Object o = enumeration.next(); + if (o == null) + { + System.err.println("CasaIdentityToken.initialize()- null"); + } + if (o instanceof java.lang.String) + { + System.err.println("CasaIdentityToken.initialize()- Type string"); + attrValue = (String) o; + } + else if (o instanceof java.lang.Byte) + { + System.err.println("CasaIdentityToken.initialize()- Type byte[]"); + attrValue = ((byte[]) o).toString(); + } + + // Proceed if we were able to get the attribute value in String form + if (attrValue != null) { - String attrValue = (String) enumeration.next(); m_attributes.put(attr.getID(), attrValue); + System.err.println("CasaIdentityToken.initialize()- Including attribute " + attr.getID() + " of value " + attrValue); // Encrypt the attribute if necessary if (encryptAttributes == true) { // tbd - Encrypt the attributes using the services public key, let the mechanism - // be configurable. + // be configurable. The services certificate should be Base64 encoded as a setting + // of the identoken.settings file. sb.append("<" + attr.getID() + ">" + attrValue + "" + "\r\n"); } else @@ -553,6 +577,10 @@ public class CasaIdentityToken implements IdentityToken sb.append("<" + attr.getID() + ">" + attrValue + "" + "\r\n"); } } + else + { + System.err.println("CasaIdentityToken.initialize()- Unrecognized object type for attribute " + attr.getID()); + } } } sb.append("" + "\r\n"); @@ -602,33 +630,6 @@ public class CasaIdentityToken implements IdentityToken } } - /* - * Return the attributes needed by the service. - */ - private Set getAttributesNeededByService(String serviceName, String hostName) - { - // tbd - Read the following from configuration - HashSet attributesNeeded = new HashSet(); - attributesNeeded.add("sn"); - attributesNeeded.add("groupMembership"); - attributesNeeded.add("securityEquals"); - attributesNeeded.add("uid"); - attributesNeeded.add("uidNumber"); - attributesNeeded.add("gidNumber"); - - return attributesNeeded; - } - - /* - * Return indication of whether or not the identity attributes must be encrypted. - */ - private boolean EncryptAttributes(String serviceName, String hostName) - { - // tbd - Based return value based on the configuration for the service. - // Default is "false". - return false; - } - /* * Returns encoded token string. * diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java new file mode 100644 index 00000000..6e72ae51 --- /dev/null +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java @@ -0,0 +1,392 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.*; +import java.util.*; + +/** + * EnabledSvcsConfig Class. + * + * This class obtains and maintains configuration and policy information about + * the services enabled to use Authentication Tokens. + * + */ +public class EnabledSvcsConfig +{ + private static final String m_authPolicyFileName = "auth.policy"; + private static final String m_authTokenSettingsFileName = "authtoken.settings"; + private static final String m_idenTokenSettingsFileName = "identoken.settings"; + + private Map m_hostsMap; + + /** + * SvcConfigEntry Class. + * + * This class is used to maintain the configuration and policy associated with an + * enabled service. + * + */ + private class SvcConfigEntry + { + protected byte[] m_authPolicyFileData; + protected AuthTokenConfig m_authTokenConfig; + protected IdenTokenConfig m_idenTokenConfig; + + /* + * Constructor. + */ + public SvcConfigEntry(byte[] authPolicyFileData, + AuthTokenConfig authTokenConfig, + IdenTokenConfig idenTokenConfig) + { + m_authPolicyFileData = authPolicyFileData; + m_authTokenConfig = authTokenConfig; + m_idenTokenConfig = idenTokenConfig; + } + } + + /* + * Constructor. + */ + public EnabledSvcsConfig(String svcConfigPath) throws Exception + { + System.err.println("EnabledSvcsConfig()-"); + + System.err.println("EnabledSvcsConfig()- SvcConfigPath = " + svcConfigPath); + + // Initialize the default auth policy, authtoken, and identtoken configs. + byte[] defaultAuthPolicyData = null; + AuthTokenConfig defaultAuthTokenConfig = null; + IdenTokenConfig defaultIdenTokenConfig = null; + + // Create a map to keep track of the enabled services and their configuration + // for each configured host. + m_hostsMap = new HashMap(); + + // Get access to the configuration folder for the service + File configFolder = new File(svcConfigPath); + try + { + // Try to obtain the default authentication policy + try + { + File f = new File(configFolder, "/" + m_authPolicyFileName); + defaultAuthPolicyData = new byte[(int) f.length()]; + FileInputStream inStream = new FileInputStream(f); + int bytesRead = inStream.read(defaultAuthPolicyData); + inStream.close(); + if (bytesRead != defaultAuthPolicyData.length) + { + System.err.println("EnabledSvcsConfig()- Error reading default policy file"); + } + } + catch (SecurityException e) + { + System.err.println("EnabledSvcsConfig()- SecurityException accessing " + configFolder + "/" + m_authPolicyFileName + " Exception=" + e.toString()); + } + catch (FileNotFoundException e) + { + System.err.println("EnabledSvcsConfig()- File " + configFolder + "/" + m_authPolicyFileName + " not found"); + } + catch (IOException e) + { + System.err.println("EnabledSvcsConfig()- IOException reading " + configFolder + "/" + m_authPolicyFileName + " Exception=" + e.toString()); + } + + // Try to obtain the default authentication token settings + try + { + defaultAuthTokenConfig = new AuthTokenConfig(configFolder + "/" + m_authTokenSettingsFileName); + } + catch (Exception e) + { + // Not able to create authentication token configuration using the default + // file. Create one using default parameters. + defaultAuthTokenConfig = new AuthTokenConfig(); + } + + // Try to obtain the default identity token settings + try + { + defaultIdenTokenConfig = new IdenTokenConfig(configFolder + "/" + m_idenTokenSettingsFileName); + } + catch (Exception e) + { + // Not able to create identity token configuration using the default + // file. Create one using default parameters. + defaultIdenTokenConfig = new IdenTokenConfig(); + } + + // Now go through the configured hosts. Note that the services config folder + // contains folders for each host for which there are enabled services. The folders + // in the services config folder must match the DNS name of the hosts where + // the enabled services reside. + File servicesConfigFolder = new File(svcConfigPath + "/services"); + try + { + String[] servicesConfigFolderObjs = servicesConfigFolder.list(); + if (servicesConfigFolderObjs != null) + { + for (int i = 0; i < servicesConfigFolderObjs.length; i++) + { + // Check if we are dealing with a file or a folder + File hostFolder = new File(servicesConfigFolder, servicesConfigFolderObjs[i]); + try + { + if (hostFolder.isDirectory() == true) + { + System.err.println("EnabledSvcsConfig()- Host folder " + hostFolder + " is directory"); + + // Now go through the services configured for this host + String[] hostFolderObjs = hostFolder.list(); + if (hostFolderObjs != null) + { + // Create a Map object to hold the service configurations for this host + Map enabledSvcsConfigMap = new HashMap(); + + for (int ii = 0; ii < hostFolderObjs.length; ii++) + { + // Check if we are dealing with a file or a folder + File serviceFolder = new File(hostFolder, hostFolderObjs[ii]); + System.err.println("EnabledSvcsConfig()- Service folder " + serviceFolder); + try + { + if (serviceFolder.isDirectory() == true) + { + System.err.println("EnabledSvcsConfig()- Service folder " + serviceFolder + " is directory"); + + // We are dealing with a folder, remember that the folder name matches the name + // of the enabled service. Check and see if there are authentication policy and + // authtoken and identoken setting files configured for it. + byte[] authPolicyData = null; + AuthTokenConfig authTokenConfig = null; + IdenTokenConfig idenTokenConfig = null; + + try + { + File policyFile = new File(serviceFolder, "/" + m_authPolicyFileName); + authPolicyData = new byte[(int) policyFile.length()]; + FileInputStream inStream = new FileInputStream(policyFile); + int bytesRead = inStream.read(authPolicyData); + inStream.close(); + if (bytesRead != authPolicyData.length) + { + System.err.println("EnabledSvcsConfig()- Error reading policy file for " + servicesConfigFolderObjs[i] + " " + hostFolderObjs[ii]); + } + } + catch (SecurityException e) + { + System.err.println("EnabledSvcsConfig()- SecurityException accessing " + serviceFolder + "/" + m_authPolicyFileName + " Exception=" + e.toString()); + } + catch (FileNotFoundException e) + { + System.err.println("EnabledSvcsConfig()- No authentication policy file for " + serviceFolder); + } + catch (IOException e) + { + System.err.println("EnabledSvcsConfig()- IOException reading " + serviceFolder + "/" + m_authPolicyFileName + " Exception=" + e.toString()); + } + + try + { + authTokenConfig = new AuthTokenConfig(serviceFolder + "/" + m_authTokenSettingsFileName); + } + catch (Exception e) + { + System.err.println("EnabledSvcsConfig()- Exception accessing " + serviceFolder + "/" + m_authTokenSettingsFileName + " Exception=" + e.toString()); + } + + try + { + idenTokenConfig = new IdenTokenConfig(serviceFolder + "/" + m_idenTokenSettingsFileName); + } + catch (Exception e) + { + System.err.println("EnabledSvcsConfig()- Exception accessing " + serviceFolder + "/" + m_idenTokenSettingsFileName + " Exception=" + e.toString()); + } + + // Make sure that we have a policy file + if ((authPolicyData != null && authPolicyData.length != 0) + || (defaultAuthPolicyData != null && defaultAuthPolicyData.length != 0)) + { + // Instantiate SvcConfigEntry for this service and place it in our map + SvcConfigEntry svcConfigEntry = new SvcConfigEntry((authPolicyData != null && authPolicyData.length != 0) ? authPolicyData : defaultAuthPolicyData, + (authTokenConfig != null) ? authTokenConfig : defaultAuthTokenConfig, + (idenTokenConfig != null) ? idenTokenConfig : defaultIdenTokenConfig); + + // Add this entry to our map + System.err.println("EnabledSvcsConfig()- Adding entry in map for " + servicesConfigFolderObjs[i] + " " + hostFolderObjs[ii]); + enabledSvcsConfigMap.put(hostFolderObjs[ii], svcConfigEntry); + } + else + { + System.err.println("EnabledSvcsConfig()- Unable to enable " + servicesConfigFolderObjs[i] + " " + hostFolderObjs[ii] + " due to no configured authentication policy"); + } + } + } + catch (SecurityException e) + { + System.err.println("EnabledSvcsConfig()- SecurityException accessing " + serviceFolder + " Exception=" + e.toString()); + } + + // Add this hosts enabled services configuration map to the hosts map + m_hostsMap.put(servicesConfigFolderObjs[i], enabledSvcsConfigMap); + } + } + else + { + System.err.println("EnabledSvcsConfig()- No services configured for " + hostFolder); + } + } + } + catch (SecurityException e) + { + System.err.println("EnabledSvcsConfig()- SecurityException accessing " + hostFolder + " Exception=" + e.toString()); + } + } + } + else + { + System.err.println("EnabledSvcsConfig()- Unable to obtain services folder " + servicesConfigFolder + " objects"); + } + } + catch (SecurityException e) + { + System.err.println("EnabledSvcsConfig()- SecurityException accessing " + servicesConfigFolder + " Exception=" + e.toString()); + } + + // Now go through the services configured as enabled. Note that a service is configured as enabled by + // placing a folder in our conf directory with a name that matches the service's name. + } + catch (SecurityException e) + { + System.err.println("EnabledSvcsConfig()- SecurityException accessing " + configFolder + " Exception=" + e.toString()); + } + } + + /* + * Returns true if the specified service has been enabled to use authentication + * tokens. + */ + public boolean svcEnabled(String hostName, String serviceName) + { + // First try to obtain the Map of enabled services for the host + // tbd - Should we make this case insensitive? + Map enabledSvcsConfigMap = (Map) m_hostsMap.get(hostName); + if (enabledSvcsConfigMap != null) + { + return enabledSvcsConfigMap.containsKey(serviceName); + } + else + { + return false; + } + } + + /* + * Returns the data associated with the authentication policy file + * associated with the specified service. + */ + public byte[] getAuthPolicyFileDataForSvc(String hostName, String serviceName) + { + // First try to obtain the Map of enabled services for the host + // tbd - Should we make this case insensitive? + Map enabledSvcsConfigMap = (Map) m_hostsMap.get(hostName); + if (enabledSvcsConfigMap != null) + { + // Retrieve SvcConfigEntry for the service from the map for the host + SvcConfigEntry svcConfigEntry = (SvcConfigEntry) enabledSvcsConfigMap.get(serviceName); + if (svcConfigEntry != null) + { + return svcConfigEntry.m_authPolicyFileData; + } + else + { + return null; + } + } + else + { + return null; + } + } + + /* + * Returns the authentication token configuration associated with the + * specified service. + */ + public AuthTokenConfig getAuthTokenConfig(String hostName, String serviceName) + { + // First try to obtain the Map of enabled services for the host + // tbd - Should we make this case insensitive? + Map enabledSvcsConfigMap = (Map) m_hostsMap.get(hostName); + if (enabledSvcsConfigMap != null) + { + // Retrieve SvcConfigEntry for the service from the map for the host + SvcConfigEntry svcConfigEntry = (SvcConfigEntry) enabledSvcsConfigMap.get(serviceName); + if (svcConfigEntry != null) + { + return svcConfigEntry.m_authTokenConfig; + } + else + { + return null; + } + } + else + { + return null; + } + } + + /* + * Returns the identity token configuration associated with the + * specified service. + */ + public IdenTokenConfig getIdenTokenConfig(String hostName, String serviceName) + { + // First try to obtain the Map of enabled services for the host + // tbd - Should we make this case insensitive? + Map enabledSvcsConfigMap = (Map) m_hostsMap.get(hostName); + if (enabledSvcsConfigMap != null) + { + // Retrieve SvcConfigEntry for the service from the map for the host + SvcConfigEntry svcConfigEntry = (SvcConfigEntry) enabledSvcsConfigMap.get(serviceName); + if (svcConfigEntry != null) + { + return svcConfigEntry.m_idenTokenConfig; + } + else + { + return null; + } + } + else + { + return null; + } + } +} \ No newline at end of file diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthPolicy.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthPolicy.java index d594e9a9..20654539 100644 --- a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthPolicy.java +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthPolicy.java @@ -26,69 +26,82 @@ package com.novell.casa.authtoksvc; import java.io.*; import java.io.PrintWriter; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import java.util.*; /** - * GetAuthPolicy Servlet Class. + * GetAuthPolicy Class. * - * This class processes authentication policy requests for a particular + * This class processes get authentication policy requests for a particular * service. * */ -public class GetAuthPolicy extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet +public class GetAuthPolicy implements RpcMethod { - private static final long serialVersionUID = -8264027868130334613L; + private SvcConfig m_svcConfig; + private EnabledSvcsConfig m_enabledSvcsConfig; /* * Constructor. */ - public GetAuthPolicy() + public GetAuthPolicy() throws Exception { - super(); - } + // Nothing to do at this time + } /* - * doGet() implementation. + * Initialize the Rpc method. */ - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + public void init(SvcConfig svcConfig, EnabledSvcsConfig enabledSvcsConfig) throws Exception { - - doPost(request, response); - } + m_svcConfig = svcConfig; + m_enabledSvcsConfig = enabledSvcsConfig; + } /* - * doPost() implementation. + * Process Rpc. */ - protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + public void invoke(InputStream inStream, PrintWriter out) throws IOException { - // Get ready to send back a reply - response.setContentType("text/html"); - PrintWriter out = response.getWriter(); - try { + System.err.println("GetAuthPolicy.invoke()"); + // Read and parse the GetAuthPolicyReqMsg sent from the client - InputStream inStream = request.getInputStream(); GetAuthPolicyReqMsg getAuthPolicyReqMsg = new GetAuthPolicyReqMsg(inStream); - // Get the auth policy for the service - byte[] authPolicy = getAuthPolicyFileData(getAuthPolicyReqMsg.getServiceName(), - getAuthPolicyReqMsg.getHostName()); - - // Write out the response - GetAuthPolicyRespMsg getAuthPolicyRespMsg = new GetAuthPolicyRespMsg(ProtoDefs.httpOkStatusMsg, - ProtoDefs.httpOkStatusCode, - new String(Base64Coder.encode(authPolicy))); - out.println(getAuthPolicyRespMsg.toString()); + // Verify that the service is enabled + if (m_enabledSvcsConfig.svcEnabled(getAuthPolicyReqMsg.getHostName(), getAuthPolicyReqMsg.getServiceName())) + { + // Get the auth policy for the service + byte[] authPolicy = m_enabledSvcsConfig.getAuthPolicyFileDataForSvc(getAuthPolicyReqMsg.getHostName(), + getAuthPolicyReqMsg.getServiceName()); + if (authPolicy != null) + { + // Write out the response + GetAuthPolicyRespMsg getAuthPolicyRespMsg = new GetAuthPolicyRespMsg(ProtoDefs.httpOkStatusMsg, + ProtoDefs.httpOkStatusCode, + new String(Base64Coder.encode(authPolicy))); + out.println(getAuthPolicyRespMsg.toString()); + } + else + { + System.err.println("GetAuthPolicy.invoke()- authPolicy is null for enabled service: " + getAuthPolicyReqMsg.getServiceName()); + GetAuthPolicyRespMsg getAuthPolicyRespMsg = new GetAuthPolicyRespMsg(ProtoDefs.httpServerErrorStatusMsg, + ProtoDefs.httpServerErrorStatusCode); + out.println(getAuthPolicyRespMsg.toString()); + } + } + else + { + // The service has not been enabled to utilize our authentication tokens + GetAuthPolicyRespMsg getAuthPolicyRespMsg = new GetAuthPolicyRespMsg(ProtoDefs.httpNotFoundStatusMsg, + ProtoDefs.httpNotFoundStatusCode); + out.println(getAuthPolicyRespMsg.toString()); + } } catch (Exception e) { - // tbd - System.err.println("GetAuthPolicy.doPost()- Exception caught: " + e.toString()); + System.err.println("GetAuthPolicy.invoke()- Exception: " + e.toString()); // Write out the response try @@ -99,38 +112,16 @@ public class GetAuthPolicy extends javax.servlet.http.HttpServlet implements jav } catch (Exception e2) { - System.err.println("GetAuthPolicy.doPost()- Exception trying to construct response msg: " + e2.toString()); + System.err.println("GetAuthPolicy.invoke()- Exception trying to construct response msg: " + e2.toString()); } } - - // Done sending out the reply - out.close(); } /* - * Returns the data associated with the authentication policy file - * associated with the specified service. + * Return the method id. */ - private byte[] getAuthPolicyFileData(String serviceName, String hostName) + public String getId() { - // tdb - Read the file associated with the specified service - StringBuffer sb = new StringBuffer(); - - // Start building the policy data - sb.append(ProtoDefs.xmlDeclaration + "\r\n"); - sb.append("<" + ProtoDefs.authPolicyElementName + ">" + "\r\n"); - sb.append("<" + ProtoDefs.authSourceElementName + ">" + "\r\n"); - sb.append("<" + ProtoDefs.realmElementName + ">" + "jctree" + "" + "\r\n"); - sb.append("<" + ProtoDefs.mechanismElementName + ">" + "Krb5Authenticate" + "" + "\r\n"); - sb.append("<" + ProtoDefs.mechanismInfoElementName + ">" + "host/jcstation.dnsdhcp.provo.novell.com" + "" + "\r\n"); - sb.append("" + "\r\n"); - sb.append("<" + ProtoDefs.authSourceElementName + ">" + "\r\n"); - sb.append("<" + ProtoDefs.realmElementName + ">" + "jctree" + "" + "\r\n"); - sb.append("<" + ProtoDefs.mechanismElementName + ">" + "PwdAuthenticate" + "" + "\r\n"); - sb.append("<" + ProtoDefs.mechanismInfoElementName + ">" + "" + "" + "\r\n"); - sb.append("" + "\r\n"); - sb.append("" + "\r\n"); - String s = sb.toString(); - return s.getBytes(); + return "GetAuthPolicy"; } } \ No newline at end of file diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthToken.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthToken.java index e9f6af69..9f6a1a56 100644 --- a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthToken.java +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/GetAuthToken.java @@ -28,93 +28,99 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - /** - * GetAuthToken Servlet Class. + * GetAuthToken Class. * * This class processes requests for tokens to authenticate an entity * to a particular service. * */ -public class GetAuthToken extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet +public class GetAuthToken implements RpcMethod { - private static final long serialVersionUID = -5792862615065914894L; + private SvcConfig m_svcConfig; + private EnabledSvcsConfig m_enabledSvcsConfig; /* * Constructor. */ - public GetAuthToken() + public GetAuthToken() throws Exception { - super(); + // Nothing to do at this time } /* - * doGet() implementation. + * Initialize the Rpc method. */ - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + public void init(SvcConfig svcConfig, EnabledSvcsConfig enabledSvcsConfig) throws Exception { - // Just let doPost() handle it. - doPost(request, response); - } + m_svcConfig = svcConfig; + m_enabledSvcsConfig = enabledSvcsConfig; + } /* - * doPost() implementation. + * Process Rpc. */ - protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + public void invoke(InputStream inStream, PrintWriter out) throws IOException { - // Get ready to send back a reply - response.setContentType("text/html"); - PrintWriter out = response.getWriter(); - try { - // Read and parse the GetAuthTokReqMsg sent from the client - InputStream inStream = request.getInputStream(); + System.err.println("GetAuthToken.invoke()"); + + // Parse the GetAuthTokReqMsg sent from the client GetAuthTokReqMsg getAuthTokReqMsg = new GetAuthTokReqMsg(inStream); - // Now create a session token (This validates the session token provided). - SessionToken sessionToken = new SessionToken(getAuthTokReqMsg.getSessionToken()); - - try + // Verify that the service is enabled + if (m_enabledSvcsConfig.svcEnabled(getAuthTokReqMsg.getHostName(), + getAuthTokReqMsg.getServiceName())) { - // Create the Authentication Token - AuthToken authToken = new AuthToken(sessionToken.getIdentId(), - sessionToken.getRealm(), - getAuthTokReqMsg.getServiceName(), - getAuthTokReqMsg.getHostName()); + // Now create a session token (This validates the session token provided). + SessionToken sessionToken = new SessionToken(getAuthTokReqMsg.getSessionToken()); - // Write out the response - GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpOkStatusMsg, - ProtoDefs.httpOkStatusCode, - authToken.toString(), - authToken.getLifetime()); - out.println(getAuthTokRespMsg.toString()); - } - catch (Exception e) - { - // tbd, use a custom exception and then set the status based - // on the type of exeption cached. - - // Write out the response try { - GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpServerErrorStatusMsg, - ProtoDefs.httpUnauthorizedStatusCode); + // Create the Authentication Token + AuthToken authToken = new AuthToken(sessionToken.getIdentId(), + sessionToken.getRealm(), + getAuthTokReqMsg.getServiceName(), + getAuthTokReqMsg.getHostName(), + m_svcConfig, + m_enabledSvcsConfig); + + // Write out the response + GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpOkStatusMsg, + ProtoDefs.httpOkStatusCode, + authToken.toString(), + authToken.getLifetime()); out.println(getAuthTokRespMsg.toString()); } - catch (Exception e2) + catch (Exception e) { - System.err.println("GetAuthToken.doPost()- Exception trying to construct response msg: " + e2.toString()); + System.err.println("GetAuthToken.invoke()- Exception: " + e.toString()); + + // Write out the response + try + { + GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpUnauthorizedStatusMsg, + ProtoDefs.httpUnauthorizedStatusCode); + out.println(getAuthTokRespMsg.toString()); + } + catch (Exception e2) + { + System.err.println("GetAuthToken.invoke()- Exception trying to construct response msg: " + e2.toString()); + } } } + else + { + // The service has not been enabled to utilize our authentication tokens + GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpNotFoundStatusMsg, + ProtoDefs.httpNotFoundStatusCode); + out.println(getAuthTokRespMsg.toString()); + } } catch (Exception e) { - // tbd - System.err.println("GetAuthToken.doPost()- Exception caught: " + e.toString()); + System.err.println("GetAuthToken.invoke()- Exception: " + e.toString()); // Write out the response try @@ -125,11 +131,16 @@ public class GetAuthToken extends javax.servlet.http.HttpServlet implements java } catch (Exception e2) { - System.err.println("GetAuthToken.doPost()- Exception trying to construct response msg: " + e2.toString()); + System.err.println("GetAuthToken.invoke()- Exception trying to construct response msg: " + e2.toString()); } } + } - // Done sending out the reply - out.close(); + /* + * Return the method id. + */ + public String getId() + { + return "GetAuthToken"; } } \ No newline at end of file diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/IdenTokenConfig.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/IdenTokenConfig.java new file mode 100644 index 00000000..aa3ce49b --- /dev/null +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/IdenTokenConfig.java @@ -0,0 +1,293 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.*; +import java.util.*; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * IdenTokenConfig Class. + * + * This class obtains and maintains identity token configuration. + * + */ +public class IdenTokenConfig +{ + // Well known identity token configuration settings + public final static String EncryptAttributes = "EncryptAttributes"; + public final static String Attributes = "Attributes"; + + // Default configuration values + private String m_defaultEncryptAttributesValue = "false"; + private String m_defaultAttributesValue = "sn"; + + private Map m_tokenSettingsMap; + private String[] m_identityAttributes; + + /* + * 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_SETTING_ELEMENT_START = 1; + private final static int AWAITING_SETTING_ELEMENT_DATA = 2; + private final static int AWAITING_SETTING_ELEMENT_END = 3; + private final static int DONE_PARSING = 4; + + private final static String m_rootElementName = "settings"; + + private Map m_keyMap; + private int m_state; + private String m_currentKey; + + /* + * Constructor + */ + public SAXHandler(Map keyMap) + { + super(); + + // Initialize our members + m_keyMap = keyMap; + m_state = AWAITING_ROOT_ELEMENT_START; + } + + /* + * endDocument() implementation. + */ + public void endDocument () throws SAXException + { + // Verify that we are not in an invalid state + if (m_state != DONE_PARSING) + { + System.err.println("IdenTokenConfig SAXHandler.endDocument()- Invalid state" + m_state); + throw new SAXException("Invalid state at endDocument"); + } + } + + /* + * 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 (m_rootElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_START; + } + else + { + System.err.println("IdenTokenConfig SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SETTING_ELEMENT_START: + // Keep track of the key name + m_currentKey = qName; + + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_DATA; + break; + + default: + System.err.println("IdenTokenConfig SAXHandler.startElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at startElement"); + } + } + + /* + * endElement() immplementation. + */ + public void endElement (String uri, String name, String qName) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_SETTING_ELEMENT_END: + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_START; + break; + + case AWAITING_SETTING_ELEMENT_START: + // Verify that we are processing the expected tag + if (m_rootElementName.equals(qName)) + { + // Advance to the next state + m_state = DONE_PARSING; + } + else + { + System.err.println("IdenTokenConfig SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("IdenTokenConfig SAXHandler.endElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at endElement"); + } + } + + /* + * character() implementation. + */ + public void characters (char ch[], int start, int length) throws SAXException + { + // Consume the data if in the right state + if (m_state == AWAITING_SETTING_ELEMENT_DATA) + { + // Consume the data and add the key to map + // tbd - Add code to aggregate attributes specified as multiple elements + m_keyMap.put(m_currentKey, new String(ch, start, length)); + + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_END; + } + } + } + + /* + * Constructor which sets default configuration values. + */ + public IdenTokenConfig() throws Exception + { + System.err.println("IdenTokenConfig()- Default"); + + // Create a map to keep track of the token settings + m_tokenSettingsMap = new HashMap(); + + // Set the default settings in our map + m_tokenSettingsMap.put(Attributes, m_defaultAttributesValue); + } + + /* + * Constructor. + */ + public IdenTokenConfig(String idenTokenSettingsFileName) throws Exception + { + System.err.println("IdenTokenConfig()-"); + + // Create a map to keep track of the token settings + m_tokenSettingsMap = new HashMap(); + + try + { + // Get an input stream to read from the token settings file + File f = new File(idenTokenSettingsFileName); + FileInputStream inStream = new FileInputStream(f); + + // Parse the file + XMLReader xr = XMLReaderFactory.createXMLReader(); + SAXHandler handler = new SAXHandler(m_tokenSettingsMap); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + + InputSource source = new InputSource(inStream); + xr.parse(source); + + inStream.close(); + + // Process the specified attributes + if (m_tokenSettingsMap.containsKey(Attributes) == false) + { + System.err.println("IdenTokenConfig()- Attributes not configured, defaulting them."); + m_tokenSettingsMap.put(Attributes, m_defaultAttributesValue); + } + String attributes = (String) m_tokenSettingsMap.get(Attributes); + m_identityAttributes = attributes.split(","); + } + catch (SAXException e) + { + System.err.println("IdenTokenConfig()- " + idenTokenSettingsFileName + " format error, exception: " + e.toString()); + throw new Exception("IdenTokenConfig()- authtoken.settings format error"); + } + catch (SecurityException e) + { + System.err.println("IdenTokenConfig()- SecurityException accessing " + idenTokenSettingsFileName + " Exception=" + e.toString()); + throw new Exception("IdenTokenConfig()- Not able to access file"); + } + catch (FileNotFoundException e) + { + System.err.println("IdenTokenConfig()- File " + idenTokenSettingsFileName + " not found"); + throw new Exception("IdenTokenConfig()- File not found"); + } + catch (IOException e) + { + System.err.println("IdenTokenConfig()- IOException accessing " + idenTokenSettingsFileName + " Exception=" + e.toString()); + throw new Exception("IdenTokenConfig()- Read error"); + } + } + + /* + * Returns the value associated with the specified setting. + */ + public String getSetting(String settingName) throws Exception + { + // Try to find the setting in our map + String value = (String) m_tokenSettingsMap.get(settingName); + if (value == null) + { + System.err.println("IdenTokenConfig.getSetting()- Did not find setting " + settingName); + + // The setting is not in our map, check if it is one to + // which we have defaults. + if (settingName.equals(EncryptAttributes) == true) + { + value = m_defaultEncryptAttributesValue; + System.err.println("AuthTokenConfig.getSetting()- Assigning default value " + value); + + // Add the key to the map so that it can be found quicker next time + m_tokenSettingsMap.put(EncryptAttributes, m_defaultEncryptAttributesValue); + } + } + else + { + System.err.println("IdenTokenConfig.getSetting()- Found setting " + settingName); + System.err.println("IdenTokenConfig.getSetting()- Setting value = " + value); + } + + return value; + } + + /* + * Returns the identity attributes that must be included in the token. + */ + public String[] getAttributes() throws Exception + { + return m_identityAttributes; + } +} \ No newline at end of file diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/IdentityToken.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/IdentityToken.java index 5e166031..721157e7 100644 --- a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/IdentityToken.java +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/IdentityToken.java @@ -25,26 +25,25 @@ package com.novell.casa.authtoksvc; /* - * IdentityTokenProvider Interface. + * IdentityToken Interface. * - * This is the interface to Identity Token Providers. + * This is the interface implemented by Identity Token Providers. */ public interface IdentityToken { - /* * Initialize the token with parameters. */ - void initialize ( - String identityId, + void initialize(String identityId, String sourceName, String targetService, - String targetHost) throws Exception; + String targetHost, + SvcConfig svcConfig) throws Exception; /* * Initialize the token object with encoded token string. */ - void initialize (String encodedToken) throws Exception; + void initialize(String encodedToken) throws Exception; /* * Returns encoded token string. diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Krb5Authenticate.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Krb5Authenticate.java index 1ab900bb..2cc78a53 100644 --- a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Krb5Authenticate.java +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Krb5Authenticate.java @@ -38,9 +38,6 @@ import javax.naming.directory.BasicAttributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchResult; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.ietf.jgss.GSSContext; import org.ietf.jgss.GSSCredential; @@ -52,30 +49,23 @@ import org.ietf.jgss.Oid; import org.bandit.ia.IAContext; /** - * Krb5Authenticate Servlet Class. + * Krb5Authenticate Class. * - * This class processes authentication requests utilizing a kerberos-V token. + * This class implementes an authentication mechanism for + * the processing of authentication requests utilizing a + * Kerberos5 token. * */ -public class Krb5Authenticate extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet +public class Krb5Authenticate implements AuthMechanism { - private static final long serialVersionUID = 7247746330553668339L; - - /* - * tbd - This needs to be somewhere else so that the same parameter - * can be accessed by other authentication mechanisms. - * - * Configurable operating parameters - * - */ - public String sessionTokenLifetime = "360"; + private SvcConfig m_svcConfig; /* * GSS Long Lived variables */ - protected GSSManager m_manager; - protected Oid m_krb5; - protected GSSName m_svcName; + protected GSSManager m_manager; + protected Oid m_krb5; + protected GSSName m_svcName; protected GSSCredential m_credential; /* @@ -132,7 +122,15 @@ public class Krb5Authenticate extends javax.servlet.http.HttpServlet implements */ public Krb5Authenticate() throws Exception { - super(); + // Nothing to do at this time + } + + /* + * Initialize the mechanism. + */ + public void init(SvcConfig svcConfig) throws Exception + { + m_svcConfig = svcConfig; try { @@ -162,40 +160,28 @@ public class Krb5Authenticate extends javax.servlet.http.HttpServlet implements System.err.println("Krb5Authenticate()- GSS Exception caught: " + e.getLocalizedMessage()); throw new Exception("Failed to instantiate needed GSS objects"); } - } + } /* - * doGet() implementation. + * invoke() implementation. */ - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + public String invoke(AuthReqMsg authReqMsg) throws Exception { - doPost(request, response); - } - - /* - * doPost() implementation. - */ - protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException - { - // Get ready to send back a reply - response.setContentType("text/html"); - PrintWriter out = response.getWriter(); + String identId = null; try { - // Read and parse the AuthReqMsg sent from the client - InputStream inStream = request.getInputStream(); - AuthReqMsg authReqMsg = new AuthReqMsg(inStream); + System.err.println("Krb5Authenticate.invoke()"); - // Now parse the PW Token + // Now parse the Kerberos Token Krb5Token krb5Token = new Krb5Token(authReqMsg.getAuthMechToken(), this); // Open a directory context and use it to identify the users // associated with the specified surname. Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory"); - env.put(IAContext.IA_REALM_CONFIG_LOCATION, "/home/jluciani/workspace/IdentityAbstraction/realms.xml"); -// env.put(IAContext.IA_REALM_SELECTOR, ""); + env.put(IAContext.IA_REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile)); + env.put(IAContext.IA_REALM_SELECTOR, authReqMsg.getRealm()); DirContext ctx = new InitialDirContext(env); @@ -203,76 +189,35 @@ public class Krb5Authenticate extends javax.servlet.http.HttpServlet implements Attributes matchAttrs = new BasicAttributes(true); // ignore attribute name case matchAttrs.put(new BasicAttribute("krbPrincipalName", krb5Token.getPrincipalName())); - NamingEnumeration answer = ctx.search("o=novell", matchAttrs); + NamingEnumeration answer = ctx.search(m_svcConfig.getSetting(SvcConfig.StartSearchContext), matchAttrs); // Proceed based on the result of the search - String identId = null; if (answer.hasMore()) { // The search succeeded, set the identity id. SearchResult sr = (SearchResult)answer.next(); - identId = sr.getName() + ",o=novell"; + identId = sr.getName() + "," + m_svcConfig.getSetting(SvcConfig.StartSearchContext); } - - // Create response based on the identity resolution results - if (identId != null) - { - // An identity was resolved, get a SessionToken for it. - SessionToken sessionToken = new SessionToken(identId, authReqMsg.getRealm(), sessionTokenLifetime); - - // Write out the response - AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpOkStatusMsg, - ProtoDefs.httpOkStatusCode, - sessionToken.toString(), - sessionTokenLifetime); - out.println(authRespMsg.toString()); - } - else - { - // Write out the response - AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpUnauthorizedStatusMsg, - ProtoDefs.httpUnauthorizedStatusCode); - out.println(authRespMsg.toString()); - } - } catch (NamingException e) { - // tbd // Log the error - System.err.println("Krb5Authenticate.doPost()- Exception caught: " + e.getExplanation()); - - // Write out the response - try - { - AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpServerErrorStatusMsg, - ProtoDefs.httpServerErrorStatusCode); - out.println(authRespMsg.toString()); - } - catch (Exception e2) - { - System.err.println("Krb5Authenticate.doPost()- Exception trying to construct response msg: " + e2.toString()); - } + System.err.println("Krb5Authenticate.invoke()- NamingException: " + e.getExplanation()); } catch (Exception e) { - // tbd - System.err.println("Krb5Authenticate.doPost()- Exception: " + e.toString()); - - // Write out the response - try - { - AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpServerErrorStatusMsg, - ProtoDefs.httpServerErrorStatusCode); - out.println(authRespMsg.toString()); - } - catch (Exception e2) - { - System.err.println("Krb5Authenticate.doPost()- Exception trying to construct response msg: " + e2.toString()); - } + System.err.println("Krb5Authenticate.invoke()- Exception: " + e.toString()); } - // Done sending out the reply - out.close(); - } + // Return the authentication result + return identId; + } + + /* + * Return the mechanism id. + */ + public String getId() + { + return "Krb5Authenticate"; + } } \ No newline at end of file diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/ProtoDefs.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/ProtoDefs.java index c3c0bfc4..e878a02d 100644 --- a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/ProtoDefs.java +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/ProtoDefs.java @@ -79,6 +79,8 @@ public class ProtoDefs public final static String httpOkStatusMsg = "OK"; public final static String httpUnauthorizedStatusCode = "401"; public final static String httpUnauthorizedStatusMsg = "Unauthorized"; + public final static String httpNotFoundStatusCode = "404"; + public final static String httpNotFoundStatusMsg = "Not Found"; public final static String httpServerErrorStatusCode = "500"; public final static String httpServerErrorStatusMsg = "Internal Server Error"; } diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/PwdAuthenticate.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/PwdAuthenticate.java index 59d40f98..579ca641 100644 --- a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/PwdAuthenticate.java +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/PwdAuthenticate.java @@ -31,10 +31,6 @@ import java.io.PrintWriter; import java.io.StringReader; import java.util.Hashtable; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.directory.BasicAttribute; @@ -49,25 +45,16 @@ import org.bandit.ia.IAContext; /** - * PwdAuthenticate Servlet Class. + * PwdAuthenticate Class. * - * This class processes authentication requests utilizing username and - * password materials. + * This class implementes an authentication mechanism for + * the processing of authentication requests utilizing a + * username/password token. * */ -public class PwdAuthenticate extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet +public class PwdAuthenticate implements AuthMechanism { - - private static final long serialVersionUID = 3710685782114934264L; - - /* - * tbd - This needs to be somewhere else so that the same parameter - * can be accessed by other authentication mechanisms. - * - * Configurable operating parameters - * - */ - public String sessionTokenLifetime = "360"; + private SvcConfig m_svcConfig; /* * Password Token Class. @@ -116,34 +103,29 @@ public class PwdAuthenticate extends javax.servlet.http.HttpServlet implements j /* * Constructor */ - public PwdAuthenticate() + public PwdAuthenticate() throws Exception { - super(); + // Nothing to do at this time } /* - * doGet() implementation. + * Initialize the mechanism. */ - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + public void init(SvcConfig svcConfig) throws Exception { - // Just let doPost() handle it. - doPost(request, response); - } + m_svcConfig = svcConfig; + } /* - * doPost() implementation. + * invoke() implementation. */ - protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + public String invoke(AuthReqMsg authReqMsg) throws Exception { - // Get ready to send back a reply - response.setContentType("text/html"); - PrintWriter out = response.getWriter(); + String identId = null; try { - // Read and parse the AuthReqMsg sent from the client - InputStream inStream = request.getInputStream(); - AuthReqMsg authReqMsg = new AuthReqMsg(inStream); + System.err.println("PwdAuthenticate.invoke()"); // Now parse the PW Token PwToken pwToken = new PwToken(authReqMsg.getAuthMechToken()); @@ -152,8 +134,8 @@ public class PwdAuthenticate extends javax.servlet.http.HttpServlet implements j // associated with the specified surname. Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory"); - env.put(IAContext.IA_REALM_CONFIG_LOCATION, "/home/jluciani/workspace/IdentityAbstraction/realms.xml"); -// env.put(IAContext.IA_REALM_SELECTOR, ""); + env.put(IAContext.IA_REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile)); + env.put(IAContext.IA_REALM_SELECTOR, authReqMsg.getRealm()); DirContext ctx = new InitialDirContext(env); @@ -161,102 +143,53 @@ public class PwdAuthenticate extends javax.servlet.http.HttpServlet implements j Attributes matchAttrs = new BasicAttributes(true); // ignore attribute name case matchAttrs.put(new BasicAttribute("cn", pwToken.getUsername())); - NamingEnumeration answer = ctx.search("o=novell", matchAttrs); + NamingEnumeration answer = ctx.search(m_svcConfig.getSetting(SvcConfig.StartSearchContext), matchAttrs); // Enumerate through the users returned checking the password - String identId = null; while (answer.hasMore()) { SearchResult sr = (SearchResult)answer.next(); - System.err.println(sr.getName()); - // Open a directory context for the user as a way of verifying its password try { Hashtable env2 = new Hashtable(); env2.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory"); - env2.put(IAContext.IA_REALM_CONFIG_LOCATION, "/home/jluciani/workspace/IdentityAbstraction/realms.xml"); -// env2.put(IAContext.IA_REALM_SELECTOR, ""); - -// env2.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); -// env2.put(Context.PROVIDER_URL, "ldap://jcserver.provo.novell.com:389"); -// env2.put(Context.SECURITY_AUTHENTICATION, "simple"); -// env2.put(Context.SECURITY_PRINCIPAL, sr.getName() + ",o=novell"); -// env2.put(Context.SECURITY_CREDENTIALS, pwToken.getPassword()); + env2.put(IAContext.IA_REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile)); + env2.put(IAContext.IA_REALM_SELECTOR, authReqMsg.getRealm()); if ((new InitialDirContext(env2)) != null) { // The password must be valid, set the identity Id. - identId = sr.getName() + ",o=novell"; + identId = sr.getName() + "," + m_svcConfig.getSetting(SvcConfig.StartSearchContext); break; } } catch (NamingException e) { - System.err.println("PwdAuthenticate.doPost()- Naming Exception: " + e.getExplanation()); + System.err.println("PwdAuthenticate.invoke()- NamingException: " + e.getExplanation()); } } - - // Create response based on the identity resolution results - if (identId != null) - { - // An identity was resolved, get a SessionToken for it. - SessionToken sessionToken = new SessionToken(identId, authReqMsg.getRealm(), sessionTokenLifetime); - - // Write out the response - AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpOkStatusMsg, - ProtoDefs.httpOkStatusCode, - sessionToken.toString(), - sessionTokenLifetime); - out.println(authRespMsg.toString()); - } - else - { - // Write out the response - AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpUnauthorizedStatusMsg, - ProtoDefs.httpUnauthorizedStatusCode); - out.println(authRespMsg.toString()); - } - } catch (NamingException e) { - // tbd // Log the error - System.err.println("PwdAuthenticate.doPost()- Naming Exception on Proxy User: " + e.getExplanation()); - - // Write out the response - try - { - AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpServerErrorStatusMsg, - ProtoDefs.httpServerErrorStatusCode); - out.println(authRespMsg.toString()); - } - catch (Exception e2) - { - System.err.println("PwdAuthenticate.doPost()- Exception trying to construct response msg: " + e2.toString()); - } + System.err.println("PwdAuthenticate.invoke()- NamingException on Proxy User: " + e.getExplanation()); } catch (Exception e) { - // tbd - System.err.println("PwdAuthenticate.doPost()- Naming Exception on Proxy User: " + e.toString()); - - // Write out the response - try - { - AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpServerErrorStatusMsg, - ProtoDefs.httpServerErrorStatusCode); - out.println(authRespMsg.toString()); - } - catch (Exception e2) - { - System.err.println("PwdAuthenticate.doPost()- Exception trying to construct response msg: " + e2.toString()); - } + System.err.println("PwdAuthenticate.invoke()- Exception: " + e.toString()); } - // Done sending out the reply - out.close(); + // Return the authentication result + return identId; + } + + /* + * Return the mechanism id. + */ + public String getId() + { + return "PwdAuthenticate"; } } \ No newline at end of file diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Rpc.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Rpc.java new file mode 100644 index 00000000..2a34ccd0 --- /dev/null +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/Rpc.java @@ -0,0 +1,170 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.util.*; + +import java.io.*; +import java.io.PrintWriter; + +import javax.servlet.*; +import javax.servlet.ServletException; +import javax.servlet.http.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + + + +/** + * Rpc Servlet Class. + * + * This class processes Rpcs to the Authentication Token Service. + * + */ +public class Rpc extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet +{ + private static final long serialVersionUID = -8264027868130334613L; + + private EnabledSvcsConfig m_enabledSvcsConfig; + private Map m_methodsMap; + + /* + * Constructor. + */ + public Rpc() + { + super(); + } + + /* + * init() implementation. + */ + public void init(ServletConfig config) throws ServletException + { + super.init(config); + + System.err.println("Rpc.init()"); + + try + { + ServletContext context = config.getServletContext(); + + // Read service configuration + SvcConfig svcConfig = new SvcConfig(context.getRealPath("/") + "WEB-INF/conf"); + + // Read enabled services configuration + EnabledSvcsConfig enabledSvcsConfig = new EnabledSvcsConfig(context.getRealPath("/") + "WEB-INF/conf"); + + // Create a map to keep track of the Rpc methods + m_methodsMap = new HashMap(); + + // Instantiate the Rpc Methods + RpcMethod getAuthPolicy = new GetAuthPolicy(); + getAuthPolicy.init(svcConfig, enabledSvcsConfig); + m_methodsMap.put(getAuthPolicy.getId(), getAuthPolicy); + + RpcMethod authenticate = new Authenticate(); + authenticate.init(svcConfig, enabledSvcsConfig); + m_methodsMap.put(authenticate.getId(), authenticate); + + RpcMethod getAuthToken = new GetAuthToken(); + getAuthToken.init(svcConfig, enabledSvcsConfig); + m_methodsMap.put(getAuthToken.getId(), getAuthToken); + } + catch (Exception e) + { + System.err.println("Rpc.init()- Exception caught: " + e.toString()); + throw new ServletException("Exception caught while instantiating Rpc methods"); + } + } + + /* + * destroy() implementation. + */ + public void destroy() + { + super.destroy(); + + System.err.println("Rpc.destroy()"); + } + + /* + * doGet() implementation. + */ + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + doPost(request, response); + } + + /* + * doPost() implementation. + */ + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + // Get ready to send back a reply + response.setContentType("text/html"); + PrintWriter out = response.getWriter(); + + try + { + // Obtain the input stream and execute the requested method + InputStream inStream = request.getInputStream(); + + String requestedMethod = request.getParameter("method"); + if (requestedMethod != null) + { + // Get the necessary method + RpcMethod method = (RpcMethod) m_methodsMap.get(requestedMethod); + if (method != null) + { + // Invoke the method to process the Rpc + method.invoke(inStream, out); + } + else + { + // Unsupported method + System.err.println("Rpc.doPost()- Unsupported method"); + response.sendError(response.SC_BAD_REQUEST); + } + } + else + { + // Missing method parameter + System.err.println("Rpc.doPost()- Missing method parameter"); + response.sendError(response.SC_BAD_REQUEST); + } + } + catch (Exception e) + { + // tbd + System.err.println("Rpc.doPost()- Exception caught: " + e.toString()); + response.sendError(response.SC_INTERNAL_SERVER_ERROR); + } + + // Done sending out the reply + out.close(); + } +} \ No newline at end of file diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/RpcMethod.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/RpcMethod.java new file mode 100644 index 00000000..3e23a49b --- /dev/null +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/RpcMethod.java @@ -0,0 +1,53 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.*; +import java.io.PrintWriter; +import java.util.*; + + +/* + * RpcMethod Interface. + * + * This is the interface implemented by Rpc Methods. + */ +public interface RpcMethod +{ + /* + * Initialize the Rpc method. + */ + void init(SvcConfig svcConfig, EnabledSvcsConfig enabledSvcsConfig) throws Exception; + + /* + * Process Rpc. + */ + void invoke(InputStream inStream, PrintWriter out) throws IOException; + + /* + * Return the method id. + */ + String getId(); +} diff --git a/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/SvcConfig.java b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/SvcConfig.java new file mode 100644 index 00000000..eae62c1e --- /dev/null +++ b/auth_token/server/AuthTokenSvc/src/com/novell/casa/authtoksvc/SvcConfig.java @@ -0,0 +1,291 @@ +/*********************************************************************** + * + * 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 + * + ***********************************************************************/ + +package com.novell.casa.authtoksvc; + +import java.io.*; +import java.util.*; + +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * SvcConfig Class. + * + * This class obtains and maintains the service configuration. + * + */ +public class SvcConfig +{ + // Well known service configuration settings + // + // The LifetimeShorter value is the value by which token lifetime + // values are shorten when specified to clients to make sure that + // the clients detect token expirations before issuing the tokens + // to a service for authentication purposes. + public final static String SessionTokenLifetime = "SessionTokenLifetime"; + public final static String LifetimeShorter = "LifetimeShorter"; + public final static String IdentityAbstractionConfigFile = "IAConfigFile"; + public final static String StartSearchContext = "startSearchContext"; + public final static String ConfigFolderPath = "ConfigFolderPath"; + + // Default configuration values + private String m_defaultSessionTokenLifetimeValue = "360"; // Seconds + private String m_defaultLifetimeShorterValue = "5"; // Seconds + + private static final String m_svcSettingsFileName = "svc.settings"; + private Map m_svcSettingsMap; + + /* + * Class for handling Authentication Request 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_SETTING_ELEMENT_START = 1; + private final static int AWAITING_SETTING_ELEMENT_DATA = 2; + private final static int AWAITING_SETTING_ELEMENT_END = 3; + private final static int DONE_PARSING = 4; + + private final static String m_rootElementName = "settings"; + + private Map m_keyMap; + private int m_state; + private String m_currentKey; + + /* + * Constructor + */ + public SAXHandler(Map keyMap) + { + super(); + + // Initialize our members + m_keyMap = keyMap; + m_state = AWAITING_ROOT_ELEMENT_START; + } + + /* + * endDocument() implementation. + */ + public void endDocument () throws SAXException + { + // Verify that we are not in an invalid state + if (m_state != DONE_PARSING) + { + System.err.println("SvcConfig SAXHandler.endDocument()- Invalid state" + m_state); + throw new SAXException("Invalid state at endDocument"); + } + } + + /* + * 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 (m_rootElementName.equals(qName)) + { + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_START; + } + else + { + System.err.println("SvcConfig SAXHandler.startElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + case AWAITING_SETTING_ELEMENT_START: + // Keep track of the key name + m_currentKey = qName; + + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_DATA; + break; + + default: + System.err.println("SvcConfig SAXHandler.startElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at startElement"); + } + } + + /* + * endElement() immplementation. + */ + public void endElement (String uri, String name, String qName) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_SETTING_ELEMENT_END: + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_START; + break; + + case AWAITING_SETTING_ELEMENT_START: + // Verify that we are processing the expected tag + if (m_rootElementName.equals(qName)) + { + // Advance to the next state + m_state = DONE_PARSING; + } + else + { + System.err.println("SvcConfig SAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("SvcConfig SAXHandler.endElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at endElement"); + } + } + + /* + * character() implementation. + */ + public void characters (char ch[], int start, int length) throws SAXException + { + // Consume the data if in the right state + if (m_state == AWAITING_SETTING_ELEMENT_DATA) + { + // Consume the data and add the key to map + m_keyMap.put(m_currentKey, new String(ch, start, length)); + + // Advance to the next state + m_state = AWAITING_SETTING_ELEMENT_END; + } + } + } + + /* + * Constructor. + */ + public SvcConfig(String svcConfigPath) throws Exception + { + System.err.println("SvcConfig()-"); + + System.err.println("SvcConfig()- SvcConfigPath = " + svcConfigPath); + + // Create a map to keep track of the service settings + m_svcSettingsMap = new HashMap(); + + try + { + // Get an input stream to services settings file + File settingsFile = new File(svcConfigPath + "/" + m_svcSettingsFileName); + FileInputStream inStream = new FileInputStream(settingsFile); + + // Parse the file + XMLReader xr = XMLReaderFactory.createXMLReader(); + SAXHandler handler = new SAXHandler(m_svcSettingsMap); + xr.setContentHandler(handler); + xr.setErrorHandler(handler); + + InputSource source = new InputSource(inStream); + xr.parse(source); + inStream.close(); + + // Add the config folder path setting to our map + m_svcSettingsMap.put(ConfigFolderPath, svcConfigPath); + } + catch (SAXException e) + { + System.err.println("SvcConfig()- Parse exception: " + e.toString()); + throw new Exception("SvcConfig()- svc.settings format error"); + } + catch (SecurityException e) + { + System.err.println("SvcConfig()- SecurityException caught while accessing " + svcConfigPath + "/" + m_svcSettingsFileName + " Exception=" + e.toString()); + } + catch (FileNotFoundException e) + { + System.err.println("SvcConfig()- File " + svcConfigPath + "/" + m_svcSettingsFileName + " not found"); + } + catch (IOException e) + { + System.err.println("SvcConfig()- IOException caught while trying to read " + svcConfigPath + "/" + m_svcSettingsFileName + " Exception=" + e.toString()); + } + } + + /* + * Returns the value associated with the specified setting. + */ + public String getSetting(String settingName) throws Exception + { + // Try to find the setting in our map + String value = (String) m_svcSettingsMap.get(settingName); + if (value == null) + { + System.err.println("SvcConfig.getSetting()- Did not find setting " + settingName); + + // The setting is not in our map, check if it is one to + // which we have defaults. + if (settingName.equals(SessionTokenLifetime) == true) + { + value = m_defaultSessionTokenLifetimeValue; + System.err.println("SvcConfig.getSetting()- Assigning default value " + value); + + // Add the key to the map so that it can be found quicker next time + m_svcSettingsMap.put(SessionTokenLifetime, m_defaultSessionTokenLifetimeValue); + } + else if (settingName.equals(LifetimeShorter) == true) + { + value = m_defaultLifetimeShorterValue; + System.err.println("SvcConfig.getSetting()- Assigning default value " + value); + + // Add the key to the map so that it can be found quicker next time + m_svcSettingsMap.put(LifetimeShorter, m_defaultLifetimeShorterValue); + } + else if (settingName.equals(IdentityAbstractionConfigFile) == true) + { + System.err.println("SvcConfig.getSetting()- Mandatory setting " + IdentityAbstractionConfigFile + " not set"); + throw new Exception("Missing mandatory configuration setting"); + } + else if (settingName.equals(StartSearchContext) == true) + { + System.err.println("SvcConfig.getSetting()- Mandatory setting " + StartSearchContext + " not set"); + throw new Exception("Missing mandatory configuration setting"); + } + } + else + { + System.err.println("SvcConfig.getSetting()- Found setting " + settingName); + System.err.println("SvcConfig.getSetting()- Setting value = " + value); + + // Do some sanity checking + // tbd - Make sure that the token lifetime values are greater than the LifetimeShorter + } + + return value; + } +} \ No newline at end of file