diff --git a/CASA-auth-token/server-java/Jaas/linux/client_keystore_setup.sh b/CASA-auth-token/server-java/Jaas/linux/client_keystore_setup.sh index 3b1239ec..271e8031 100755 --- a/CASA-auth-token/server-java/Jaas/linux/client_keystore_setup.sh +++ b/CASA-auth-token/server-java/Jaas/linux/client_keystore_setup.sh @@ -34,17 +34,26 @@ # # ############################################################# +SILENT=0 +if [ "$1" != "" ]; then + if [ "$1" == "-s" ]; then + SILENT=1 + fi +fi + if [ -d /usr/lib64 ]; then - LIB=lib64 + LIB=lib64 else - LIB=lib + LIB=lib fi JAVA_HOME=/usr/$LIB/jvm/jre-1.5.0 # Do not do anything if the client keystore has already been created if [ -f /etc/CASA/authtoken/keys/client/jks-store ]; then - echo "The client keystore is already setup" + if [ $SILENT == 0 ]; then + echo "The client keystore is already setup" + fi else if [ -f /etc/CASA/authtoken/keys/casaatsdSigningCert ]; then echo "Setting up the clients's keystore" diff --git a/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/CasaLoginModule.java b/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/CasaLoginModule.java index 8b3c5377..ab9aa626 100644 --- a/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/CasaLoginModule.java +++ b/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/CasaLoginModule.java @@ -47,7 +47,7 @@ import com.novell.casa.authtoksvc.CasaIdentityToken; * infrastructure. * */ -public class CasaLoginModule implements LoginModule +public final class CasaLoginModule implements LoginModule { private final static String casaUsername = "CasaIdentityUser"; diff --git a/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/CasaPrincipal.java b/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/CasaPrincipal.java index 7628cf78..71ea028b 100644 --- a/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/CasaPrincipal.java +++ b/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/CasaPrincipal.java @@ -35,12 +35,12 @@ import com.novell.casa.authtoksvc.IdentityToken; * identities authenticated by Casa. * */ -public class CasaPrincipal implements Principal +public final class CasaPrincipal implements Principal { - private String m_name; - private String m_realm; - private String m_identStoreUrl; - private javax.naming.directory.Attributes m_attributes; + private final String m_name; + private final String m_realm; + private final String m_identStoreUrl; + private final javax.naming.directory.Attributes m_attributes; /* * Constructor @@ -58,7 +58,7 @@ public class CasaPrincipal implements Principal * (non-Javadoc) * @see java.security.Principal#getName() */ - public String getName() + public final String getName() { return m_name; } @@ -66,7 +66,7 @@ public class CasaPrincipal implements Principal /* * Returns the name associated with the source of the identity data. */ - public String getRealm() + public final String getRealm() { return m_realm; } @@ -74,7 +74,7 @@ public class CasaPrincipal implements Principal /* * Returns the url associated with the source of the identity data. */ - public String getIdentStoreUrl() + public final String getIdentStoreUrl() { return m_identStoreUrl; } @@ -82,7 +82,7 @@ public class CasaPrincipal implements Principal /* * Returns the identity attributes. */ - public javax.naming.directory.Attributes getAttributes() + public final javax.naming.directory.Attributes getAttributes() { return m_attributes; } diff --git a/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/sample/SampleApp.java b/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/sample/SampleApp.java index 0cd43c85..3f1f85e8 100644 --- a/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/sample/SampleApp.java +++ b/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/sample/SampleApp.java @@ -44,7 +44,7 @@ import com.novell.casa.jaas.CasaPrincipal; * This is a sample application which demonstrates the use of * JAAS and Casa to authenticate a connection. */ -public class SampleApp +public final class SampleApp { /** * @param args diff --git a/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/sample/SampleAppCallbackHandler.java b/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/sample/SampleAppCallbackHandler.java index 990ec5b2..b7f644b3 100644 --- a/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/sample/SampleAppCallbackHandler.java +++ b/CASA-auth-token/server-java/Jaas/src/com/novell/casa/jaas/sample/SampleAppCallbackHandler.java @@ -33,9 +33,9 @@ import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; -public class SampleAppCallbackHandler implements CallbackHandler +public final class SampleAppCallbackHandler implements CallbackHandler { - private String m_authToken; + private final String m_authToken; /* * Constructor @@ -46,7 +46,7 @@ public class SampleAppCallbackHandler implements CallbackHandler m_authToken = authToken; } - public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + public final void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) { diff --git a/CASA-auth-token/server-java/Svc/Makefile.am b/CASA-auth-token/server-java/Svc/Makefile.am index 16fcb79c..77e816fb 100644 --- a/CASA-auth-token/server-java/Svc/Makefile.am +++ b/CASA-auth-token/server-java/Svc/Makefile.am @@ -75,6 +75,7 @@ JAVAFILES = src/com/novell/casa/authtoksvc/ProtoDefs.java \ src/com/novell/casa/authtoksvc/PwdAuthenticate.java \ src/com/novell/casa/authtoksvc/IVerifySetting.java \ src/com/novell/casa/authtoksvc/SettingsFileUtil.java \ + src/com/novell/casa/authtoksvc/SettingsFileSAXHandler.java \ src/com/novell/casa/authtoksvc/AuthPolicyEditor.java \ src/com/novell/casa/authtoksvc/AuthTokenSettingsEditor.java \ src/com/novell/casa/authtoksvc/IdenTokenSettingsEditor.java \ diff --git a/CASA-auth-token/server-java/Svc/TODO b/CASA-auth-token/server-java/Svc/TODO index 2b7224bd..24cb6267 100644 --- a/CASA-auth-token/server-java/Svc/TODO +++ b/CASA-auth-token/server-java/Svc/TODO @@ -10,6 +10,7 @@ This file contains a list of the items still outstanding for AuthTokenSvc. OUTSTANDING ITEMS +- CasaIdentityToken needs to obtain the identity source url from the identity abstraction layer. - Switch Client/Server communication to use SOAP.(This is under evaluation). - Add code to verify that client/server communications occur over HTTPS. - Add logging. diff --git a/CASA-auth-token/server-java/Svc/linux/CasaAuthtokenSvcD b/CASA-auth-token/server-java/Svc/linux/CasaAuthtokenSvcD index 0ae40db3..98a04136 100644 --- a/CASA-auth-token/server-java/Svc/linux/CasaAuthtokenSvcD +++ b/CASA-auth-token/server-java/Svc/linux/CasaAuthtokenSvcD @@ -28,7 +28,7 @@ # X-UnitedLinux-Should-Start: $named $syslog $time # Required-Stop: $local_fs $remote_fs $network # X-UnitedLinux-Should-Stop: $named $syslog $time -# Default-Start: 1 2 3 5 +# Default-Start: 2 3 5 # Default-Stop: # Short-Description: Casa Authtoken Service Daemon # Description: Start Casa Authtoken Service Daemon diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthMechConfig.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthMechConfig.java index 7f27b21c..656472ae 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthMechConfig.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthMechConfig.java @@ -51,155 +51,6 @@ public final class AuthMechConfig private final Map m_mechSettingsMap; - /** - * Class for handling parsing events. - */ - private static final 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 final Map m_keyMap; - private int m_state; - private String m_currentKey; - - /** - * Constructor. - * - * @param keyMap Key/Value map. - */ - public SAXHandler(Map keyMap) - { - super(); - - // Initialize our members - m_keyMap = keyMap; - m_state = AWAITING_ROOT_ELEMENT_START; - } - - /** - * endDocument() implementation. - * - * @throws SAXException - */ - public void endDocument () throws SAXException - { - // Verify that we are not in an invalid state - if (m_state != DONE_PARSING) - { - System.err.println("AuthMechConfig SAXHandler.endDocument()- Invalid state" + m_state); - throw new SAXException("Invalid state at endDocument"); - } - } - - /** - * startElement() implementation. - * - * @param uri Uri. - * @param name Local name. - * @param qName Qualified name. - * @param atts Attributes. - * @throws SAXException - */ - 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("AuthMechConfig 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("AuthMechConfig SAXHandler.startElement()- Invalid state " + m_state); - throw new SAXException("Invalid state at startElement"); - } - } - - /** - * endElement() implementation. - * - * @param uri Uri. - * @param name Local name. - * @param qName Qualified name. - * @throws SAXException - */ - public void endElement (String uri, String name, String qName) throws SAXException - { - // Proceed based on our state - switch (m_state) - { - case AWAITING_SETTING_ELEMENT_DATA: - 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("AuthMechConfig SAXHandler.endElement()- Un-expected element"); - throw new SAXException("Un-expected element"); - } - break; - - default: - System.err.println("AuthMechConfig SAXHandler.endElement()- Invalid state " + m_state); - throw new SAXException("Invalid state at endElement"); - } - } - - /** - * character() implementation. - * - * @param ch Characters with element data. - * @param start Start position in the character array. - * @param length Number of characters to use in the array. - * @throws SAXException - */ - 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. */ @@ -224,22 +75,21 @@ public final class AuthMechConfig // Create a map to keep track of the token settings m_mechSettingsMap = new HashMap(); + FileInputStream inStream = null; try { // Get an input stream to read from the token settings file File f = new File(mechSettingsFileName); - FileInputStream inStream = new FileInputStream(f); + inStream = new FileInputStream(f); // Parse the file XMLReader xr = XMLReaderFactory.createXMLReader(); - SAXHandler handler = new SAXHandler(m_mechSettingsMap); + SettingsFileSAXHandler handler = new SettingsFileSAXHandler(m_mechSettingsMap); xr.setContentHandler(handler); xr.setErrorHandler(handler); InputSource source = new InputSource(inStream); xr.parse(source); - - inStream.close(); } catch (SAXException e) { @@ -261,6 +111,20 @@ public final class AuthMechConfig System.err.println("AuthMechConfig()- IOException accessing " + mechSettingsFileName + " Exception=" + e.toString()); throw new Exception("AuthMechConfig()- Read error"); } + finally + { + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } } /** diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthPolicyEditor.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthPolicyEditor.java index 5b6ab76e..7a6f7ad2 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthPolicyEditor.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthPolicyEditor.java @@ -104,6 +104,7 @@ public final class AuthPolicyEditor private static boolean updateFile(String filePath, Document doc) { boolean result = false; + FileOutputStream out = null; // Update the file with the specified document // after removing the text nodes. @@ -125,11 +126,10 @@ public final class AuthPolicyEditor // Update file File f = new File(filePath); - FileOutputStream out = new FileOutputStream(f); + out = new FileOutputStream(f); OutputFormat format = new OutputFormat(doc); XMLSerializer serializer = new XMLSerializer(out, format); serializer.serialize(doc.getDocumentElement()); - out.close(); result = true; } @@ -141,6 +141,21 @@ public final class AuthPolicyEditor { System.out.println("SecurityException writting to file " + filePath); } + finally + { + if (out != null) + { + try + { + out.flush(); + out.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } return result; } @@ -154,19 +169,18 @@ public final class AuthPolicyEditor private static Document getPolicyFileDoc(String filePath) { Document doc = null; + FileInputStream inStream = null; try { // Get an input stream to read from policy file File f = new File(filePath); - FileInputStream inStream = new FileInputStream(f); + inStream = new FileInputStream(f); InputSource source = new InputSource(inStream); DOMParser parser = new DOMParser(); parser.parse(source); doc = parser.getDocument(); - - inStream.close(); } catch (FileNotFoundException e) { @@ -184,6 +198,20 @@ public final class AuthPolicyEditor { System.err.println("Policy file " + filePath + " format error"); } + finally + { + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } return doc; } @@ -196,21 +224,35 @@ public final class AuthPolicyEditor private static Document getPolicyDoc() { Document doc = null; + StringReader reader = null; try { - StringReader reader = new StringReader(initialPolicy); + reader = new StringReader(initialPolicy); InputSource source = new InputSource(reader); DOMParser parser = new DOMParser(); parser.parse(source); doc = parser.getDocument(); - reader.close(); } catch (Exception e) { System.err.println("Program error, exception: " + e.toString()); } + finally + { + if (reader != null) + { + try + { + reader.close(); + } + catch (Exception e) + { + // Do nothing + } + } + } return doc; } @@ -286,17 +328,18 @@ public final class AuthPolicyEditor Document doc = getPolicyDoc(); if (doc != null) { + FileOutputStream out = null; + try { File f = new File(filePath); boolean createStatus = f.createNewFile(); if (createStatus == true) { - FileOutputStream out = new FileOutputStream(f); + out = new FileOutputStream(f); OutputFormat format = new OutputFormat(doc); XMLSerializer serializer = new XMLSerializer(out, format); serializer.serialize(doc.getDocumentElement()); - out.close(); opPerformed = true; } @@ -313,6 +356,21 @@ public final class AuthPolicyEditor { System.out.println("SecurityException creating " + filePath); } + finally + { + if (out != null) + { + try + { + out.flush(); + out.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } } return opPerformed; diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthReqMsg.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthReqMsg.java index 6da153f3..88ae1b08 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthReqMsg.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthReqMsg.java @@ -25,6 +25,7 @@ package com.novell.casa.authtoksvc; import java.io.InputStream; +import java.util.Arrays; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -51,7 +52,7 @@ public final class AuthReqMsg { protected String m_realm = null; - protected String m_authMechToken = null; + protected char[] m_authMechToken = null; protected String m_authMechanism = null; /** @@ -73,7 +74,7 @@ public final class AuthReqMsg private final static int DONE_PARSING = 11; private final AuthReqMsg m_authReqMsg; - private int m_state; + private int m_state; /** * Constructor. @@ -250,7 +251,7 @@ public final class AuthReqMsg break; default: - System.err.println("AuthReqMsg SAXHandler.startElement()- State error"); + System.err.println("AuthReqMsg SAXHandler.endElement()- State error"); throw new SAXException("State error"); } } @@ -296,7 +297,15 @@ public final class AuthReqMsg case AWAITING_AUTH_MECH_TOKEN_DATA: // Consume the data - m_authReqMsg.m_authMechToken = new String(ch, start, length); + // + // Allocate array to consume the data + m_authReqMsg.m_authMechToken = new char[length]; + + // Copy the data to the newly allocated array + System.arraycopy(ch, start, m_authReqMsg.m_authMechToken, 0, length); + + // Clear the token data in the source array for security purposes + Arrays.fill(ch, start, start + length, ' '); // Advance to the next state m_state = AWAITING_AUTH_MECH_TOKEN_ELEMENT_END; @@ -304,7 +313,24 @@ public final class AuthReqMsg case AWAITING_AUTH_MECH_TOKEN_ELEMENT_END: // Consume the data - m_authReqMsg.m_authMechToken = m_authReqMsg.m_authMechToken.concat(new String(ch, start, length)); + // + // Allocate array to contain the already consumed data and the + // data to be consumed. + char[] newSink = new char[m_authReqMsg.m_authMechToken.length + length]; + + // Copy the already consumed data and the data to be consumed to the + // newly allocated array. + System.arraycopy(m_authReqMsg.m_authMechToken, 0, newSink, 0, m_authReqMsg.m_authMechToken.length); + System.arraycopy(ch, start, newSink, m_authReqMsg.m_authMechToken.length, length); + + // Clear the token data in the previous data sink for security purposes + Arrays.fill(m_authReqMsg.m_authMechToken, ' '); + + // Keep track of the new token data sink array + m_authReqMsg.m_authMechToken = newSink; + + // Clear the token data in the source array for security purposes + Arrays.fill(ch, start, start + length, ' '); break; default: @@ -340,6 +366,35 @@ public final class AuthReqMsg } } + /** + * Method to cleanup resources associated with the object. This + * method needs to be executed for objects that are no longer of + * use for security reasons. + */ + public void cleanup() + { + // Clear the token data if present + if (m_authMechToken != null) + Arrays.fill(m_authMechToken, ' '); + } + + /** + * Finalize method. + * + * @throws Throwable + */ + protected void finalize() throws Throwable + { + try + { + cleanup(); + } + finally + { + super.finalize(); + } + } + /** * Method to get the authentication realm. * @@ -355,7 +410,7 @@ public final class AuthReqMsg * * @return Authentication mechanism token. */ - public String getAuthMechToken() + public char[] getAuthMechToken() { return m_authMechToken; } diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthToken.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthToken.java index 120c0860..d3717204 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthToken.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthToken.java @@ -97,6 +97,7 @@ public final class AuthToken AuthTokenConfig authTokenConfig = enabledSvcsConfig.getAuthTokenConfig(targetHost, targetService); if (authTokenConfig != null) { + OutputStream outStream = null; try { // For now lets use the services of the only IdentityToken provider @@ -128,16 +129,29 @@ public final class AuthToken //XMLUtils.PrettyElementToWriter(authTokenMessage.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out)); // Now save the message as a string - OutputStream outStream = new ByteArrayOutputStream(); + outStream = new ByteArrayOutputStream(); authTokenMessage.writeTo(outStream); m_token = outStream.toString(); - outStream.close(); } catch (Exception e) { // tbd System.err.println("AuthToken()- Exception: " + e.toString()); } + finally + { + if (outStream != null) + { + try + { + outStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } } else { @@ -163,17 +177,32 @@ public final class AuthToken m_token = token; // Now instantiate a SOAP message with the string - InputStream inStream = new ByteArrayInputStream(m_token.getBytes()); - org.apache.axis.Message message; + InputStream inStream = null; + org.apache.axis.Message message = null; try { + inStream = new ByteArrayInputStream(m_token.getBytes()); message = new Message(inStream); - - } catch (Exception e) + } + catch (Exception e) { System.err.println("AuthToken()- Exception caught creating message, msg: " + e.getMessage()); throw new Exception("Invalid Authentication Token"); } + finally + { + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } // Get access to the SOAP Envelope SOAPEnvelope envelope = message.getSOAPEnvelope(); @@ -230,13 +259,14 @@ public final class AuthToken boolean includeCert) { Message secureMessage; + InputStream inStream = null; try { // Build SOAP Message with an identity token in the body // // First create a message and obtain its body - InputStream inStream = new ByteArrayInputStream(authTokenSoapMsg.getBytes()); + inStream = new ByteArrayInputStream(authTokenSoapMsg.getBytes()); Message message = new Message(inStream); message.setMessageContext(axisMsgContext); SOAPBody body = (SOAPBody) message.getSOAPBody(); @@ -268,6 +298,17 @@ public final class AuthToken System.out.println("AuthToken.getMessage() - Exception caught building message, error: " + e.getMessage()); secureMessage = null; } + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } return secureMessage; } diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthTokenConfig.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthTokenConfig.java index f7fd136e..80a6430e 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthTokenConfig.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/AuthTokenConfig.java @@ -46,161 +46,17 @@ public final class AuthTokenConfig public final static String IdentityTokenType = "IdentityTokenType"; // Default configuration values - private final String m_defaultTokenLifetimeValue = "3600"; // Seconds - private final String m_defaultLifetimeShorterValue = "5"; // Seconds - private final String m_defaultIdentityTokenTypeValue = "CasaIdentityToken"; + private final static String m_defaultTokenLifetimeValue = "3600"; // Seconds + private final static String m_defaultLifetimeShorterValue = "5"; // Seconds + private final static String m_defaultIdentityTokenTypeValue = "CasaIdentityToken"; + + // Minimum configuration values + private final static int m_minimumTokenLifetimeValue = 30; // Seconds + private final static int m_minimumLifetimeShorterValue = 5; // Seconds + private final static int m_minimumLifetimeShorterDifferential = 15; private final Map m_tokenSettingsMap; - /** - * Class for handling parsing events. - */ - private static final 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 final Map m_keyMap; - private int m_state; - private String m_currentKey; - - /** - * Constructor. - * - * @param keyMap Key/Value pair map. - */ - public SAXHandler(Map keyMap) - { - super(); - - // Initialize our members - m_keyMap = keyMap; - m_state = AWAITING_ROOT_ELEMENT_START; - } - - /** - * endDocument() implementation. - * - * @throws SAXException - */ - 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. - * - * @param uri Uri. - * @param name Local name. - * @param qName Qualified name. - * @param atts Attributes. - * @throws SAXException - */ - 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. - * - * @param uri Uri. - * @param name Local name. - * @param qName Qualified name. - * @throws SAXException - */ - public void endElement (String uri, String name, String qName) throws SAXException - { - // Proceed based on our state - switch (m_state) - { - case AWAITING_SETTING_ELEMENT_DATA: - 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. - * - * @param ch Characters with element data. - * @param start Start position in the character array. - * @param length Number of characters to use in the array. - * @throws SAXException - */ - 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. */ @@ -230,22 +86,80 @@ public final class AuthTokenConfig // Create a map to keep track of the token settings m_tokenSettingsMap = new HashMap(); + FileInputStream inStream = null; try { // Get an input stream to read from the token settings file File f = new File(authTokenSettingsFileName); - FileInputStream inStream = new FileInputStream(f); + inStream = new FileInputStream(f); // Parse the file XMLReader xr = XMLReaderFactory.createXMLReader(); - SAXHandler handler = new SAXHandler(m_tokenSettingsMap); + SettingsFileSAXHandler handler = new SettingsFileSAXHandler(m_tokenSettingsMap); xr.setContentHandler(handler); xr.setErrorHandler(handler); InputSource source = new InputSource(inStream); xr.parse(source); - inStream.close(); + // Do some sanity checking + int tokenLifetime; + try + { + tokenLifetime = Integer.valueOf(getSetting(TokenLifetime)).intValue(); + if (tokenLifetime < m_minimumTokenLifetimeValue) + { + System.err.println("AuthTokenConfig()- Configured token lifetime too small, defaulting to " + + Integer.toString(m_minimumTokenLifetimeValue) + " seconds"); + tokenLifetime = m_minimumTokenLifetimeValue; + + // Update the map with the new value for the setting + m_tokenSettingsMap.put(TokenLifetime, Integer.toString(tokenLifetime)); + } + } + catch (NumberFormatException e) + { + System.err.println("AuthTokenConfig()- Invalid configured token lifetime value, defaulting to " + + Integer.toString(m_minimumTokenLifetimeValue) + " seconds"); + tokenLifetime = m_minimumTokenLifetimeValue; + + // Update the map with the new value for the setting + m_tokenSettingsMap.put(TokenLifetime, Integer.toString(tokenLifetime)); + } + + int lifetimeShorter; + try + { + lifetimeShorter = Integer.valueOf(getSetting(LifetimeShorter)).intValue(); + if (lifetimeShorter < m_minimumLifetimeShorterValue) + { + System.err.println("AuthTokenConfig()- Configured lifetime shorter too small, defaulting to " + + Integer.toString(m_minimumLifetimeShorterValue) + " seconds"); + lifetimeShorter = m_minimumLifetimeShorterValue; + + // Update the map with the new value for the setting + m_tokenSettingsMap.put(LifetimeShorter, Integer.toString(lifetimeShorter)); + } + } + catch (NumberFormatException e) + { + System.err.println("AuthTokenConfig()- Invalid configured lifetime shorter value, defaulting to " + + Integer.toString(m_minimumLifetimeShorterValue) + " seconds"); + lifetimeShorter = m_minimumLifetimeShorterValue; + + // Update the map with the new value for the setting + m_tokenSettingsMap.put(LifetimeShorter, Integer.toString(lifetimeShorter)); + } + + if (lifetimeShorter > tokenLifetime + || (tokenLifetime - lifetimeShorter) < m_minimumLifetimeShorterDifferential) + { + System.err.println("AuthTokenConfig()- Invalid lifetime shorter value, defaulting to " + + Integer.toString(m_minimumLifetimeShorterValue) + " seconds"); + + // Update the map with the new value for the setting + m_tokenSettingsMap.put(LifetimeShorter, Integer.toString(m_minimumLifetimeShorterValue)); + } } catch (SAXException e) { @@ -267,6 +181,20 @@ public final class AuthTokenConfig System.err.println("AuthTokenConfig()- IOException accessing " + authTokenSettingsFileName + " Exception=" + e.toString()); throw new Exception("AuthTokenConfig()- Read error"); } + finally + { + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } } /** @@ -314,9 +242,6 @@ public final class AuthTokenConfig { 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; diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Authenticate.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Authenticate.java index 8b2533b3..87dd5486 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Authenticate.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Authenticate.java @@ -86,6 +86,11 @@ public final class Authenticate implements RpcMethod { for (int i = 0; i < mechanismsConfigFolderObjs.length; i++) { + FileOutputStream fos = null; + ObjectOutputStream oos = null; + FileInputStream fis = null; + ObjectInputStream ois = null; + // Check if we are dealing with a file or a folder File mechanismFolder = new File(mechanismsConfigFolder, mechanismsConfigFolderObjs[i]); try @@ -125,17 +130,13 @@ public final class Authenticate implements RpcMethod // Load the mech class using our custom loader Class mechClass = customClassLoader.loadClass(mechClassName); - FileOutputStream fos = new FileOutputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp"); - ObjectOutputStream oos = new ObjectOutputStream(fos); + fos = new FileOutputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp"); + oos = new ObjectOutputStream(fos); oos.writeObject(mechClass); - oos.close(); - fos.close(); - FileInputStream fis = new FileInputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp"); - ObjectInputStream ois = new ObjectInputStream(fis); + fis = new FileInputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp"); + ois = new ObjectInputStream(fis); mechClass = (Class) ois.readObject(); - ois.close(); - fis.close(); - + // Now reload the class using the class loader for our AuthMechanism class AuthMechanism mechanism = (AuthMechanism) mechClass.newInstance(); mechanism.init(svcConfig, mechConfig); @@ -179,16 +180,12 @@ public final class Authenticate implements RpcMethod // Load the mech class using our custom loader Class mechClass = customClassLoader.loadClass(mechClassName); - FileOutputStream fos = new FileOutputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp"); - ObjectOutputStream oos = new ObjectOutputStream(fos); + fos = new FileOutputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp"); + oos = new ObjectOutputStream(fos); oos.writeObject(mechClass); - oos.close(); - fos.close(); - FileInputStream fis = new FileInputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp"); - ObjectInputStream ois = new ObjectInputStream(fis); + fis = new FileInputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp"); + ois = new ObjectInputStream(fis); mechClass = (Class) ois.readObject(); - ois.close(); - fis.close(); // Now reload the class using the class loader for our AuthMechanism class AuthMechanism mechanism = (AuthMechanism) mechClass.newInstance(); @@ -245,6 +242,55 @@ public final class Authenticate implements RpcMethod { System.err.println("Authenticate.init()- SecurityException accessing " + mechanismFolder + " Exception=" + e.toString()); } + finally + { + if (fos != null) + { + try + { + fos.flush(); + fos.close(); + } + catch (IOException e) + { + // Do nothing + } + } + if (oos != null) + { + try + { + oos.flush(); + oos.close(); + } + catch (IOException e) + { + // Do nothing + } + } + if (fis != null) + { + try + { + fis.close(); + } + catch (IOException e) + { + // Do nothing + } + } + if (ois != null) + { + try + { + ois.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } } } else @@ -262,16 +308,18 @@ public final class Authenticate implements RpcMethod * Process Rpc. * * @param inStream Input data stream (Request data). - * @param out Output data print writter (Reply data). + * @param out Output data print writer (Reply data). */ public final void invoke(InputStream inStream, PrintWriter out) { + AuthReqMsg authReqMsg = null; + try { System.err.println("Authenticate.invoke()"); // Parse the AuthReqMsg sent from the client - AuthReqMsg authReqMsg = new AuthReqMsg(inStream); + authReqMsg = new AuthReqMsg(inStream); // Get the necessary authentication mechanism AuthMechanism authMechanism = m_authMechanismMap.get(authReqMsg.getMechanismId()); @@ -336,6 +384,13 @@ public final class Authenticate implements RpcMethod System.err.println("Authenticate.invoke()- Exception trying to construct response msg: " + e2.toString()); } } + finally + { + // Make sure to invoke the cleanup method on the AuthReqMsg to + // deal with security sensitive data. + if (authReqMsg != null) + authReqMsg.cleanup(); + } } /** diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/CasaIdentityToken.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/CasaIdentityToken.java index 71e16127..e4efd243 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/CasaIdentityToken.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/CasaIdentityToken.java @@ -25,6 +25,7 @@ package com.novell.casa.authtoksvc; import java.io.ByteArrayInputStream; +import java.io.IOException; import java.util.Hashtable; import javax.naming.Context; @@ -33,6 +34,7 @@ import javax.naming.NamingException; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; +import javax.naming.directory.Attribute; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -120,12 +122,13 @@ public final class CasaIdentityToken implements IdentityToken private final static int AWAITING_ATTRIBUTE_END = 19; private final static int AWAITING_ATTRIBUTE_DATA = 20; private final static int AWAITING_BINARY_ATTRIBUTE_DATA = 21; - private final static int DONE_PARSING = 22; + private final static int AWAITING_BINARY_ATTRIBUTE_END = 22; + private final static int DONE_PARSING = 23; private final CasaIdentityToken m_casaIdentToken; - private int m_state; - private String m_currAttribute; - private boolean m_encryptedAttrs; + private int m_state; + private String m_currAttribute; + private boolean m_encryptedAttrs; /** * Constructor. @@ -398,6 +401,40 @@ public final class CasaIdentityToken implements IdentityToken m_state = AWAITING_ATTRIBUTE_START; break; + case AWAITING_BINARY_ATTRIBUTE_END: + // Decode the attribute data since it is base64 encoded + Attribute attrib = m_casaIdentToken.m_attributes.remove(m_currAttribute); + if (attrib != null) + { + try + { + char[] attribData = (char[]) attrib.get(); + if (attribData != null) + { + m_casaIdentToken.m_attributes.put(m_currAttribute, Base64Coder.decode(attribData)); + } + else + { + System.err.println("CasaIdentityToken SAXHandler.endElement()- Attribute data not found"); + throw new SAXException("Attribute data not found"); + } + } + catch (NamingException e) + { + System.err.println("CasaIdentityToken SAXHandler.endElement()- Attribute data not found"); + throw new SAXException("Attribute data not found"); + } + } + else + { + System.err.println("CasaIdentityToken SAXHandler.endElement()- Attribute not found"); + throw new SAXException("Attribute not found"); + } + + // Advance to the next state + m_state = AWAITING_ATTRIBUTE_START; + break; + case AWAITING_ATTRIBUTE_START: // Verify that we are processing the expected tag if (attributesElementName.equals(qName)) @@ -413,7 +450,7 @@ public final class CasaIdentityToken implements IdentityToken break; default: - System.err.println("CasaIdentityToken SAXHandler.startElement()- State error"); + System.err.println("CasaIdentityToken SAXHandler.endElement()- State error"); throw new SAXException("State error"); } } @@ -498,6 +535,49 @@ public final class CasaIdentityToken implements IdentityToken m_state = AWAITING_ATTRIBUTE_END; break; + case AWAITING_ATTRIBUTE_END: + // Consume the data + // + // Decrypt the attribute data if necessary + if (m_encryptedAttrs) + { + // tbd - Decrypt the attribute key and value with the private key of the service + // using the configured mechanism. + } + else + { + // Append the data to what we have already consumed + Attribute attrib = m_casaIdentToken.m_attributes.remove(m_currAttribute); + if (attrib != null) + { + try + { + String attribData = (String) attrib.get(); + if (attribData != null) + { + m_casaIdentToken.m_attributes.put(m_currAttribute, + attribData.concat(new String(ch, start, length))); + } + else + { + System.err.println("CasaIdentityToken SAXHandler.characters()- Attribute data not found"); + throw new SAXException("Attribute data not found"); + } + } + catch (NamingException e) + { + System.err.println("CasaIdentityToken SAXHandler.characters()- Attribute data not found"); + throw new SAXException("Attribute data not found"); + } + } + else + { + System.err.println("CasaIdentityToken SAXHandler.characters()- Attribute not found"); + throw new SAXException("Attribute not found"); + } + } + break; + case AWAITING_BINARY_ATTRIBUTE_DATA: // Consume the data // @@ -509,14 +589,63 @@ public final class CasaIdentityToken implements IdentityToken } else { - // The data is base64 encoded + // We are dealing with base64 encoded data char[] encodedChars = new char[length]; System.arraycopy(ch, start, encodedChars, 0, length); - m_casaIdentToken.m_attributes.put(m_currAttribute, Base64Coder.decode(encodedChars)); + m_casaIdentToken.m_attributes.put(m_currAttribute, encodedChars); } // Advance to the next state - m_state = AWAITING_ATTRIBUTE_END; + m_state = AWAITING_BINARY_ATTRIBUTE_END; + break; + + case AWAITING_BINARY_ATTRIBUTE_END: + // Consume the data + // + // Decrypt the attribute data if necessary + if (m_encryptedAttrs) + { + // tbd - Decrypt the attribute key and value with the private key of the service + // using the configured mechanism. + } + else + { + // Append the data to what we have already consumed + Attribute attrib = m_casaIdentToken.m_attributes.remove(m_currAttribute); + if (attrib != null) + { + try + { + // We are dealing with base64 encoded data + char[] consumedData = (char[]) attrib.get(); + if (consumedData != null) + { + char[] encodedChars = new char[consumedData.length + length]; + System.arraycopy(consumedData, 0, encodedChars, 0, consumedData.length); + System.arraycopy(ch, start, encodedChars, consumedData.length, length); + m_casaIdentToken.m_attributes.put(m_currAttribute, encodedChars); + } + else + { + System.err.println("CasaIdentityToken SAXHandler.characters()- Attribute data not found"); + throw new SAXException("Attribute data not found"); + } + } + catch (NamingException e) + { + System.err.println("CasaIdentityToken SAXHandler.characters()- Attribute data not found"); + throw new SAXException("Attribute data not found"); + } + } + else + { + System.err.println("CasaIdentityToken SAXHandler.characters()- Attribute not found"); + throw new SAXException("Attribute not found"); + } + } + + // Advance to the next state + m_state = AWAITING_BINARY_ATTRIBUTE_END; break; default: @@ -643,13 +772,13 @@ public final class CasaIdentityToken implements IdentityToken } catch (NamingException e) { - // tbd - Log the event??? System.err.println("CasaIdentityToken.initialize()- Exception: " + e.getExplanation()); + throw new Exception("Error obtaining identity data for token"); } catch (Exception e) { - // tbd - System.err.println("CasaIdentityToken.initialize()- Exception: " + e.toString()); + System.err.println("CasaIdentityToken.initialize()- Exception: " + e.toString()); + throw new Exception("Error obtaining identity data for token"); } } @@ -665,6 +794,7 @@ public final class CasaIdentityToken implements IdentityToken m_token = Base64Coder.decode(encodedToken); // Now parse the token into its elements + ByteArrayInputStream inStream = null; try { // Parse the AuthReqMsg @@ -673,8 +803,7 @@ public final class CasaIdentityToken implements IdentityToken xr.setContentHandler(handler); xr.setErrorHandler(handler); - - ByteArrayInputStream inStream = new ByteArrayInputStream(m_token.getBytes()); + inStream = new ByteArrayInputStream(m_token.getBytes()); InputSource source = new InputSource(inStream); xr.parse(source); } @@ -684,6 +813,20 @@ public final class CasaIdentityToken implements IdentityToken System.err.println("CasaIdentityToken()- Parse exception: " + e.toString()); throw new Exception("Token error"); } + finally + { + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } } /** @@ -716,7 +859,6 @@ public final class CasaIdentityToken implements IdentityToken */ public final String getProviderType () throws Exception { - // tbd - Change to a GUID return "CasaIdentityToken"; } diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java index bb413313..f51ba66f 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/EnabledSvcsConfig.java @@ -106,13 +106,13 @@ public final class EnabledSvcsConfig try { // Try to obtain the default authentication policy + FileInputStream inStream = null; try { File f = new File(configFolder, m_authPolicyFileName); m_defaultAuthPolicyData = new byte[(int) f.length()]; - FileInputStream inStream = new FileInputStream(f); + inStream = new FileInputStream(f); int bytesRead = inStream.read(m_defaultAuthPolicyData); - inStream.close(); if (bytesRead != m_defaultAuthPolicyData.length) { System.err.println("EnabledSvcsConfig()- Error reading default policy file"); @@ -130,6 +130,20 @@ public final class EnabledSvcsConfig { System.err.println("EnabledSvcsConfig()- IOException reading " + configFolder + File.separator + m_authPolicyFileName + " Exception=" + e.toString()); } + finally + { + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } // Try to obtain the default authentication token settings try @@ -199,14 +213,14 @@ public final class EnabledSvcsConfig byte[] authPolicyData = null; AuthTokenConfig authTokenConfig = null; IdenTokenConfig idenTokenConfig = null; + inStream = null; try { File policyFile = new File(serviceFolder, m_authPolicyFileName); authPolicyData = new byte[(int) policyFile.length()]; - FileInputStream inStream = new FileInputStream(policyFile); + 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]); @@ -224,6 +238,20 @@ public final class EnabledSvcsConfig { System.err.println("EnabledSvcsConfig()- IOException reading " + serviceFolder + File.separator + m_authPolicyFileName + " Exception=" + e.toString()); } + finally + { + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } try { diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/GetAuthPolicyReqMsg.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/GetAuthPolicyReqMsg.java index a01d7db2..b7c5b375 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/GetAuthPolicyReqMsg.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/GetAuthPolicyReqMsg.java @@ -217,7 +217,7 @@ public final class GetAuthPolicyReqMsg break; default: - System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- State error"); + System.err.println("GetAuthPolicyReqMsg SAXHandler.endElement()- State error"); throw new SAXException("State error"); } } diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/GetAuthTokReqMsg.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/GetAuthTokReqMsg.java index 3766f104..78de08e5 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/GetAuthTokReqMsg.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/GetAuthTokReqMsg.java @@ -72,7 +72,7 @@ public final class GetAuthTokReqMsg private final static int DONE_PARSING = 11; private final GetAuthTokReqMsg m_GetAuthTokReqMsg; - private int m_state; + private int m_state; /** * Constructor. @@ -250,7 +250,7 @@ public final class GetAuthTokReqMsg break; default: - System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- State error"); + System.err.println("GetAuthTokReqMsg SAXHandler.endElement()- State error"); throw new SAXException("State error"); } } diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/GetAuthToken.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/GetAuthToken.java index b8e258f4..97e7d368 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/GetAuthToken.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/GetAuthToken.java @@ -81,11 +81,11 @@ public final class GetAuthToken implements RpcMethod if (m_enabledSvcsConfig.svcEnabled(getAuthTokReqMsg.getHostName(), getAuthTokReqMsg.getServiceName())) { - // Now create a session token (This validates the session token provided). - SessionToken sessionToken = new SessionToken(getAuthTokReqMsg.getSessionToken()); - try { + // Now create a session token (This validates the session token provided). + SessionToken sessionToken = new SessionToken(getAuthTokReqMsg.getSessionToken()); + // Create the Authentication Token AuthToken authToken = new AuthToken(sessionToken.getIdentId(), sessionToken.getRealm(), diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/IdenTokenConfig.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/IdenTokenConfig.java index 28aaf53e..1ac5092f 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/IdenTokenConfig.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/IdenTokenConfig.java @@ -51,156 +51,6 @@ public final class IdenTokenConfig private final Map m_tokenSettingsMap; private String[] m_identityAttributes; - /** - * Class for handling parsing events. - */ - private static final 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 final Map m_keyMap; - private int m_state; - private String m_currentKey; - - /** - * Constructor. - * - * @param keyMap Key/Value map. - */ - public SAXHandler(Map keyMap) - { - super(); - - // Initialize our members - m_keyMap = keyMap; - m_state = AWAITING_ROOT_ELEMENT_START; - } - - /** - * endDocument() implementation. - * - * @throws SAXException - */ - public final 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. - * - * @param uri Uri. - * @param name Local name. - * @param qName Qualified name. - * @param atts Attributes. - * @throws SAXException - */ - public final 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() implementation. - * - * @param uri Uri. - * @param name Local name. - * @param qName Qualified name. - * @throws SAXException - */ - public final void endElement (String uri, String name, String qName) throws SAXException - { - // Proceed based on our state - switch (m_state) - { - case AWAITING_SETTING_ELEMENT_DATA: - 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. - * - * @param ch Characters with element data. - * @param start Start position in the character array. - * @param length Number of characters to use in the array. - * @throws SAXException - */ - public final 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. */ @@ -228,23 +78,22 @@ public final class IdenTokenConfig // Create a map to keep track of the token settings m_tokenSettingsMap = new HashMap(); + FileInputStream inStream = null; try { // Get an input stream to read from the token settings file File f = new File(idenTokenSettingsFileName); - FileInputStream inStream = new FileInputStream(f); + inStream = new FileInputStream(f); // Parse the file XMLReader xr = XMLReaderFactory.createXMLReader(); - SAXHandler handler = new SAXHandler(m_tokenSettingsMap); + SettingsFileSAXHandler handler = new SettingsFileSAXHandler(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) { @@ -274,6 +123,20 @@ public final class IdenTokenConfig System.err.println("IdenTokenConfig()- IOException accessing " + idenTokenSettingsFileName + " Exception=" + e.toString()); throw new Exception("IdenTokenConfig()- Read error"); } + finally + { + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } } /** diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Krb5Authenticate.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Krb5Authenticate.java index a47014f3..01320a11 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Krb5Authenticate.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Krb5Authenticate.java @@ -84,12 +84,10 @@ public final class Krb5Authenticate implements AuthMechanism, Serializable * @param parent Associated Krb5Authenticate object. * @throws Exception */ - public Krb5Token(String encodedToken, Krb5Authenticate parent) throws Exception + public Krb5Token(char[] encodedToken, Krb5Authenticate parent) throws Exception { // Decode the token - char[] tokenChars = new char[encodedToken.length()]; - encodedToken.getChars(0, tokenChars.length, tokenChars, 0); - byte[] tokenBytes = Base64Coder.decode(tokenChars); + byte[] tokenBytes = Base64Coder.decode(encodedToken); try { @@ -227,9 +225,9 @@ public final class Krb5Authenticate implements AuthMechanism, Serializable // Perform the search NamingEnumeration answer = ctx.search(searchContext, - "(krbPrincipalName={0})", - new String[] {krb5Token.getPrincipalName()}, - controls); + "(krbPrincipalName={0})", + new String[] {krb5Token.getPrincipalName()}, + controls); // Proceed based on the result of the search if (answer.hasMore()) diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Makefile.am b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Makefile.am index f92118b9..02d01da0 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Makefile.am +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Makefile.am @@ -55,6 +55,7 @@ JAVAFILES = ProtoDefs.java \ IdenTokenSettingsEditor.java \ IVerifySetting.java \ SettingsFileUtil.java \ + SettingsFileSAXHandler.java \ SvcSettingsEditor.java EXTRA_DIST = $(JAVAFILES) \ diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/PwdAuthenticate.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/PwdAuthenticate.java index ba855571..e55516ea 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/PwdAuthenticate.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/PwdAuthenticate.java @@ -73,18 +73,40 @@ public final class PwdAuthenticate implements AuthMechanism, Serializable * @param encodedToken Base64 encoded password token. * @throws IOException */ - public PwToken(String encodedToken) throws IOException + public PwToken(char[] encodedToken) throws IOException { - // Decode the token - String token = Base64Coder.decode(encodedToken); + BufferedReader tokenReader = null; - BufferedReader tokenReader = new BufferedReader(new StringReader(token)); + try + { + // Decode the token + byte[] tokenBytes = Base64Coder.decode(encodedToken); - // The second line contains the "username" - m_username = tokenReader.readLine(); + // Unfortunately the password has to be passed to JNDI as a String. Given this, + // we are going to go ahead and convert the token to a String to facilitate + // the parsing operation.. + tokenReader = new BufferedReader(new StringReader(tokenBytes.toString())); - // The third line contains the "password" - m_password = tokenReader.readLine(); + // The first line contains the "username" + m_username = tokenReader.readLine(); + + // The second line contains the "password" + m_password = tokenReader.readLine(); + } + finally + { + if (tokenReader != null) + { + try + { + tokenReader.close(); + } + catch (Exception e) + { + // Do nothing + } + } + } } /** diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Rpc.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Rpc.java index d30ed3e0..8fca060c 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Rpc.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/Rpc.java @@ -64,7 +64,7 @@ public final class Rpc extends javax.servlet.http.HttpServlet implements javax.s private final class ReconfigureThread implements Runnable { private final Rpc m_rpc; - private boolean m_run = true; + private volatile boolean m_run = true; /** * Constructor. @@ -269,14 +269,17 @@ public final class Rpc extends javax.servlet.http.HttpServlet implements javax.s */ 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(); + PrintWriter out = null; + InputStream inStream = null; try { + // Get ready to send back a reply + response.setContentType("text/html"); + out = response.getWriter(); + // Obtain the input stream and execute the requested method - InputStream inStream = request.getInputStream(); + inStream = request.getInputStream(); String requestedMethod = request.getParameter("method"); if (requestedMethod != null) @@ -308,8 +311,32 @@ public final class Rpc extends javax.servlet.http.HttpServlet implements javax.s System.err.println("Rpc.doPost()- Exception caught: " + e.toString()); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } + finally + { + if (out != null) + { + try + { + out.flush(); + out.close(); + } + catch (Exception e) + { + // Do nothing + } + } - // Done sending out the reply - out.close(); + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } } } \ No newline at end of file diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SessionToken.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SessionToken.java index ff476a1f..3a1b19dc 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SessionToken.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SessionToken.java @@ -98,10 +98,28 @@ public final class SessionToken svcConfig); // Now save the message as a string - OutputStream outStream = new ByteArrayOutputStream(); - sessionTokenMessage.writeTo(outStream); - m_token = outStream.toString(); - outStream.close(); + OutputStream outStream = null; + try + { + outStream = new ByteArrayOutputStream(); + sessionTokenMessage.writeTo(outStream); + m_token = outStream.toString(); + } + finally + { + if (outStream != null) + { + try + { + outStream.flush(); + outStream.close(); + } + catch (Exception e) + { + // Do nothing + } + } + } } /** @@ -113,48 +131,67 @@ public final class SessionToken */ public SessionToken(String token) throws Exception { - // Decode the token string - m_token = Base64Coder.decode(token); + InputStream inStream = null; - // Now instantiate a SOAP message with the string - InputStream inStream = new ByteArrayInputStream(m_token.getBytes()); - Message message = new Message(inStream); - - // Get access to the SOAP Envelope - SOAPEnvelope envelope = message.getSOAPEnvelope(); - - // Verify the message - if (WSSecurity.verifyMessage(envelope)) + try { - // Message verification succeded, now obtain the realm and identity id - // from the message body. - SOAPBody body = (SOAPBody) envelope.getBody(); - QName sessionTokenElementName = new QName("session_token"); - MessageElement sessionTokenElement = body.getChildElement(sessionTokenElementName); - QName realmElementName = new QName("realm"); - MessageElement realmElement = sessionTokenElement.getChildElement(realmElementName); - if (realmElement != null) - { - m_realm = realmElement.getChildNodes().item(0).getNodeValue(); - } - QName identIdElementName = new QName("ident_id"); - MessageElement identIdElement = sessionTokenElement.getChildElement(identIdElementName); - if (identIdElement != null) - { - m_id = identIdElement.getChildNodes().item(0).getNodeValue(); - } + // Decode the token string + m_token = Base64Coder.decode(token); - if (m_realm == null || m_id == null) + // Now instantiate a SOAP message with the string + inStream = new ByteArrayInputStream(m_token.getBytes()); + Message message = new Message(inStream); + + // Get access to the SOAP Envelope + SOAPEnvelope envelope = message.getSOAPEnvelope(); + + // Verify the message + if (WSSecurity.verifyMessage(envelope)) { - System.out.println("SessionToken()- Required data missing from session token"); - throw new Exception("Error: Required data missing from session Token"); + // Message verification succeded, now obtain the realm and identity id + // from the message body. + SOAPBody body = (SOAPBody) envelope.getBody(); + QName sessionTokenElementName = new QName("session_token"); + MessageElement sessionTokenElement = body.getChildElement(sessionTokenElementName); + QName realmElementName = new QName("realm"); + MessageElement realmElement = sessionTokenElement.getChildElement(realmElementName); + if (realmElement != null) + { + m_realm = realmElement.getChildNodes().item(0).getNodeValue(); + } + QName identIdElementName = new QName("ident_id"); + MessageElement identIdElement = sessionTokenElement.getChildElement(identIdElementName); + if (identIdElement != null) + { + m_id = identIdElement.getChildNodes().item(0).getNodeValue(); + } + + if (m_realm == null || m_id == null) + { + System.out.println("SessionToken()- Required data missing from session token"); + throw new Exception("Error: Required data missing from session Token"); + } + } + else + { + // Message verification failed + System.err.println("SessionToken()- Invalid Session Token"); + throw new Exception("Invalid Session Token"); } } - else + finally { - // Message verification failed - System.err.println("SessionToken()- Invalid Session Token"); - throw new Exception("Invalid Session Token"); + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } } } @@ -173,13 +210,14 @@ public final class SessionToken SvcConfig svcConfig) { Message secureMessage; + InputStream inStream = null; try { // Build SOAP Message with an identity token in the body // // First create a message and obtain its body - InputStream inStream = new ByteArrayInputStream(sessionTokenSoapMsg.getBytes()); + inStream = new ByteArrayInputStream(sessionTokenSoapMsg.getBytes()); Message message = new Message(inStream); message.setMessageContext(axisMsgContext); SOAPBody body = (SOAPBody) message.getSOAPBody(); @@ -211,6 +249,20 @@ public final class SessionToken System.out.println("SessionToken.getMessage() - Exception caught building message, error: " + e.getMessage()); secureMessage = null; } + finally + { + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } return secureMessage; } diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SettingsFileSAXHandler.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SettingsFileSAXHandler.java new file mode 100644 index 00000000..97984b0f --- /dev/null +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SettingsFileSAXHandler.java @@ -0,0 +1,196 @@ +/*********************************************************************** + * + * 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 org.xml.sax.SAXException; + +/** + * Settings file SAXHandler Class. + *

+ * This class provides a SAXHandler for parsing .settings files. + * + */ +public final class SettingsFileSAXHandler 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 final Map m_keyMap; + private int m_state; + private String m_currentKey; + + /** + * Constructor. + * + * @param keyMap Key/Value map. + */ + public SettingsFileSAXHandler(Map keyMap) + { + super(); + + // Initialize our members + m_keyMap = keyMap; + m_state = AWAITING_ROOT_ELEMENT_START; + } + + /** + * endDocument() implementation. + * + * @throws SAXException + */ + public final void endDocument () throws SAXException + { + // Verify that we are not in an invalid state + if (m_state != DONE_PARSING) + { + System.err.println("SettingsFileSAXHandler.endDocument()- Invalid state" + m_state); + throw new SAXException("Invalid state at endDocument"); + } + } + + /** + * startElement() implementation. + * + * @param uri Uri. + * @param name Local name. + * @param qName Qualified name. + * @param atts Attributes. + * @throws SAXException + */ + public final 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("SettingsFileSAXHandler.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("SettingsFileSAXHandler.startElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at startElement"); + } + } + + /** + * endElement() implementation. + * + * @param uri Uri. + * @param name Local name. + * @param qName Qualified name. + * @throws SAXException + */ + public final void endElement (String uri, String name, String qName) throws SAXException + { + // Proceed based on our state + switch (m_state) + { + case AWAITING_SETTING_ELEMENT_DATA: + 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("SettingsFileSAXHandler.endElement()- Un-expected element"); + throw new SAXException("Un-expected element"); + } + break; + + default: + System.err.println("SettingsFileSAXHandler.endElement()- Invalid state " + m_state); + throw new SAXException("Invalid state at endElement"); + } + } + + /** + * character() implementation. + * + * @param ch Characters with element data. + * @param start Start position in the character array. + * @param length Number of characters to use in the array. + * @throws SAXException + */ + public final 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; + } + else if (m_state == AWAITING_SETTING_ELEMENT_END) + { + // Concat this data to the setting data that we have already consumed + String settingData = m_keyMap.remove(m_currentKey); + if (settingData != null) + { + // Consume the data and add the key to map + m_keyMap.put(m_currentKey, settingData.concat(new String(ch, start, length))); + } + else + { + System.err.println("SettingsFileSAXHandler.characters()- Settings data not found"); + throw new SAXException("Settings data not found"); + } + } + } +} diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SettingsFileUtil.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SettingsFileUtil.java index 6cc6a8dd..03574ed7 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SettingsFileUtil.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SettingsFileUtil.java @@ -53,19 +53,18 @@ public final class SettingsFileUtil private static Document getSettingsFileDoc(String filePath) { Document doc; + FileInputStream inStream = null; try { // Get an input stream to read from settings file File f = new File(filePath); - FileInputStream inStream = new FileInputStream(f); + inStream = new FileInputStream(f); InputSource source = new InputSource(inStream); DOMParser parser = new DOMParser(); parser.parse(source); doc = parser.getDocument(); - - inStream.close(); } catch (FileNotFoundException e) { @@ -87,6 +86,20 @@ public final class SettingsFileUtil System.err.println("Settings file " + filePath + " format error"); doc = null; } + finally + { + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } return doc; } @@ -100,21 +113,35 @@ public final class SettingsFileUtil private static Document getSettingsDoc(String settings) { Document doc = null; + StringReader reader = null; try { - StringReader reader = new StringReader(settings); + reader = new StringReader(settings); InputSource source = new InputSource(reader); DOMParser parser = new DOMParser(); parser.parse(source); doc = parser.getDocument(); - reader.close(); } catch (Exception e) { System.err.println("Program error, exception: " + e.toString()); } + finally + { + if (reader != null) + { + try + { + reader.close(); + } + catch (Exception e) + { + // Do nothing + } + } + } return doc; } @@ -160,7 +187,7 @@ public final class SettingsFileUtil * @return True if the operation is successfully performed. */ public static boolean performCreateOperation(String filePath, - String settings) + String settings) { boolean opPerformed = false; @@ -168,17 +195,18 @@ public final class SettingsFileUtil Document doc = getSettingsDoc(settings); if (doc != null) { + FileOutputStream out = null; + try { File f = new File(filePath); boolean createStatus = f.createNewFile(); if (createStatus == true) { - FileOutputStream out = new FileOutputStream(f); + out = new FileOutputStream(f); OutputFormat format = new OutputFormat(doc); XMLSerializer serializer = new XMLSerializer(out, format); serializer.serialize(doc.getDocumentElement()); - out.close(); opPerformed = true; } @@ -195,6 +223,21 @@ public final class SettingsFileUtil { System.out.println("SecurityException creating " + filePath); } + finally + { + if (out != null) + { + try + { + out.flush(); + out.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } } return opPerformed; @@ -307,6 +350,7 @@ public final class SettingsFileUtil } // Update the file after removing the text nodes + FileOutputStream out = null; try { // Remove text nodes @@ -323,11 +367,10 @@ public final class SettingsFileUtil // Update file File f = new File(filePath); - FileOutputStream out = new FileOutputStream(f); + out = new FileOutputStream(f); OutputFormat format = new OutputFormat(doc); XMLSerializer serializer = new XMLSerializer(out, format); serializer.serialize(doc.getDocumentElement()); - out.close(); opPerformed = true; } @@ -339,6 +382,21 @@ public final class SettingsFileUtil { System.out.println("SecurityException writting to file " + filePath); } + finally + { + if (out != null) + { + try + { + out.flush(); + out.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } } } @@ -384,6 +442,7 @@ public final class SettingsFileUtil settingFound = true; // Update the file after removing the text nodes + FileOutputStream out = null; try { // Remove text nodes @@ -400,11 +459,10 @@ public final class SettingsFileUtil // Update file File f = new File(filePath); - FileOutputStream out = new FileOutputStream(f); + out = new FileOutputStream(f); OutputFormat format = new OutputFormat(doc); XMLSerializer serializer = new XMLSerializer(out, format); serializer.serialize(doc.getDocumentElement()); - out.close(); opPerformed = true; } @@ -416,6 +474,21 @@ public final class SettingsFileUtil { System.out.println("SecurityException writting to file " + filePath); } + finally + { + if (out != null) + { + try + { + out.flush(); + out.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } } } diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SvcConfig.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SvcConfig.java index 0b8aa761..2eda8b37 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SvcConfig.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/SvcConfig.java @@ -63,158 +63,15 @@ public final class SvcConfig public final static String DefaultSigningKeyAliasNameValue = "signingKey"; public final static String DefaultSigningKeyPasswordValue = "secret"; + // Minimum configuration values + private final static int MinimumTokenLifetimeValue = 360; // Seconds + private final static int MinimumLifetimeShorterValue = 5; // Seconds + private final static int MinimumLifetimeShorterDifferential = 15; + private final static int MinimumReconfigureIntervalValue = 30; // Seconds + private static final String m_svcSettingsFileName = "svc.settings"; private final Map m_svcSettingsMap; - /** - * Class for handling Authentication Request parsing events. - */ - private static final 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 final Map m_keyMap; - private int m_state; - private String m_currentKey; - - /** - * Constructor. - * - * @param keyMap Key/Value map. - */ - public SAXHandler(Map keyMap) - { - super(); - - // Initialize our members - m_keyMap = keyMap; - m_state = AWAITING_ROOT_ELEMENT_START; - } - - /** - * endDocument() implementation. - * - * @throws SAXException - */ - public final 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. - * - * @param uri Uri. - * @param name Local name. - * @param qName Qualified name. - * @param atts Attributes. - * @throws SAXException - */ - public final 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() implementation. - * - * @param uri Uri. - * @param name Local name. - * @param qName Qualified name. - * @throws SAXException - */ - public final void endElement (String uri, String name, String qName) throws SAXException - { - // Proceed based on our state - switch (m_state) - { - case AWAITING_SETTING_ELEMENT_DATA: - 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. - * - * @param ch Characters with element data. - * @param start Start position in the character array. - * @param length Number of characters to use in the array. - * @throws SAXException - */ - public final 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. * @@ -231,25 +88,106 @@ public final class SvcConfig // Create a map to keep track of the service settings m_svcSettingsMap = new HashMap(); + FileInputStream inStream = null; try { // Get an input stream to services settings file File settingsFile = new File(svcConfigPath, m_svcSettingsFileName); - FileInputStream inStream = new FileInputStream(settingsFile); + inStream = new FileInputStream(settingsFile); // Parse the file XMLReader xr = XMLReaderFactory.createXMLReader(); - SAXHandler handler = new SAXHandler(m_svcSettingsMap); + SettingsFileSAXHandler handler = new SettingsFileSAXHandler(m_svcSettingsMap); xr.setContentHandler(handler); xr.setErrorHandler(handler); InputSource source = new InputSource(inStream); xr.parse(source); - inStream.close(); // Add the application and config folder path settings to our map m_svcSettingsMap.put(AppRootPath, appRootPath); m_svcSettingsMap.put(ConfigFolderPath, svcConfigPath); + + // Do some sanity checking + int tokenLifetime; + try + { + tokenLifetime = Integer.valueOf(getSetting(SessionTokenLifetime)).intValue(); + if (tokenLifetime < MinimumTokenLifetimeValue) + { + System.err.println("SvcConfig()- Configured token lifetime too small, defaulting to " + + Integer.toString(MinimumTokenLifetimeValue) + " seconds"); + tokenLifetime = MinimumTokenLifetimeValue; + + // Update the map with the new value for the setting + m_svcSettingsMap.put(SessionTokenLifetime, Integer.toString(tokenLifetime)); + } + } + catch (NumberFormatException e) + { + System.err.println("SvcConfig()- Invalid configured token lifetime value, defaulting to " + + Integer.toString(MinimumTokenLifetimeValue) + " seconds"); + tokenLifetime = MinimumTokenLifetimeValue; + + // Update the map with the new value for the setting + m_svcSettingsMap.put(SessionTokenLifetime, Integer.toString(tokenLifetime)); + } + + int lifetimeShorter; + try + { + lifetimeShorter = Integer.valueOf(getSetting(LifetimeShorter)).intValue(); + if (lifetimeShorter < MinimumLifetimeShorterValue) + { + System.err.println("SvcConfig()- Configured lifetime shorter too small, defaulting to " + + Integer.toString(MinimumLifetimeShorterValue) + " seconds"); + lifetimeShorter = MinimumLifetimeShorterValue; + + // Update the map with the new value for the setting + m_svcSettingsMap.put(LifetimeShorter, Integer.toString(lifetimeShorter)); + } + } + catch (NumberFormatException e) + { + System.err.println("SvcConfig()- Invalid configured lifetime shorter value, defaulting to " + + Integer.toString(MinimumLifetimeShorterValue) + " seconds"); + lifetimeShorter = MinimumLifetimeShorterValue; + + // Update the map with the new value for the setting + m_svcSettingsMap.put(LifetimeShorter, Integer.toString(lifetimeShorter)); + } + + if (lifetimeShorter > tokenLifetime + || (tokenLifetime - lifetimeShorter) < MinimumLifetimeShorterDifferential) + { + System.err.println("SvcConfig()- Invalid lifetime shorter value, defaulting to " + + Integer.toString(MinimumLifetimeShorterValue) + " seconds"); + + // Update the map with the new value for the setting + m_svcSettingsMap.put(LifetimeShorter, Integer.toString(MinimumLifetimeShorterValue)); + } + + int reconfigureInterval; + try + { + reconfigureInterval = Integer.valueOf(getSetting(ReconfigureInterval)).intValue(); + if (reconfigureInterval < MinimumReconfigureIntervalValue) + { + System.err.println("SvcConfig()- Configured reconfigure interval too small, defaulting to " + + Integer.toString(MinimumReconfigureIntervalValue) + " seconds"); + + // Update the map with the new value for the setting + m_svcSettingsMap.put(ReconfigureInterval, Integer.toString(MinimumReconfigureIntervalValue)); + } + } + catch (NumberFormatException e) + { + System.err.println("SvcConfig()- Invalid configured reconfigured interval value, defaulting to " + + Integer.toString(MinimumReconfigureIntervalValue) + " seconds"); + + // Update the map with the new value for the setting + m_svcSettingsMap.put(ReconfigureInterval, Integer.toString(MinimumReconfigureIntervalValue)); + } } catch (SAXException e) { @@ -259,14 +197,31 @@ public final class SvcConfig catch (SecurityException e) { System.err.println("SvcConfig()- SecurityException caught while accessing " + svcConfigPath + File.separator + m_svcSettingsFileName + " Exception=" + e.toString()); + throw new Exception("SvcConfig()- Not able to access file"); } catch (FileNotFoundException e) { System.err.println("SvcConfig()- File " + svcConfigPath + File.separator + m_svcSettingsFileName + " not found"); + throw new Exception("SvcConfig()- File not found"); } catch (IOException e) { System.err.println("SvcConfig()- IOException caught while trying to read " + svcConfigPath + File.separator + m_svcSettingsFileName + " Exception=" + e.toString()); + throw new Exception("SvcConfig()- Read error"); + } + finally + { + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } } } @@ -337,9 +292,6 @@ public final class SvcConfig { 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; diff --git a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/WSSecurity.java b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/WSSecurity.java index c2493255..9e3bed35 100644 --- a/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/WSSecurity.java +++ b/CASA-auth-token/server-java/Svc/src/com/novell/casa/authtoksvc/WSSecurity.java @@ -25,6 +25,7 @@ package com.novell.casa.authtoksvc; import java.io.ByteArrayInputStream; +import java.io.IOException; import org.apache.axis.Message; import org.apache.axis.message.SOAPEnvelope; @@ -66,11 +67,33 @@ public final class WSSecurity */ private static Message toSOAPMessage(Document doc) throws Exception { - Canonicalizer c14n = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS); - byte[] canonicalMessage = c14n.canonicalizeSubtree(doc); - ByteArrayInputStream in = new ByteArrayInputStream(canonicalMessage); - MessageFactory factory = MessageFactory.newInstance(); - return (org.apache.axis.Message) factory.createMessage(null, in); + ByteArrayInputStream inStream = null; + Message msg = null; + + try + { + Canonicalizer c14n = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS); + byte[] canonicalMessage = c14n.canonicalizeSubtree(doc); + inStream = new ByteArrayInputStream(canonicalMessage); + MessageFactory factory = MessageFactory.newInstance(); + msg = (org.apache.axis.Message) factory.createMessage(null, inStream); + } + finally + { + if (inStream != null) + { + try + { + inStream.close(); + } + catch (IOException e) + { + // Do nothing + } + } + } + + return msg; } /** diff --git a/CASA-auth-token/server-java/package/linux/CASA_auth_token_svc.changes b/CASA-auth-token/server-java/package/linux/CASA_auth_token_svc.changes index 2fe094e1..14a91ebd 100644 --- a/CASA-auth-token/server-java/package/linux/CASA_auth_token_svc.changes +++ b/CASA-auth-token/server-java/package/linux/CASA_auth_token_svc.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Mon Jan 8 15:26:15 MST 2007 - jluciani@novell.com + +- Applied changes to solve most issues found during my code + review of the components. + ------------------------------------------------------------------- Wed Dec 13 10:18:25 MST 2006 - jluciani@novell.com