The "java" folder has been renamed "server-java" to reflect that it only

contains server components. In the process, I also flatened its
directory structure.
This commit is contained in:
Juan Carlos Luciani
2006-11-16 09:20:06 +00:00
parent b00ec15375
commit 9b2e33bfa8
144 changed files with 16047 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
#######################################################################
#
# Copyright (C) 2006 Novell, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Author: Juan Carlos Luciani <jluciani@novell.com>
#
#######################################################################
SUBDIRS = novell
DIST_SUBDIRS = novell
CFILES =
EXTRA_DIST = $(CFILES)
.PHONY: package package-clean package-install package-uninstall
package package-clean package-install package-uninstall:
$(MAKE) -C $(TARGET_OS) $@
maintainer-clean-local:
rm -f Makefile.in

View File

@@ -0,0 +1,37 @@
#######################################################################
#
# Copyright (C) 2006 Novell, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Author: Juan Carlos Luciani <jluciani@novell.com>
#
#######################################################################
SUBDIRS = casa
DIST_SUBDIRS = casa
CFILES =
EXTRA_DIST = $(CFILES)
.PHONY: package package-clean package-install package-uninstall
package package-clean package-install package-uninstall:
$(MAKE) -C $(TARGET_OS) $@
maintainer-clean-local:
rm -f Makefile.in

View File

@@ -0,0 +1,37 @@
#######################################################################
#
# Copyright (C) 2006 Novell, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Author: Juan Carlos Luciani <jluciani@novell.com>
#
#######################################################################
SUBDIRS = authtoksvc
DIST_SUBDIRS = authtoksvc
CFILES =
EXTRA_DIST = $(CFILES)
.PHONY: package package-clean package-install package-uninstall
package package-clean package-install package-uninstall:
$(MAKE) -C $(TARGET_OS) $@
maintainer-clean-local:
rm -f Makefile.in

View File

@@ -0,0 +1,274 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.*;
import java.util.*;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* AuthMechConfig Class.
*
* This class obtains and maintains authentication token configuration.
*
*/
public class AuthMechConfig
{
// Well known authentication token configuration settings
public final static String ClassName = "ClassName";
public final static String RelativeClassPath = "RelativeClassPath";
public final static String ClassPath = "ClassPath";
public final static String Krb5ServicePrincipalName = "ServicePrincipalName";
// Default configuration values
private String m_defaultKrb5ServicePrincipalNameValue = "host";
private Map m_mechSettingsMap;
/*
* 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("AuthMechConfig 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("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() immplementation.
*/
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.
*/
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 AuthMechConfig() throws Exception
{
System.err.println("AuthMechConfig()- Default");
// Create a map to keep track of the token settings
m_mechSettingsMap = new HashMap();
}
/*
* Constructor.
*/
public AuthMechConfig(String mechSettingsFileName) throws Exception
{
System.err.println("AuthMechConfig()-");
// Create a map to keep track of the token settings
m_mechSettingsMap = new HashMap();
try
{
// Get an input stream to read from the token settings file
File f = new File(mechSettingsFileName);
FileInputStream inStream = new FileInputStream(f);
// Parse the file
XMLReader xr = XMLReaderFactory.createXMLReader();
SAXHandler handler = new SAXHandler(m_mechSettingsMap);
xr.setContentHandler(handler);
xr.setErrorHandler(handler);
InputSource source = new InputSource(inStream);
xr.parse(source);
inStream.close();
}
catch (SAXException e)
{
System.err.println("AuthMechConfig()- " + mechSettingsFileName + " format error, exception: " + e.toString());
throw new Exception("AuthMechConfig()- authtoken.settings format error");
}
catch (SecurityException e)
{
System.err.println("AuthMechConfig()- SecurityException accessing " + mechSettingsFileName + " Exception=" + e.toString());
throw new Exception("AuthMechConfig()- Not able to access file");
}
catch (FileNotFoundException e)
{
System.err.println("AuthMechConfig()- File " + mechSettingsFileName + " not found");
throw new Exception("AuthMechConfig()- File not found");
}
catch (IOException e)
{
System.err.println("AuthMechConfig()- IOException accessing " + mechSettingsFileName + " Exception=" + e.toString());
throw new Exception("AuthMechConfig()- 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_mechSettingsMap.get(settingName);
if (value == null)
{
System.err.println("AuthMechConfig.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(Krb5ServicePrincipalName) == true)
{
value = m_defaultKrb5ServicePrincipalNameValue;
System.err.println("AuthMechConfig.getSetting()- Assigning default value " + value);
// Add the key to the map so that it can be found quicker next time
m_mechSettingsMap.put(Krb5ServicePrincipalName, m_defaultKrb5ServicePrincipalNameValue);
}
}
else
{
System.err.println("AuthMechConfig.getSetting()- Found setting " + settingName);
System.err.println("AuthMechConfig.getSetting()- Setting value = " + value);
}
return value;
}
}

View File

@@ -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 <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
/*
* AuthMechanism Interface.
*
* This is the interface implemented by Authentication Mechanisms.
*
* Please note that Authentication Machanisms must also implement the
* Serializable interface.
*
*/
public interface AuthMechanism
{
/*
* Initialize the authentication mechanism.
*/
void init(SvcConfig svcConfig, AuthMechConfig mechConfig) 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();
}

View File

@@ -0,0 +1,871 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.apache.xerces.parsers.DOMParser;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import java.io.*;
import java.util.Formatter;
/**
*
* Class for the creation and editing of auth.policy files.
*
**/
public class AuthPolicyEditor
{
private static final String usage =
"usage: AuthPolicyEditor -op [-entry realm:mechanismName[:mechanismInfo]] [-refentry realm:mechanismName] -file policyFilePath\n\n" +
" where:\n" +
" -op - Corresponds to one of the following operations:\n" +
" -create - Create new auth policy file\n" +
" -list - List auth source entries\n" +
" -prepend - Insert auth source entry at the head\n" +
" -append - Insert auth source entry at the tail\n" +
" -insert - Insert auth source entry after specified reference entry\n" +
" -remove - Remove auth source entry\n" +
" -file - Path the the auth policy file\n" +
" -entry - Auth source entry to be inserted or removed. Must be followed by\n" +
" a string formated as follows:\n" +
" insert operations format: realm:mechanismName or realm:mechanismName:mechanismInfo\n" +
" remove operations format: realm:mechanismName\n" +
" -refentry - Reference auth source entry. Must be followed by a string formated\n" +
" as follows: realm:mechanismName\n";
private static final String initialPolicy =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<auth_policy>\n" +
"</auth_policy>\n";
private final static String AuthSourceElementName = "auth_source";
private final static String RealmElementName = "realm";
private final static String MechanismElementName = "mechanism";
private final static String MechanismInfoElementName = "mechanism_info";
private final static String Krb5Mechanism = "Krb5Authenticate";
private final static String PwdMechanism = "PwdAuthenticate";
/**
* Returns the formal mechanism name if well known
*
* @param mechName Name of mechanism.
* @return Mechanism formal name.
*/
private static String mechFormalName(String mechName)
{
String formalName;
if (mechName.compareToIgnoreCase(Krb5Mechanism) == 0)
formalName = Krb5Mechanism;
else if (mechName.compareToIgnoreCase(PwdMechanism) == 0)
formalName = PwdMechanism;
else
formalName = mechName;
return formalName;
}
/**
* Update the contents of the specified file with the provided
* policy document.
*
* @param filePath Path to policy file to be updated.
* @param doc Policy document.
* @return True if successful.
*/
private static boolean updateFile(String filePath, Document doc)
{
boolean result = false;
// Update the file with the specified document
// after removing the text nodes.
try
{
// Remove text nodes
Element root = doc.getDocumentElement();
Node child;
Node next = (Node) root.getFirstChild();
while ((child = next) != null)
{
next = child.getNextSibling();
if (child.getNodeType() == Node.TEXT_NODE)
{
// Remove the node
root.removeChild(child);
}
}
// Update file
File f = new File(filePath);
FileOutputStream out = new FileOutputStream(f);
OutputFormat format = new OutputFormat(doc);
XMLSerializer serializer = new XMLSerializer(out, format);
serializer.serialize(doc.getDocumentElement());
out.close();
result = true;
}
catch (IOException e)
{
System.out.println("Error writing to file " + filePath + ", exception: " + e.toString());
}
catch (SecurityException e)
{
System.out.println("SecurityException writting to file " + filePath);
}
return result;
}
/**
* Gets document for the specified policy file.
*
* @param filePath Path to the policy file.
* @return Document representation of the policy file.
*/
private static Document getPolicyFileDoc(String filePath)
{
Document doc = null;
try
{
// Get an input stream to read from policy file
File f = new File(filePath);
FileInputStream inStream = new FileInputStream(f);
InputSource source = new InputSource(inStream);
DOMParser parser = new DOMParser();
parser.parse(source);
doc = parser.getDocument();
inStream.close();
}
catch (FileNotFoundException e)
{
System.err.println("Policy file " + filePath + " not found");
}
catch (SecurityException e)
{
System.err.println("SecurityException accessing " + filePath);
}
catch (IOException e)
{
System.err.println("IOException accessing " + filePath + " Exception=" + e.toString());
}
catch (SAXException e)
{
System.err.println("Policy file " + filePath + " format error");
}
return doc;
}
/**
* Gets a starting policy document
*
* @return Starting policy document.
*/
private static Document getPolicyDoc()
{
Document doc = null;
try
{
StringReader 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());
}
return doc;
}
/**
* List the auth_source entries in the specified policy file.
*
* @param filePath Path to the policy file.
* @return True if the operation is successfully performed.
*/
private static boolean performListOperation(String filePath)
{
boolean opPerformed = false;
// List the auth sources present in the policy file
Document doc = getPolicyFileDoc(filePath);
if (doc != null)
{
// Go through the elements of the document
Element root = doc.getDocumentElement();
Node auth_source_node;
Node next_auth_source_node = root.getFirstChild();
while ((auth_source_node = next_auth_source_node) != null)
{
next_auth_source_node = auth_source_node.getNextSibling();
if (auth_source_node.getNodeType() == Node.ELEMENT_NODE
&& auth_source_node.getLocalName().compareToIgnoreCase("auth_source") == 0)
{
System.out.println("Auth_Source: ");
// We are dealing with an auth_source, display its children.
Node child;
Node next = auth_source_node.getFirstChild();
while ((child = next) != null)
{
next = child.getNextSibling();
if (child.getNodeType() == Node.ELEMENT_NODE)
{
if (child.getLocalName().compareToIgnoreCase("realm") == 0)
{
System.out.println(" Identity source: " + child.getTextContent());
}
else if (child.getLocalName().compareToIgnoreCase("mechanism") == 0)
{
System.out.println(" Authentication Mechanism: " + child.getTextContent());
}
else if (child.getLocalName().compareToIgnoreCase("mechanism_info") == 0)
{
System.out.println(" Authentication Mechanism Info: " + child.getTextContent());
}
}
}
}
}
opPerformed = true;
}
return opPerformed;
}
/**
* Create policy file.
*
* @param filePath Path to the settings file.
* @return True if the operation is successfully performed.
*/
private static boolean performCreateOperation(String filePath)
{
boolean opPerformed = false;
// create a policy file
Document doc = getPolicyDoc();
if (doc != null)
{
try
{
File f = new File(filePath);
boolean createStatus = f.createNewFile();
if (createStatus == true)
{
FileOutputStream out = new FileOutputStream(f);
OutputFormat format = new OutputFormat(doc);
XMLSerializer serializer = new XMLSerializer(out, format);
serializer.serialize(doc.getDocumentElement());
out.close();
opPerformed = true;
}
else
{
System.out.println("File " + filePath + " already exists");
}
}
catch (IOException e)
{
System.out.println("Error creating file " + filePath + ", exception: " + e.toString());
}
catch (SecurityException e)
{
System.out.println("SecurityException creating " + filePath);
}
}
return opPerformed;
}
/**
* Prepend the auth_source entry to the specified policy file.
*
* @param filePath Path to the policy file.
* @param entry Auth_source entry to be prepended. Entry is formated as
* follows: realm:mech:mechinfo (Note that the mechinfo
* is optional).
* @return True if operation is successfully performed.
*/
private static boolean performPrependOperation(String filePath, String entry)
{
boolean opPerformed = false;
// Prepend auth source entry to the policy file
Document doc = getPolicyFileDoc(filePath);
if (doc != null)
{
// Parse the entry into its components. Entry is formated as
// follows: realm:mech:mechinfo (Note that the mechinfo
// is optional).
String[] entryComponents = entry.split(":");
if (entryComponents.length >= 2
&& entryComponents.length <= 3)
{
// Create and prepend the entry elements
Element root = doc.getDocumentElement();
Element auth_source_element = doc.createElement(AuthSourceElementName);
Element realm_element = doc.createElement(RealmElementName);
realm_element.setTextContent(entryComponents[0]);
auth_source_element.appendChild(realm_element);
Element mechanism_element = doc.createElement(MechanismElementName);
mechanism_element.setTextContent(mechFormalName(entryComponents[1]));
auth_source_element.appendChild(mechanism_element);
if (entryComponents.length == 3)
{
Element mechanism_info_element = doc.createElement(MechanismInfoElementName);
mechanism_info_element.setTextContent(mechFormalName(entryComponents[2]));
auth_source_element.appendChild(mechanism_info_element);
}
Element firstEntry = null;
Node child;
Node next = (Node) root.getFirstChild();
while ((child = next) != null)
{
next = child.getNextSibling();
if (child.getNodeType() == Node.ELEMENT_NODE)
{
// This is the first entry
firstEntry = (Element) child;
break;
}
}
if (firstEntry != null)
root.insertBefore(auth_source_element, firstEntry);
else
root.appendChild(auth_source_element);
// Update the file
opPerformed = updateFile(filePath, doc);
}
else
{
System.out.println("Invalid entry format");
}
}
return opPerformed;
}
/**
* Append the auth_source entry to the specified policy file.
*
* @param filePath Path to the policy file.
* @param entry Auth_source entry to be appended. Entry is formated as
* follows: realm:mech:mechinfo (Note that the mechinfo
* is optional).
* @return True if operation is successfully performed.
*/
private static boolean performAppendOperation(String filePath, String entry)
{
boolean opPerformed = false;
// Append auth source entry to the policy file
Document doc = getPolicyFileDoc(filePath);
if (doc != null)
{
// Parse the entry into its components. Entry is formated as
// follows: realm:mech:mechinfo (Note that the mechinfo
// is optional).
String[] entryComponents = entry.split(":");
if (entryComponents.length >= 2
&& entryComponents.length <= 3)
{
// Create and append the entry elements
Element root = doc.getDocumentElement();
Element auth_source_element = doc.createElement(AuthSourceElementName);
Element realm_element = doc.createElement(RealmElementName);
realm_element.setTextContent(entryComponents[0]);
auth_source_element.appendChild(realm_element);
Element mechanism_element = doc.createElement(MechanismElementName);
mechanism_element.setTextContent(mechFormalName(entryComponents[1]));
auth_source_element.appendChild(mechanism_element);
if (entryComponents.length == 3)
{
Element mechanism_info_element = doc.createElement(MechanismInfoElementName);
mechanism_info_element.setTextContent(mechFormalName(entryComponents[2]));
auth_source_element.appendChild(mechanism_info_element);
}
root.appendChild(auth_source_element);
// Update the file
opPerformed = updateFile(filePath, doc);
}
else
{
System.out.println("Invalid entry format");
}
}
return opPerformed;
}
/**
* Insert the auth_source entry to the specified policy file.
*
* @param filePath Path to the policy file.
* @param entry Auth_source entry to be inserted. Entry is formated as
* follows: realm:mech:mechinfo (Note that the mechinfo
* is optional).
* @param refEntry Reference auth_source entry (New entry is inserted after
* it). Entry is formated as follows: realm:mech.
* @return True if operation is successfully performed.
*/
private static boolean performInsertOperation(String filePath, String entry, String refEntry)
{
boolean opPerformed = false;
// Remove auth sources present in the policy file
Document doc = getPolicyFileDoc(filePath);
if (doc != null)
{
// Parse the entries into their components. Entry is formated as
// follows: realm:mech:mechinfo (Note that the mechinfo
// is optional).
String[] entryComponents = entry.split(":");
String[] refEntryComponents = refEntry.split(":");
if (refEntryComponents.length == 2
&& entryComponents.length >= 2
&& entryComponents.length <= 3)
{
// Go through the elements of the document
Element root = doc.getDocumentElement();
Node curr_auth_source_node;
Node next_auth_source_node = root.getFirstChild();
while ((curr_auth_source_node = next_auth_source_node) != null)
{
next_auth_source_node = curr_auth_source_node.getNextSibling();
if (curr_auth_source_node.getNodeType() == Node.ELEMENT_NODE
&& curr_auth_source_node.getLocalName().compareToIgnoreCase("auth_source") == 0)
{
// We are dealing with an auth_source, check if this is the
// reference entry.
boolean realmMatch = false;
boolean mechanismMatch = false;
Node child;
Node next = curr_auth_source_node.getFirstChild();
while ((child = next) != null)
{
next = child.getNextSibling();
if (child.getNodeType() == Node.ELEMENT_NODE)
{
if (child.getLocalName().compareToIgnoreCase(RealmElementName) == 0)
{
// Compare the realm name
if (child.getTextContent().compareToIgnoreCase(refEntryComponents[0]) == 0)
realmMatch = true;
}
else if (child.getLocalName().compareToIgnoreCase(MechanismElementName) == 0)
{
// Compare the realm name
if (child.getTextContent().compareToIgnoreCase(mechFormalName(refEntryComponents[1])) == 0)
mechanismMatch = true;
}
}
}
// Insert entry after current entry if we have a match for the reference entry
if (realmMatch && mechanismMatch)
{
Element auth_source_element = doc.createElement(AuthSourceElementName);
Element realm_element = doc.createElement(RealmElementName);
realm_element.setTextContent(entryComponents[0]);
auth_source_element.appendChild(realm_element);
Element mechanism_element = doc.createElement(MechanismElementName);
mechanism_element.setTextContent(mechFormalName(entryComponents[1]));
auth_source_element.appendChild(mechanism_element);
if (entryComponents.length == 3)
{
Element mechanism_info_element = doc.createElement(MechanismInfoElementName);
mechanism_info_element.setTextContent(mechFormalName(entryComponents[2]));
auth_source_element.appendChild(mechanism_info_element);
}
curr_auth_source_node.getNextSibling();
Element nextEntry = null;
next = (Node) curr_auth_source_node.getNextSibling();;
while ((child = next) != null)
{
next = child.getNextSibling();
if (child.getNodeType() == Node.ELEMENT_NODE)
{
// This is the next entry
nextEntry = (Element) child;
break;
}
}
if (nextEntry != null)
root.insertBefore(auth_source_element, nextEntry);
else
root.appendChild(auth_source_element);
// Update the file
opPerformed = updateFile(filePath, doc);
break;
}
}
}
}
else
{
System.out.println("Invalid entry format");
}
}
return opPerformed;
}
/**
* Remove the auth_source entry from the specified policy file.
*
* @param filePath Path to the policy file.
* @param entry Auth_source entry to be removed. Entry is formated as
* follows: realm:mech.
* @return True if operation is successfully performed.
*/
private static boolean performRemoveOperation(String filePath, String entry)
{
boolean opPerformed = false;
// Remove auth sources present in the policy file
Document doc = getPolicyFileDoc(filePath);
if (doc != null)
{
// Parse the entry into its components. Entry is formated as
// follows: realm:mech:mechinfo (Note that the mechinfo
// is optional).
String[] entryComponents = entry.split(":");
if (entryComponents.length == 2)
{
// Go through the elements of the document
Element root = doc.getDocumentElement();
Node auth_source_node;
Node next_auth_source_node = root.getFirstChild();
while ((auth_source_node = next_auth_source_node) != null)
{
next_auth_source_node = auth_source_node.getNextSibling();
if (auth_source_node.getNodeType() == Node.ELEMENT_NODE
&& auth_source_node.getLocalName().compareToIgnoreCase("auth_source") == 0)
{
// We are dealing with an auth_source, check if this is the entry
// that must be removed.
boolean realmMatch = false;
boolean mechanismMatch = false;
Node child;
Node next = auth_source_node.getFirstChild();
while ((child = next) != null)
{
next = child.getNextSibling();
if (child.getNodeType() == Node.ELEMENT_NODE)
{
if (child.getLocalName().compareToIgnoreCase(RealmElementName) == 0)
{
// Compare the realm name
if (child.getTextContent().compareToIgnoreCase(entryComponents[0]) == 0)
realmMatch = true;
}
else if (child.getLocalName().compareToIgnoreCase(MechanismElementName) == 0)
{
// Compare the realm name
if (child.getTextContent().compareToIgnoreCase(mechFormalName(entryComponents[1])) == 0)
mechanismMatch = true;
}
}
}
// Remove current entry if it matches
if (realmMatch && mechanismMatch)
{
System.out.println("RemovingChild");
root.removeChild(auth_source_node);
// Update the file
opPerformed = updateFile(filePath, doc);
break;
}
}
}
}
else
{
System.out.println("Invalid entry format");
}
}
return opPerformed;
}
/**
* Applications Entry Point
*
* @param args
*/
public static void main(String[] args)
{
String op = null;
boolean opPerformed = false;
boolean argumentsError = false;
String filePath = null;
String entry = null;
String refEntry = null;
// Process the command line arguments
for (int i = 0; i < args.length; i++)
{
// Proceed based on the command
if (args[i].compareToIgnoreCase("-list") == 0)
{
// List operation requested
if (op == null)
{
op = "list";
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-create") == 0)
{
// Create operation requested
if (op == null)
{
op = "create";
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-prepend") == 0)
{
// Prepend operation requested
if (op == null)
{
op = "prepend";
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-append") == 0)
{
// Append operation requested
if (op == null)
{
op = "append";
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-insert") == 0)
{
// Insert operation requested
if (op == null)
{
op = "insert";
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-remove") == 0)
{
// Remove operation requested
if (op == null)
{
op = "remove";
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-entry") == 0)
{
// The next argument should contain the entry information
if (args.length > (i + 1))
{
entry = args[i + 1];
i++;
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-refentry") == 0)
{
// The next argument should contain the reference entry information
if (args.length > (i + 1))
{
refEntry = args[i + 1];
i++;
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-file") == 0)
{
// The next argument should contain the filepath
if (args.length > (i + 1))
{
filePath = args[i + 1];
i++;
}
else
{
argumentsError = true;
break;
}
}
else
{
argumentsError = true;
}
}
// Proceed based on the specified parameters
if (argumentsError == false)
{
if (filePath != null && op != null)
{
System.out.println("Dealing with policy file: " + filePath);
// Proceed based on the operation requested
if (op.compareTo("list") == 0)
{
opPerformed = performListOperation(filePath);
}
else if (op.compareTo("create") == 0)
{
opPerformed = performCreateOperation(filePath);
}
else if (op.compareTo("prepend") == 0)
{
// Verify that the required parameters were specified
if (entry != null)
{
opPerformed = performPrependOperation(filePath, entry);
}
else
{
argumentsError = true;
}
}
else if (op.compareTo("append") == 0)
{
// Verify that the required parameters were specified
if (entry != null)
{
opPerformed = performAppendOperation(filePath, entry);
}
else
{
argumentsError = true;
}
}
else if (op.compareTo("insert") == 0)
{
// Verify that the required parameters were specified
if (entry != null && refEntry != null)
{
opPerformed = performInsertOperation(filePath, entry, refEntry);
}
else
{
argumentsError = true;
}
}
else if (op.compareTo("remove") == 0)
{
// Verify that the required parameters were specified
if (entry != null)
{
opPerformed = performRemoveOperation(filePath, entry);
}
else
{
argumentsError = true;
}
}
else
{
System.err.println("Tool error");
}
}
else
{
argumentsError = true;
}
}
// Display the usage string if we encountered an error with the
// command line arguments.
if (argumentsError)
System.out.print(usage);
// Set the exit code appropriatedly
if (opPerformed)
System.exit(0);
else
System.exit(1);
}
}

View File

@@ -0,0 +1,343 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.InputStream;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* AuthReqMsg Class.
*
* This class deals with the message sent by Casa Client when requesting
* that an entity be authenticated. The format of the message is as
* follows:
*
* <?xml version="1.0" encoding="ISO-8859-1"?>
* <auth_req>
* <realm>realm value</realm>
* <mechanism>mechanism id</mechanism>
* <auth_mech_token>mechanism token data</auth_mech_token>
* </auth_req>
*
*/
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.
*/
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
{
private final static int AWAITING_ROOT_ELEMENT_START = 0;
private final static int AWAITING_ROOT_ELEMENT_END = 1;
private final static int AWAITING_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_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;
/*
* Constructor
*/
public SAXHandler (AuthReqMsg authReqMsg)
{
super();
// Initialize our members
m_authReqMsg = authReqMsg;
m_state = AWAITING_ROOT_ELEMENT_START;
}
/*
* endDocument() implementation.
*/
public void endDocument () throws SAXException
{
// Verify that we obtained all of the required elements
if (m_state != DONE_PARSING)
{
System.err.println("AuthReqMsg SAXHandler.endDocument()- Missing element");
throw new SAXException("Missing element");
}
}
/*
* startElement() implementation.
*/
public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
{
// Proceed based on our state
switch (m_state)
{
case AWAITING_ROOT_ELEMENT_START:
// Verify that we are processing the expected tag
if (ProtoDefs.authRequestElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_REALM_ELEMENT_START;
}
else
{
System.err.println("AuthReqMsg SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_REALM_ELEMENT_START:
// Verify that we are processing the expected tag
if (ProtoDefs.realmElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_REALM_DATA;
}
else
{
System.err.println("AuthReqMsg SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
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))
{
// Advance to the next state
m_state = AWAITING_AUTH_MECH_TOKEN_DATA;
}
else
{
System.err.println("AuthReqMsg SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
default:
System.err.println("AuthReqMsg SAXHandler.startElement()- State error");
throw new SAXException("State error");
}
}
/*
* endElement() immplementation.
*/
public void endElement (String uri, String name, String qName) throws SAXException
{
// Proceed based on our state
switch (m_state)
{
case AWAITING_ROOT_ELEMENT_END:
// Verify that we are processing the expected tag
if (ProtoDefs.authRequestElementName.equals(qName))
{
// Advance to the next state
m_state = DONE_PARSING;
}
else
{
System.err.println("AuthReqMsg SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_REALM_ELEMENT_END:
// Verify that we are processing the expected tag
if (ProtoDefs.realmElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_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;
}
else
{
System.err.println("AuthReqMsg SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_AUTH_MECH_TOKEN_ELEMENT_END:
// Verify that we are processing the expected tag
if (ProtoDefs.authMechTokenElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_ROOT_ELEMENT_END;
}
else
{
System.err.println("AuthReqMsg SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
default:
System.err.println("AuthReqMsg SAXHandler.startElement()- State error");
throw new SAXException("State error");
}
}
/*
* character() implementation.
*/
public void characters (char ch[], int start, int length) throws SAXException
{
// Proceed based on our state
switch (m_state)
{
case AWAITING_REALM_DATA:
// Consume the data
m_authReqMsg.m_realm = new String(ch, start, length);
// Advance to the next state
m_state = AWAITING_REALM_ELEMENT_END;
break;
case AWAITING_REALM_ELEMENT_END:
// Consume the data
m_authReqMsg.m_realm = m_authReqMsg.m_realm.concat(new String(ch, start, length));
break;
case AWAITING_MECH_DATA:
// Consume the data
m_authReqMsg.m_authMechanism = new String(ch, start, length);
// Advance to the next state
m_state = AWAITING_MECH_ELEMENT_END;
break;
case AWAITING_MECH_ELEMENT_END:
// Consume the data
m_authReqMsg.m_authMechanism = m_authReqMsg.m_authMechanism.concat(new String(ch, start, length));
break;
case AWAITING_AUTH_MECH_TOKEN_DATA:
// Consume the data
m_authReqMsg.m_authMechToken = new String(ch, start, length);
// Advance to the next state
m_state = AWAITING_AUTH_MECH_TOKEN_ELEMENT_END;
break;
case AWAITING_AUTH_MECH_TOKEN_ELEMENT_END:
// Consume the data
m_authReqMsg.m_authMechToken = m_authReqMsg.m_authMechToken.concat(new String(ch, start, length));
break;
default:
// Do nothing
break;
}
}
}
/*
* Constructor
*/
public AuthReqMsg (InputStream inStream) throws Exception
{
try
{
// Parse the AuthReqMsg
XMLReader xr = XMLReaderFactory.createXMLReader();
SAXHandler handler = new SAXHandler(this);
xr.setContentHandler(handler);
xr.setErrorHandler(handler);
InputSource source = new InputSource(inStream);
xr.parse(source);
}
catch (SAXException e)
{
System.err.println("AuthReqMsg()- Parse exception: " + e.toString());
throw new Exception("Protocol error");
}
}
/*
* Method to get the authentication realm.
*/
public String getRealm() throws Exception
{
return m_realm;
}
/*
* Method to get the authentication mechanism token.
*/
public String getAuthMechToken() throws Exception
{
return m_authMechToken;
}
/*
* Method to get the authentication mechanism id.
*/
public String getMechanismId() throws Exception
{
return m_authMechanism;
}
}

View File

@@ -0,0 +1,113 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
/**
* AuthRespMsg Class.
*
* This class deals with the message sent to the CASA Client as a
* response to an authentication request. The format of the message is
* as follows when the response includes a session token:
*
* <?xml version="1.0" encoding="ISO-8859-1"?>
* <auth_resp>
* <status><description>OK</description>200</status>
* <session_token><lifetime>lifetime value</lifetime>session token data</session_token>
* </auth_resp>
*
* The format of the message is as follows when the response does not
* include a session token.
*
* <?xml version="1.0" encoding="ISO-8859-1"?>
* <auth_resp>
* <status><description>status description</description>status code</status>
* </auth_resp>
*
* Plase note that the protocol utilizes the status codes defined
* in the HTTP 1.1 Specification.
*
*/
public class AuthRespMsg
{
String m_msg;
/*
* Constructor for a msg that does not include the session token.
*/
public AuthRespMsg (
String statusDescription,
String statusCode) throws Exception
{
// Get a StringBuffer to help us with the construction of the message
StringBuffer sb = new StringBuffer();
// Start building the message
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
sb.append("<" + ProtoDefs.authResponseElementName + ">" + "\r\n");
sb.append("<" + ProtoDefs.statusElementName + ">"
+ "<" + ProtoDefs.descriptionElementName + ">" + statusDescription + "</" + ProtoDefs.descriptionElementName + ">"
+ statusCode + "</" + ProtoDefs.statusElementName + ">" + "\r\n");
sb.append("</" + ProtoDefs.authResponseElementName + ">" + "\r\n");
// The message has now been built, save it.
m_msg = sb.toString();
}
/*
* Constructor for a msg that includes the session token.
*/
public AuthRespMsg (
String statusDescription,
String statusCode,
String sessionToken,
String sessionTokenLifetime) throws Exception
{
// Get a StringBuffer to help us with the construction of the message
StringBuffer sb = new StringBuffer();
// Start building the message
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
sb.append("<" + ProtoDefs.authResponseElementName + ">" + "\r\n");
sb.append("<" + ProtoDefs.statusElementName + ">"
+ "<" + ProtoDefs.descriptionElementName + ">" + ProtoDefs.httpOkStatusMsg + "</" + ProtoDefs.descriptionElementName + ">"
+ ProtoDefs.httpOkStatusCode + "</" + ProtoDefs.statusElementName + ">" + "\r\n");
sb.append("<" + ProtoDefs.sessionTokenElementName + ">"
+ "<" + ProtoDefs.lifetimeElementName + ">" + sessionTokenLifetime + "</" + ProtoDefs.lifetimeElementName + ">"
+ sessionToken + "</" + ProtoDefs.sessionTokenElementName + ">" + "\r\n");
sb.append("</" + ProtoDefs.authResponseElementName + ">" + "\r\n");
// The message has now been built, save it.
m_msg = sb.toString();
}
/*
* Returns a string containing the AuthRespMsg.
*/
public String toString()
{
return m_msg;
}
}

View File

@@ -0,0 +1,335 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.ByteArrayInputStream;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.client.AxisClient;
import org.apache.axis.configuration.NullProvider;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.axis.message.SOAPBody;
import org.apache.axis.message.MessageElement;
import javax.xml.namespace.QName;
import java.io.*;
// Un-comment the following line to print Authentication Token Messages
//import org.apache.axis.utils.XMLUtils;
/*
* AuthToken Class.
*
* This class constructs authentication tokens that clients can present
* to services for authentication. The authentication token consists of
* a SOAP message secured with WSSecurity with the appropriate elements signed
* and with a timestamp. The body of the SOAP message is as follows:
*
* <auth_token>
* <ident_token><type>Identity Token type</type>identity token data</ident_token>
* </auth_token>
*
*/
public class AuthToken
{
private String m_token;
private String m_lifetime = "";
private String m_lifetimeShorter = "";
private String m_identityTokenType = null;
private String m_identityToken = null;
static final String authTokenSoapMsg =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<SOAP-ENV:Envelope" +
" xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\"\n" +
" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
" <SOAP-ENV:Body>" +
" <auth_token><ident_token><type></type></ident_token></auth_token>" +
" </SOAP-ENV:Body>" +
"</SOAP-ENV:Envelope>";
static final private MessageContext axisMsgContext = new MessageContext(new AxisClient(new NullProvider()));
/*
* Constructor.
*/
public AuthToken(String identityId,
String realm,
String targetService,
String targetHost,
SvcConfig svcConfig,
EnabledSvcsConfig enabledSvcsConfig) throws Exception
{
// Get access to the authentication token configuration for this service
AuthTokenConfig authTokenConfig = enabledSvcsConfig.getAuthTokenConfig(targetHost, targetService);
if (authTokenConfig != null)
{
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);
m_identityToken = identityToken.getEncodedToken();
m_identityTokenType = identityToken.getProviderType();
m_lifetime = authTokenConfig.getSetting(AuthTokenConfig.TokenLifetime);
m_lifetimeShorter = authTokenConfig.getSetting(AuthTokenConfig.LifetimeShorter);
// Create AuthTokenMessage
Message authTokenMessage = getMessage(identityToken.getEncodedToken(),
identityToken.getProviderType(),
Integer.valueOf(m_lifetime).intValue(),
svcConfig,
(targetHost.compareTo("localhost") == 0) ? false : true);
// Un-comment the following line to print Authentication Token Messages
//XMLUtils.PrettyElementToWriter(authTokenMessage.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
// Now save the message as a string
OutputStream outStream = new ByteArrayOutputStream();
authTokenMessage.writeTo(outStream);
m_token = outStream.toString();
outStream.close();
}
catch (Exception e)
{
// tbd
System.err.println("AuthToken()- Exception: " + e.toString());
}
}
else
{
throw new Exception("Error: Missing authentication token config for " + targetService);
}
}
/*
* Constructor given an authentication token string. The constructor
* validates the token as part of its processing.
*/
public AuthToken(String token,
boolean encodedToken) throws Exception
{
// Decode the token string if necessary
if (encodedToken)
m_token = Base64Coder.decode(token);
else
m_token = token;
// Now instantiate a SOAP message with the string
InputStream inStream = new ByteArrayInputStream(m_token.getBytes());
org.apache.axis.Message message;
try
{
message = new Message(inStream);
} catch (Exception e)
{
System.err.println("AuthToken()- Exception caught creating message, msg: " + e.getMessage());
throw new Exception("Invalid Authentication Token");
}
// Get access to the SOAP Envelope
SOAPEnvelope envelope = message.getSOAPEnvelope();
// Verify the message
if (WSSecurity.verifyMessage(envelope))
{
// Message verification succeded, now obtain the identity token
// and its type from the message body.
SOAPBody body = (SOAPBody) envelope.getBody();
QName authTokenElementName = new QName("auth_token");
MessageElement authTokenElement = body.getChildElement(authTokenElementName);
QName identTokenElementName = new QName("ident_token");
MessageElement identTokenElement = authTokenElement.getChildElement(identTokenElementName);
if (identTokenElement != null)
{
QName identTokenTypeElementName = new QName("type");
MessageElement identTokenTypeElement = identTokenElement.getChildElement(identTokenTypeElementName);
if (identTokenTypeElement != null)
{
m_identityToken = identTokenElement.getChildNodes().item(1).getNodeValue();
m_identityTokenType = identTokenTypeElement.getValue();
}
}
if (m_identityToken == null || m_identityTokenType == null)
{
System.out.println("AuthToken()- Required data missing from authentication token");
throw new Exception("Error: Required data missing from Authentication Token");
}
}
else
{
// Message verification failed
System.err.println("AuthToken()- Invalid Authentication Token");
throw new Exception("Invalid Authentication Token");
}
}
/**
* Get AuthToken SOAP Message
*
* @param identityToken String containing the identity token that should be part of the message
* @param identityTokenType String containing the identity token type
* @param lifetime Lifetime that should be specified in the message timestamp (seconds)
* @param svcConfig Service configuration object
* @param includeCert True if the message should include the Public Certificate
* @return <code>Message<code> AuthToken message, null if the method fails.
*/
private Message getMessage(String identityToken,
String identityTokenType,
int lifetime,
SvcConfig svcConfig,
boolean includeCert)
{
Message secureMessage;
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());
Message message = new Message(inStream);
message.setMessageContext(axisMsgContext);
SOAPBody body = (SOAPBody) message.getSOAPBody();
// Get access to the auth_token element
QName authTokenElementName = new QName("auth_token");
MessageElement authTokenElement = body.getChildElement(authTokenElementName);
// Get access to the ident_token element and set its value
QName identTokenElementName = new QName("ident_token");
MessageElement identTokenElement = authTokenElement.getChildElement(identTokenElementName);
identTokenElement.addTextNode(identityToken);
// Get access to the identity token type element element and set its value
QName identTokenTypeElementName = new QName("type");
MessageElement identTokenTypeElement = identTokenElement.getChildElement(identTokenTypeElementName);
identTokenTypeElement.setValue(identityTokenType);
// Now we need to secure the SOAP message that we created, we are doing to
// do so by adding a timestamp and signing the timestamp as well as the body.
// To do this we are going to leverage WS-Security.
secureMessage = WSSecurity.secureSOAPEnvelope(message.getSOAPEnvelope(),
lifetime,
svcConfig,
includeCert);
}
catch (Exception e)
{
System.out.println("AuthToken.getMessage() - Exception caught building message, error: " + e.getMessage());
secureMessage = null;
}
return secureMessage;
}
/*
* Returns a string containing the Base64 encode token.
*/
public String toString()
{
return Base64Coder.encode(m_token);
}
/*
* Returns the lifetime of the token.
*
* Note: It is only valid to execute this procedure if its called on an object
* instantiated via the constructor which takes a lifetime parameter.
*/
public String getLifetime() throws Exception
{
// Throw exeption if the lifetime parameter is not set
if (m_lifetime.length() == 0)
{
System.out.println("AuthToken.getLifetime() - Called when lifetime is not set");
throw new Exception("Error: Called getLifetime while not set");
}
return Integer.toString(Integer.valueOf(m_lifetime).intValue() - Integer.valueOf(m_lifetimeShorter).intValue());
}
/*
* Returns the identity token.
*/
public String getIdentityToken()
{
return m_identityToken;
}
/*
* Returns the identity token type.
*/
public String getIdentityTokenType()
{
return m_identityTokenType;
}
/*
* Validates an authentication token. If successful it
* returns a string containing the identity token associated
* with the authentication token; otherwise it returns NULL;
*
* Note, the routine assumes that the token is not encoded.
*/
public static String validate(String authTokenString)
{
System.err.println("AuthToken.validate()- Start");
// Instantiate the AuthToken, this validates the token itself.
try
{
AuthToken authToken = new AuthToken(authTokenString, false);
// If we are here is because the token validation succeeded,
// return the identity token string.
System.err.println("AuthToken.validate()- Returning identity token");
return authToken.getIdentityToken();
}
catch (Exception e)
{
// The validation of one of the tokens failed
// tbd - Log
System.err.println("AuthToken.validate()- Exception caught during token processing, msg: " + e.getMessage());
return null;
}
}
}

View File

@@ -0,0 +1,298 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.*;
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 = "3600"; // 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_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.
*/
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;
}
}

View File

@@ -0,0 +1,324 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
/**
*
* Class for the creation and editing of authtoken.settings files.
*
**/
public class AuthTokenSettingsEditor implements IVerifySetting
{
private static final String usage =
"usage: AuthTokenSettingsEditor -op [settingName [settingValue]] -file settingsFilePath\n\n" +
" where:\n" +
" -op - Corresponds to one of the following operations:\n" +
" -create - Create new authtoken settings file\n" +
" -list - List settings\n" +
" -get - Get settings, must be followed by settingName parameter\n" +
" -set - Set settings, must be followed by settingName and settingValue parameters\n" +
" -remove - Remove settings\n" +
" -file - Path the the authtoken settings file\n" +
" settingName - Name of the setting being retrieved or set\n" +
" settingValue - Value of the setting being set\n\n" +
" The following settings are valid:\n" +
" TokenLifetime\n" +
" LifetimeShorter\n";
private static final String settings =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<settings>\n" +
"</settings>\n";
/**
* Checks if the specified setting is valid.
*
* @param setting The name of the setting being checked.
* @return True if the specified setting is valid.
*/
public boolean validSetting(String setting)
{
boolean result = false;
if (setting.compareToIgnoreCase(AuthTokenConfig.TokenLifetime) == 0)
result = true;
else if (setting.compareToIgnoreCase(AuthTokenConfig.LifetimeShorter) == 0)
result = true;
else if (setting.compareToIgnoreCase(AuthTokenConfig.IdentityTokenType) == 0)
result = true;
else
System.out.println("Invalid setting specified");
return result;
}
/**
* Checks if the specified setting is valid in conjunction
* with the specified value.
*
* @param setting The name of the setting being checked.
* @param value The value of the specified setting.
* @return The formal name of the setting if found to be valid.
*/
public String validSettingNameAndValue(String setting,
String value)
{
String validSetting = null;
if (setting.compareToIgnoreCase(AuthTokenConfig.TokenLifetime) == 0)
{
// Verify that we are dealing with a numeric value
try
{
Integer.valueOf(value);
// Good
validSetting = AuthTokenConfig.TokenLifetime;
}
catch (NumberFormatException e)
{
System.out.println("Invalid setting value specified");
}
}
else if (setting.compareToIgnoreCase(AuthTokenConfig.LifetimeShorter) == 0)
{
// Verify that we are dealing with a numeric value
try
{
Integer.valueOf(value);
// Good
validSetting = AuthTokenConfig.LifetimeShorter;
}
catch (NumberFormatException e)
{
System.out.println("Invalid setting value specified");
}
}
else if (setting.compareToIgnoreCase(AuthTokenConfig.IdentityTokenType) == 0)
{
// Always succeed
validSetting = AuthTokenConfig.IdentityTokenType;
}
else
System.out.println("Invalid setting specified");
return validSetting;
}
/**
* Applications Entry Point
*
* @param args
*/
public static void main(String[] args)
{
String op = null;
boolean opPerformed = false;
boolean argumentsError = false;
String filePath = null;
String setting = null;
String value = null;
AuthTokenSettingsEditor editor = new AuthTokenSettingsEditor();
// Process the command line arguments
for (int i = 0; i < args.length; i++)
{
// Proceed based on the command
if (args[i].compareToIgnoreCase("-file") == 0)
{
// The next argument should contain the filepath
if (args.length > (i + 1))
{
filePath = args[i + 1];
i++;
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-list") == 0)
{
// List operation requested
if (op == null)
{
op = "list";
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-create") == 0)
{
// List operation requested
if (op == null)
{
op = "create";
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-get") == 0)
{
// Get setting operation requested
if (op == null)
{
op = "get";
// The next argument should contain the setting name
if (args.length > (i + 1))
{
setting = args[i + 1];
i++;
}
else
{
argumentsError = true;
break;
}
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-set") == 0)
{
// Set setting operation requested
if (op == null)
{
op = "set";
// The next two arguments should contain the setting name
// and the setting value.
if (args.length > (i + 2))
{
setting = args[i + 1];
value = args[i + 2];
i += 2;
}
else
{
argumentsError = true;
break;
}
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-remove") == 0)
{
// Remove setting operation requested
if (op == null)
{
op = "remove";
// The next argument should contain the setting name
if (args.length > (i + 1))
{
setting = args[i + 1];
i++;
}
else
{
argumentsError = true;
break;
}
}
else
{
argumentsError = true;
break;
}
}
else
{
argumentsError = true;
}
}
// Proceed based on the specified parameters
if (argumentsError == false)
{
if (filePath != null && op != null)
{
System.out.println("Dealing with settings file: " + filePath);
// Proceed based on the operation requested
if (op.compareTo("list") == 0)
{
opPerformed = SettingsFileUtil.performListOperation(filePath);
}
else if (op.compareTo("create") == 0)
{
opPerformed = SettingsFileUtil.performCreateOperation(filePath, settings);
}
else if (op.compareTo("get") == 0)
{
opPerformed = SettingsFileUtil.performGetOperation(filePath, setting, editor);
}
else if (op.compareTo("set") == 0)
{
opPerformed = SettingsFileUtil.performSetOperation(filePath, setting, value, editor);
}
else if (op.compareTo("remove") == 0)
{
opPerformed = SettingsFileUtil.performRemoveOperation(filePath, setting, editor);
}
else
{
System.err.println("Tool error");
}
}
else
{
argumentsError = true;
}
}
// Display the usage string if we encountered an error with the
// command line arguments.
if (argumentsError)
System.out.print(usage);
// Set the exit code appropriatedly
if (opPerformed)
System.exit(0);
else
System.exit(1);
}
}

View File

@@ -0,0 +1,341 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.util.*;
import java.io.*;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.net.MalformedURLException;
import java.net.URLClassLoader;
/**
* Authenticate Class.
*
* This class processes authentication requests.
*
*/
public class Authenticate implements RpcMethod
{
private static final String m_mechanismSettingsFileName = "mechanism.settings";
private Map m_authMechanismMap;
private SvcConfig m_svcConfig;
private EnabledSvcsConfig m_enabledSvcsConfig;
/*
* Constructor
*/
public Authenticate() throws Exception
{
// Create a map to keep track of the authentication mechanisms
m_authMechanismMap = new HashMap();
}
/*
* Initialize the Rpc method.
*/
public void init(SvcConfig svcConfig, EnabledSvcsConfig enabledSvcsConfig) throws Exception
{
m_svcConfig = svcConfig;
m_enabledSvcsConfig = enabledSvcsConfig;
// Now go through the configured authentication mechanisms, as we do so, instantiate
// the mechanisms and place them in our map. Note that the mechanisms config folder
// contains folders for each installed authentication mechanism. The name of these
// folders usually match the name of the Authentication mechanisms.
String svcConfigPath = svcConfig.getSetting(SvcConfig.ConfigFolderPath);
File mechanismsConfigFolder = new File(svcConfigPath, "auth_mechanisms");
try
{
String[] mechanismsConfigFolderObjs = mechanismsConfigFolder.list();
if (mechanismsConfigFolderObjs != null)
{
for (int i = 0; i < mechanismsConfigFolderObjs.length; i++)
{
// Check if we are dealing with a file or a folder
File mechanismFolder = new File(mechanismsConfigFolder, mechanismsConfigFolderObjs[i]);
try
{
if (mechanismFolder.isDirectory() == true)
{
System.err.println("Authenticate.init()- Mechanism folder " + mechanismFolder + " is directory");
// Try to obtain the mechanism settings
try
{
AuthMechConfig mechConfig = new AuthMechConfig(mechanismFolder + File.separator + m_mechanismSettingsFileName);
// Mechanism settings obtained, now instantiate it and place it in our map.
//
String mechClassName = mechConfig.getSetting(AuthMechConfig.ClassName);
if (mechClassName != null)
{
// We now know the name of the class implementing the mechanism, now lets
// get the relative path to the class file. Note that the path is relative
// to the root folder of our application.
String relativePath = mechConfig.getSetting(AuthMechConfig.RelativeClassPath);
if (relativePath != null)
{
// Create a file object to the folder containing the class file. Note that we need to
// ultimately instantiate objects from a class loaded by the same class loader that
// loads the AuthMechanism class to avoid ClassCastExceptions.
File mechClassPathFile = new File(svcConfig.getSetting(SvcConfig.AppRootPath) + relativePath);
System.err.println("Authenticate.init()- Mechanism path = " + mechClassPathFile);
try
{
URL methClassPathUrl = mechClassPathFile.toURL();
URL[] urls = new URL[]{methClassPathUrl};
// Create a class loader for the folder
ClassLoader customClassLoader = new URLClassLoader(urls);
// 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);
oos.writeObject(mechClass);
oos.close();
fos.close();
FileInputStream fis = new FileInputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp");
ObjectInputStream 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);
m_authMechanismMap.put(mechanism.getId(), mechanism);
}
catch (MalformedURLException e)
{
System.err.println("Authenticate.init()- MalformedURLException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
}
catch (ClassNotFoundException e)
{
System.err.println("Authenticate.init()- ClassNotFoundException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
}
catch (InstantiationException e)
{
System.err.println("Authenticate.init()- InstantiationException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
}
catch (IllegalAccessException e)
{
System.err.println("Authenticate.init()- IllegalAccessException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
}
}
else
{
// A relative path was not configured, check if instead a full path was configured.
String classPath = mechConfig.getSetting(AuthMechConfig.ClassPath);
if (classPath != null)
{
// Create a file object to the folder containing the class file. Note that we need to
// ultimately instantiate objects from a class loaded by the same class loader that
// loads the AuthMechanism class to avoid ClassCastExceptions.
File mechClassPathFile = new File(classPath);
System.err.println("Authenticate.init()- Mechanism path = " + mechClassPathFile);
try
{
URL methClassPathUrl = mechClassPathFile.toURL();
URL[] urls = new URL[]{methClassPathUrl};
// Create a class loader for the folder
ClassLoader customClassLoader = new URLClassLoader(urls);
// 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);
oos.writeObject(mechClass);
oos.close();
fos.close();
FileInputStream fis = new FileInputStream(svcConfig.getSetting(SvcConfig.AppRootPath) + "tmp");
ObjectInputStream 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);
m_authMechanismMap.put(mechanism.getId(), mechanism);
}
catch (MalformedURLException e)
{
System.err.println("Authenticate.init()- MalformedURLException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
}
catch (ClassNotFoundException e)
{
System.err.println("Authenticate.init()- ClassNotFoundException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
}
catch (InstantiationException e)
{
System.err.println("Authenticate.init()- InstantiationException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
}
catch (IllegalAccessException e)
{
System.err.println("Authenticate.init()- IllegalAccessException for " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
}
}
else
{
System.err.println("Authenticate.init()- No configuration to find class path to load " + mechanismFolder + File.separator + m_mechanismSettingsFileName);
}
}
}
else
{
System.err.println("Authenticate.init()- No configured mechanism class name for " + mechanismFolder + File.separator + m_mechanismSettingsFileName);
}
}
catch (SecurityException e)
{
System.err.println("Authenticate.init()- SecurityException accessing " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
}
catch (FileNotFoundException e)
{
System.err.println("Authenticate.init()- No authentication policy file for " + mechanismFolder);
}
catch (IOException e)
{
System.err.println("Authenticate.init()- IOException reading " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
}
catch (Exception e)
{
System.err.println("Authenticate.init()- Exception instantiating mechConfig or mechanism " + mechanismFolder + File.separator + m_mechanismSettingsFileName + " Exception=" + e.toString());
}
}
}
catch (SecurityException e)
{
System.err.println("Authenticate.init()- SecurityException accessing " + mechanismFolder + " Exception=" + e.toString());
}
}
}
else
{
System.err.println("Authenticate.init()- Unable to obtain mechanisms folder " + mechanismsConfigFolder + " objects");
}
}
catch (SecurityException e)
{
System.err.println("Authenticate.init()- SecurityException accessing " + mechanismsConfigFolder + " Exception=" + e.toString());
}
}
/*
* Process Rpc.
*/
public void invoke(InputStream inStream, PrintWriter out) throws IOException
{
try
{
System.err.println("Authenticate.invoke()");
// Parse the AuthReqMsg sent from the client
AuthReqMsg authReqMsg = new AuthReqMsg(inStream);
// Get the necessary authentication mechanism
AuthMechanism authMechanism = (AuthMechanism) m_authMechanismMap.get(authReqMsg.getMechanismId());
if (authMechanism != null)
{
// Invoke the mechanism to authenticate the entity
String identId = authMechanism.invoke(authReqMsg);
// Create response based on the identity resolution results
if (identId != null && identId.length() != 0)
{
System.err.println("Authenticate.invoke()- identId resolved, " + identId);
// An identity was resolved, get a SessionToken for it.
SessionToken sessionToken = new SessionToken(identId,
authReqMsg.getRealm(),
m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime),
m_svcConfig);
// Write out the response
String respLifetime = Integer.toString(Integer.valueOf(m_svcConfig.getSetting(SvcConfig.SessionTokenLifetime)).intValue()
- Integer.valueOf(m_svcConfig.getSetting(SvcConfig.LifetimeShorter)).intValue());
AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpOkStatusMsg,
ProtoDefs.httpOkStatusCode,
sessionToken.toString(),
respLifetime);
out.println(authRespMsg.toString());
}
else
{
System.err.println("Authenticate.invoke()- identId not resolved");
// Write out the response
AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpUnauthorizedStatusMsg,
ProtoDefs.httpUnauthorizedStatusCode);
out.println(authRespMsg.toString());
}
}
else
{
System.err.println("Authenticate.invoke()- Unsupported mechanism " + authReqMsg.getMechanismId());
// Write out the response
AuthRespMsg authRespMsg = new AuthRespMsg(ProtoDefs.httpNotFoundStatusMsg,
ProtoDefs.httpNotFoundStatusCode);
out.println(authRespMsg.toString());
}
}
catch (Exception e)
{
System.err.println("Authenticate.invoke()- 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("Authenticate.invoke()- Exception trying to construct response msg: " + e2.toString());
}
}
}
/*
* Return the method id.
*/
public String getId()
{
return "Authenticate";
}
}

View File

@@ -0,0 +1,121 @@
/**************************************************************************
*
* A Base64 Encoder/Decoder.
*
* This class is used to encode and decode data in Base64 format
* as described in RFC 1521.
*
* <p>
* Copyright 2003: Christian d'Heureuse, Inventec Informatik AG, Switzerland.<br>
* License: This is "Open Source" software and released under the <a href="http://www.gnu.org/licenses/lgpl.html" target="_top">GNU/LGPL</a> license.
* It is provided "as is" without warranty of any kind. Please contact the author for other licensing arrangements.<br>
* Home page: <a href="http://www.source-code.biz" target="_top">www.source-code.biz</a><br>
*
* <p>
* Version history:<br>
* 2003-07-22 Christian d'Heureuse (chdh): Module created.<br>
* 2005-08-11 chdh: Lincense changed from GPL to LGPL.
*
**************************************************************************/
package com.novell.casa.authtoksvc;
public class Base64Coder {
// Mapping table from 6-bit nibbles to Base64 characters.
private static char[] map1 = new char[64];
static {
int i=0;
for (char c='A'; c<='Z'; c++) map1[i++] = c;
for (char c='a'; c<='z'; c++) map1[i++] = c;
for (char c='0'; c<='9'; c++) map1[i++] = c;
map1[i++] = '+'; map1[i++] = '/'; }
// Mapping table from Base64 characters to 6-bit nibbles.
private static byte[] map2 = new byte[128];
static {
for (int i=0; i<map2.length; i++) map2[i] = -1;
for (int i=0; i<64; i++) map2[map1[i]] = (byte)i; }
/**
* Encodes a string into Base64 format.
* No blanks or line breaks are inserted.
* @param s a String to be encoded.
* @return A String with the Base64 encoded data.
*/
public static String encode (String s) {
return new String(encode(s.getBytes())); }
/**
* Encodes a byte array into Base64 format.
* No blanks or line breaks are inserted.
* @param in an array containing the data bytes to be encoded.
* @return A character array with the Base64 encoded data.
*/
public static char[] encode (byte[] in) {
int iLen = in.length;
int oDataLen = (iLen*4+2)/3; // output length without padding
int oLen = ((iLen+2)/3)*4; // output length including padding
char[] out = new char[oLen];
int ip = 0;
int op = 0;
while (ip < iLen) {
int i0 = in[ip++] & 0xff;
int i1 = ip < iLen ? in[ip++] & 0xff : 0;
int i2 = ip < iLen ? in[ip++] & 0xff : 0;
int o0 = i0 >>> 2;
int o1 = ((i0 & 3) << 4) | (i1 >>> 4);
int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6);
int o3 = i2 & 0x3F;
out[op++] = map1[o0];
out[op++] = map1[o1];
out[op] = op < oDataLen ? map1[o2] : '='; op++;
out[op] = op < oDataLen ? map1[o3] : '='; op++; }
return out; }
/**
* Decodes a Base64 string.
* @param s a Base64 String to be decoded.
* @return A String containing the decoded data.
* @throws IllegalArgumentException if the input is not valid Base64 encoded data.
*/
public static String decode (String s) {
return new String(decode(s.toCharArray())); }
/**
* Decodes Base64 data.
* No blanks or line breaks are allowed within the Base64 encoded data.
* @param in a character array containing the Base64 encoded data.
* @return An array containing the decoded data bytes.
* @throws IllegalArgumentException if the input is not valid Base64 encoded data.
*/
public static byte[] decode (char[] in) {
int iLen = in.length;
if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4.");
while (iLen > 0 && in[iLen-1] == '=') iLen--;
int oLen = (iLen*3) / 4;
byte[] out = new byte[oLen];
int ip = 0;
int op = 0;
while (ip < iLen) {
int i0 = in[ip++];
int i1 = in[ip++];
int i2 = ip < iLen ? in[ip++] : 'A';
int i3 = ip < iLen ? in[ip++] : 'A';
if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127)
throw new IllegalArgumentException ("Illegal character in Base64 encoded data.");
int b0 = map2[i0];
int b1 = map2[i1];
int b2 = map2[i2];
int b3 = map2[i3];
if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0)
throw new IllegalArgumentException ("Illegal character in Base64 encoded data.");
int o0 = ( b0 <<2) | (b1>>>4);
int o1 = ((b1 & 0xf)<<4) | (b2>>>2);
int o2 = ((b2 & 3)<<6) | b3;
out[op++] = (byte)o0;
if (op<oLen) out[op++] = (byte)o1;
if (op<oLen) out[op++] = (byte)o2; }
return out; }
}

View File

@@ -0,0 +1,774 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.ByteArrayInputStream;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import org.bandit.ia.IAContext;
/*
* CasaIdentityToken Class.
*
* This class constructs Casa Identity tokens.
*
* A Casa Identity Token is a simple XML Document
* with information about an identity in the form
* of:
*
* <?xml version="1.0" encoding="ISO-8859-1"?>
* <casa_ident_tok>
* <id>identity id</id>
* <source_name>identity data source name</source_name>
* <source_url>identity data source url</source_url>
* <target_service>target service name</target_service>
* <target_host>target host name</target_host>
* <attributes>
* <attribute name>attribute value</attribute name>
* <attribute2 name>attribute2 value</attribute name>
* ...
* </attributes>
* </casa_ident_tok>
*
*
* attribute/values pairs. The attribute names
* being the XML elements of the documents.
*
*/
public class CasaIdentityToken implements IdentityToken
{
/*
* XML Element Name Constants for the documents exchanged between the
* Casa Client and the Casa Server.
*/
private final static String casaIdentTokElementName = "casa_ident_tok";
private final static String idElementName = "id";
private final static String sourceNameElementName = "source_name";
private final static String sourceUrlElementName = "source_url";
private final static String targetServiceElementName = "target_service";
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;
private String m_sourceUrl = null;
private String m_service = null;
private String m_host = null;
private String m_token = null;
private javax.naming.directory.Attributes m_attributes = null;
/*
* 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_ROOT_ELEMENT_END = 1;
private final static int AWAITING_ID_ELEMENT_START = 2;
private final static int AWAITING_ID_ELEMENT_END = 3;
private final static int AWAITING_ID_DATA = 4;
private final static int AWAITING_SOURCE_NAME_ELEMENT_START = 5;
private final static int AWAITING_SOURCE_NAME_ELEMENT_END = 6;
private final static int AWAITING_SOURCE_NAME_DATA = 7;
private final static int AWAITING_SOURCE_URL_ELEMENT_START = 8;
private final static int AWAITING_SOURCE_URL_ELEMENT_END = 9;
private final static int AWAITING_SOURCE_URL_DATA = 10;
private final static int AWAITING_TARGET_SERVICE_ELEMENT_START = 11;
private final static int AWAITING_TARGET_SERVICE_ELEMENT_END = 12;
private final static int AWAITING_TARGET_SERVICE_DATA = 13;
private final static int AWAITING_TARGET_HOST_ELEMENT_START = 14;
private final static int AWAITING_TARGET_HOST_ELEMENT_END = 15;
private final static int AWAITING_TARGET_HOST_DATA = 16;
private final static int AWAITING_ATTRIBUTES_ELEMENT_START = 17;
private final static int AWAITING_ATTRIBUTE_START = 18;
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 CasaIdentityToken m_casaIdentToken;
private int m_state;
private String m_currAttribute;
private boolean m_encryptedAttrs;
/*
* Constructor
*/
public SAXHandler (CasaIdentityToken casaIdentityToken)
{
super();
// Initialize our members
m_casaIdentToken = casaIdentityToken;
m_state = AWAITING_ROOT_ELEMENT_START;
}
/*
* endDocument() implementation.
*/
public void endDocument () throws SAXException
{
// Verify that we obtained all of the required elements
if (m_state != DONE_PARSING)
{
System.err.println("CasaIdentityToken SAXHandler.endDocument()- Missing element");
throw new SAXException("Missing element");
}
}
/*
*
* startElement() implementation.
*/
public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
{
// Proceed based on our state
switch (m_state)
{
case AWAITING_ROOT_ELEMENT_START:
// Verify that we are processing the expected tag
if (casaIdentTokElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_ID_ELEMENT_START;
}
else
{
System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_ID_ELEMENT_START:
// Verify that we are processing the expected tag
if (idElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_ID_DATA;
}
else
{
System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_SOURCE_NAME_ELEMENT_START:
// Verify that we are processing the expected tag
if (sourceNameElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_SOURCE_NAME_DATA;
}
else
{
System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_SOURCE_URL_ELEMENT_START:
// Verify that we are processing the expected tag
if (sourceUrlElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_SOURCE_URL_DATA;
}
else
{
System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_TARGET_SERVICE_ELEMENT_START:
// Verify that we are processing the expected tag
if (targetServiceElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_TARGET_SERVICE_DATA;
}
else
{
System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_TARGET_HOST_ELEMENT_START:
// Verify that we are processing the expected tag
if (targetHostElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_TARGET_HOST_DATA;
}
else
{
System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_ATTRIBUTES_ELEMENT_START:
// Verify that we are processing the expected tag
if (attributesElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_ATTRIBUTE_START;
}
else
{
System.err.println("CasaIdentityToken SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_ATTRIBUTE_START:
// Save the element name as the current attribute
m_currAttribute = qName;
// Advance to the next state based on the attribute type
String attrType = atts.getValue("type");
if (attrType != null && attrType.equals("binary"))
{
// We are dealing with a binary attribute. We are going to
// assume that binary attributes are always base64 encoded.
m_state = AWAITING_BINARY_ATTRIBUTE_DATA;
}
else
{
// Assume we are dealing with an attribute of type string
m_state = AWAITING_ATTRIBUTE_DATA;
}
break;
default:
System.err.println("CasaIdentityToken SAXHandler.startElement()- State error");
throw new SAXException("State error");
}
}
/*
* endElement() immplementation.
*/
public void endElement (String uri, String name, String qName) throws SAXException
{
// Proceed based on our state
switch (m_state)
{
case AWAITING_ROOT_ELEMENT_END:
// Verify that we are processing the expected tag
if (casaIdentTokElementName.equals(qName))
{
// Advance to the next state
m_state = DONE_PARSING;
}
else
{
System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_ID_ELEMENT_END:
// Verify that we are processing the expected tag
if (idElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_SOURCE_NAME_ELEMENT_START;
}
else
{
System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_SOURCE_NAME_ELEMENT_END:
// Verify that we are processing the expected tag
if (sourceNameElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_SOURCE_URL_ELEMENT_START;
}
else
{
System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_SOURCE_URL_ELEMENT_END:
// Verify that we are processing the expected tag
if (sourceUrlElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_TARGET_SERVICE_ELEMENT_START;
}
else
{
System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_TARGET_SERVICE_ELEMENT_END:
// Verify that we are processing the expected tag
if (targetServiceElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_TARGET_HOST_ELEMENT_START;
}
else
{
System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_TARGET_HOST_ELEMENT_END:
// Verify that we are processing the expected tag
if (targetHostElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_ATTRIBUTES_ELEMENT_START;
}
else
{
System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_ATTRIBUTE_END:
// 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))
{
// Advance to the next state
m_state = AWAITING_ROOT_ELEMENT_END;
}
else
{
System.err.println("CasaIdentityToken SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
default:
System.err.println("CasaIdentityToken SAXHandler.startElement()- State error");
throw new SAXException("State error");
}
}
/*
* character() implementation.
*/
public void characters (char ch[], int start, int length) throws SAXException
{
// Proceed based on our state
switch (m_state)
{
case AWAITING_ID_DATA:
// Consume the data
m_casaIdentToken.m_identityId = new String(ch, start, length);
// Advance to the next state
m_state = AWAITING_ID_ELEMENT_END;
break;
case AWAITING_SOURCE_NAME_DATA:
// Consume the data
m_casaIdentToken.m_sourceName = new String(ch, start, length);
// Advance to the next state
m_state = AWAITING_SOURCE_NAME_ELEMENT_END;
break;
case AWAITING_SOURCE_URL_DATA:
// Consume the data
m_casaIdentToken.m_sourceUrl = new String(ch, start, length);
// Advance to the next state
m_state = AWAITING_SOURCE_URL_ELEMENT_END;
break;
case AWAITING_TARGET_SERVICE_DATA:
// Consume the data
m_casaIdentToken.m_service = new String(ch, start, length);
// Advance to the next state
m_state = AWAITING_TARGET_SERVICE_ELEMENT_END;
break;
case AWAITING_TARGET_HOST_DATA:
// Consume the data
m_casaIdentToken.m_host = new String(ch, start, length);
// At this point we now have the target service and host names,
// check if our configuration says that the attributes have been
// encrypted.
// 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;
break;
case AWAITING_ATTRIBUTE_DATA:
// 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
{
m_casaIdentToken.m_attributes.put(m_currAttribute, new String(ch, start, length));
}
// Advance to the next state
m_state = AWAITING_ATTRIBUTE_END;
break;
case AWAITING_BINARY_ATTRIBUTE_DATA:
// 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
{
// The data is base64 encoded
char[] encodedChars = new char[length];
System.arraycopy(ch, start, encodedChars, 0, length);
m_casaIdentToken.m_attributes.put(m_currAttribute, Base64Coder.decode(encodedChars));
}
// Advance to the next state
m_state = AWAITING_ATTRIBUTE_END;
break;
default:
// Do nothing
break;
}
}
}
/*
* Constructor.
*/
public CasaIdentityToken (IdenTokenConfig idenTokenConfig)
{
// Initialize our members
m_token = null;
m_attributes = new javax.naming.directory.BasicAttributes();
m_idenTokenConfig = idenTokenConfig;
}
/*
* Constructor.
*/
public CasaIdentityToken ()
{
// Initialize our members
m_token = null;
m_attributes = new javax.naming.directory.BasicAttributes();
m_idenTokenConfig = null;
}
/*
* Initialize with parameters.
*/
public void initialize (String identityId,
String sourceName,
String targetService,
String targetHost,
SvcConfig svcConfig) throws Exception
{
// Save input parameters
m_identityId = identityId;
m_sourceName = sourceName;
m_sourceUrl = "ldap://myldaphost.novell.com:389"; // tbd - Obtain from Identity Abstraction layer
m_service = targetService;
m_host = targetHost;
try
{
// 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, svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
env.put(IAContext.IA_REALM_SELECTOR, sourceName);
DirContext ctx = new InitialDirContext(env);
// Setup a string buffer for building the IdentityToken, notice for now
// we are not going to wrap the identity token.
StringBuffer sb = new StringBuffer();
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
sb.append("<" + casaIdentTokElementName + ">" + "\r\n");
sb.append("<" + idElementName + ">" + identityId + "</" + idElementName + ">\r\n");
sb.append("<" + sourceNameElementName + ">" + sourceName + "</" + sourceNameElementName + ">\r\n");
sb.append("<" + sourceUrlElementName + ">" + m_sourceUrl + "</" + sourceUrlElementName + ">\r\n");
sb.append("<" + targetServiceElementName + ">" + m_service + "</" + targetServiceElementName + ">\r\n");
sb.append("<" + targetHostElementName + ">" + m_host + "</" + targetHostElementName + ">\r\n");
sb.append("<" + attributesElementName + ">" + "\r\n");
// Get the necessary attributes of the specified services in the identity token
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();
NamingEnumeration enumeration = attr.getAll();
while (enumeration.hasMore())
{
Object attrValue = enumeration.next();
m_attributes.put(attr.getID(), attrValue);
System.err.println("CasaIdentityToken.initialize()- Including attribute " + attr.getID());
// Encrypt the attribute if necessary
if (encryptAttributes == true)
{
// tbd - Encrypt the attributes using the services public key, let the mechanism
// be configurable. The service's certificate should be Base64 encoded as a setting
// of the identoken.settings file.
}
else
{
// Proceed based on the attribute value type
if (attrValue instanceof byte[])
{
// The attribute value is of type byte[], we need to encode it.
sb.append("<" + attr.getID() + " type=\"binary\" encoding=\"base64\">" + new String(Base64Coder.encode((byte[]) attrValue)) + "</" + attr.getID() + ">" + "\r\n");
System.err.println("Attribute " + attr.getID() + "included as " + new String(Base64Coder.encode((byte[]) attrValue)));
}
else
{
// Assume the attribute value is of type String
sb.append("<" + attr.getID() + ">" + (String) attrValue + "</" + attr.getID() + ">" + "\r\n");
}
}
}
}
sb.append("</" + attributesElementName + ">" + "\r\n");
sb.append("</" + casaIdentTokElementName + ">" + "\r\n");
m_token = sb.toString();
}
catch (NamingException e)
{
// tbd - Log the event???
System.err.println("CasaIdentityToken.initialize()- Exception: " + e.getExplanation());
}
catch (Exception e)
{
// tbd
System.err.println("CasaIdentityToken.initialize()- Exception: " + e.toString());
}
}
/*
* Initialize the token object with an ecoded token string.
*/
public void initialize (String encodedToken) throws Exception
{
// Save copy of the token
m_token = Base64Coder.decode(encodedToken);
// Now parse the token into its elements
try
{
// Parse the AuthReqMsg
XMLReader xr = XMLReaderFactory.createXMLReader();
SAXHandler handler = new SAXHandler(this);
xr.setContentHandler(handler);
xr.setErrorHandler(handler);
ByteArrayInputStream inStream = new ByteArrayInputStream(m_token.getBytes());
InputSource source = new InputSource(inStream);
xr.parse(source);
}
catch (SAXException e)
{
// tbd - Log this.
System.err.println("CasaIdentityToken()- Parse exception: " + e.toString());
throw new Exception("Token error");
}
}
/*
* Returns encoded token string.
*
* IMPORTANT: The token string can not contain the substring "]]>"
* within it.
*/
public String getEncodedToken () throws Exception
{
if (m_token != null)
{
return Base64Coder.encode(m_token);
}
else
{
System.err.println("CasaIdentityToken.toString()- Not initialized");
throw new Exception("Not initialized");
}
}
/*
* Returns a string containing our type of identity token provider.
*/
public String getProviderType () throws Exception
{
// tbd - Change to a GUID
return "CasaIdentityToken";
}
/*
* Returns a string containing the identity id.
*/
public String getIdentityId () throws Exception
{
if (m_identityId != null)
return m_identityId;
else
{
System.err.println("CasaIdentityToken.getIdentityId()- Not initialized");
throw new Exception("Not initialized");
}
}
/*
* Returns a string containing the name associated with the
* identity source.
*/
public String getSourceName () throws Exception
{
if (m_sourceName != null)
return m_sourceName;
else
{
System.err.println("CasaIdentityToken.getSourceName()- Not initialized");
throw new Exception("Not initialized");
}
}
/*
* Returns a string containing the url associated with the
* identity source.
*/
public String getSourceUrl () throws Exception
{
if (m_sourceUrl != null)
return m_sourceUrl;
else
{
System.err.println("CasaIdentityToken.getSourceUrl()- Not initialized");
throw new Exception("Not initialized");
}
}
/*
* Returns a string containing the name of the targeted service.
*/
public String getTargetService () throws Exception
{
if (m_service != null)
return m_service;
else
{
System.err.println("CasaIdentityToken.getTargetService()- Not initialized");
throw new Exception("Not initialized");
}
}
/*
* Returns a string containig the name of the host where the
* targeted service resides.
*/
public String getTargetHost () throws Exception
{
if (m_host != null)
return m_host;
else
{
System.err.println("CasaIdentityToken.getTargetHost()- Not initialized");
throw new Exception("Not initialized");
}
}
/*
* Returns the attributes of the identity.
*/
public javax.naming.directory.Attributes getAttributes () throws Exception
{
if (m_attributes != null)
return m_attributes;
else
{
System.err.println("CasaIdentityToken.getIdentityAttributes()- Not initialized");
throw new Exception("Not initialized");
}
}
}

View File

@@ -0,0 +1,422 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.*;
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 boolean m_enabledSvcsOnly;
// Default auth policy, authtoken, and identtoken configs.
byte[] m_defaultAuthPolicyData = null;
AuthTokenConfig m_defaultAuthTokenConfig = null;
IdenTokenConfig m_defaultIdenTokenConfig = null;
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,
boolean enabledSvcsOnly) throws Exception
{
System.err.println("EnabledSvcsConfig()-");
System.err.println("EnabledSvcsConfig()- SvcConfigPath = " + svcConfigPath);
// Remember the enabledSvcsOnly setting
m_enabledSvcsOnly = enabledSvcsOnly;
// 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);
m_defaultAuthPolicyData = new byte[(int) f.length()];
FileInputStream 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");
}
}
catch (SecurityException e)
{
System.err.println("EnabledSvcsConfig()- SecurityException accessing " + configFolder + File.separator + m_authPolicyFileName + " Exception=" + e.toString());
}
catch (FileNotFoundException e)
{
System.err.println("EnabledSvcsConfig()- File " + configFolder + File.separator + m_authPolicyFileName + " not found");
}
catch (IOException e)
{
System.err.println("EnabledSvcsConfig()- IOException reading " + configFolder + File.separator + m_authPolicyFileName + " Exception=" + e.toString());
}
// Try to obtain the default authentication token settings
try
{
m_defaultAuthTokenConfig = new AuthTokenConfig(configFolder + File.separator + m_authTokenSettingsFileName);
}
catch (Exception e)
{
// Not able to create authentication token configuration using the default
// file. Create one using default parameters.
m_defaultAuthTokenConfig = new AuthTokenConfig();
}
// Try to obtain the default identity token settings
try
{
m_defaultIdenTokenConfig = new IdenTokenConfig(configFolder + File.separator + m_idenTokenSettingsFileName);
}
catch (Exception e)
{
// Not able to create identity token configuration using the default
// file. Create one using default parameters.
m_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, "enabled_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 + File.separator + 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 + File.separator + m_authPolicyFileName + " Exception=" + e.toString());
}
try
{
authTokenConfig = new AuthTokenConfig(serviceFolder + File.separator + m_authTokenSettingsFileName);
}
catch (Exception e)
{
System.err.println("EnabledSvcsConfig()- Exception accessing " + serviceFolder + File.separator + m_authTokenSettingsFileName + " Exception=" + e.toString());
}
try
{
idenTokenConfig = new IdenTokenConfig(serviceFolder + File.separator + m_idenTokenSettingsFileName);
}
catch (Exception e)
{
System.err.println("EnabledSvcsConfig()- Exception accessing " + serviceFolder + File.separator + m_idenTokenSettingsFileName + " Exception=" + e.toString());
}
// Make sure that we have a policy file
if ((authPolicyData != null && authPolicyData.length != 0)
|| (m_defaultAuthPolicyData != null && m_defaultAuthPolicyData.length != 0))
{
// Instantiate SvcConfigEntry for this service and place it in our map
SvcConfigEntry svcConfigEntry = new SvcConfigEntry((authPolicyData != null && authPolicyData.length != 0) ? authPolicyData : m_defaultAuthPolicyData,
(authTokenConfig != null) ? authTokenConfig : m_defaultAuthTokenConfig,
(idenTokenConfig != null) ? idenTokenConfig : m_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());
}
}
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)
{
// Always return try if m_enabledSvcsOnly is configured "false" else
// check the enabled svcs configuration.
if (m_enabledSvcsOnly == false)
{
return true;
}
else
{
// 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)
{
byte[] authPolicyData = null;
// 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)
{
authPolicyData = svcConfigEntry.m_authPolicyFileData;
}
}
// If m_enabledSvcsOnly is configured "false" and if no authentication policy
// data was found for this service then return the default authentication policy
// data.
if (authPolicyData == null
&& m_enabledSvcsOnly == false)
{
authPolicyData = m_defaultAuthPolicyData;
}
return authPolicyData;
}
/*
* Returns the authentication token configuration associated with the
* specified service.
*/
public AuthTokenConfig getAuthTokenConfig(String hostName, String serviceName)
{
AuthTokenConfig authTokenConfig = null;
// 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)
{
authTokenConfig = svcConfigEntry.m_authTokenConfig;
}
}
// If m_enabledSvcsOnly is configured "false" and if no AuthTokenConfig
// was found for this service then return the default AuthTokenConfig.
if (authTokenConfig == null
&& m_enabledSvcsOnly == false)
{
authTokenConfig = m_defaultAuthTokenConfig;
}
return authTokenConfig;
}
/*
* Returns the identity token configuration associated with the
* specified service.
*/
public IdenTokenConfig getIdenTokenConfig(String hostName, String serviceName)
{
IdenTokenConfig idenTokenConfig = null;
// 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)
{
idenTokenConfig = svcConfigEntry.m_idenTokenConfig;
}
}
// If m_enabledSvcsOnly is configured "false" and if no IdenTokenConfig
// was found for this service then return the default IdenTokenConfig.
if (idenTokenConfig == null
&& m_enabledSvcsOnly == false)
{
idenTokenConfig = m_defaultIdenTokenConfig;
}
return idenTokenConfig;
}
}

View File

@@ -0,0 +1,132 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.*;
import java.io.PrintWriter;
import java.util.*;
/**
* GetAuthPolicy Class.
*
* This class processes get authentication policy requests for a particular
* service.
*
*/
public class GetAuthPolicy implements RpcMethod
{
private SvcConfig m_svcConfig;
private EnabledSvcsConfig m_enabledSvcsConfig;
/*
* Constructor.
*/
public GetAuthPolicy() throws Exception
{
// Nothing to do at this time
}
/*
* Initialize the Rpc method.
*/
public void init(SvcConfig svcConfig, EnabledSvcsConfig enabledSvcsConfig) throws Exception
{
m_svcConfig = svcConfig;
m_enabledSvcsConfig = enabledSvcsConfig;
}
/*
* Process Rpc.
*/
public void invoke(InputStream inStream, PrintWriter out) throws IOException
{
try
{
System.err.println("GetAuthPolicy.invoke()");
// Read and parse the GetAuthPolicyReqMsg sent from the client
GetAuthPolicyReqMsg getAuthPolicyReqMsg = new GetAuthPolicyReqMsg(inStream);
// 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());
System.err.println("GetAuthPolicy.invoke()- Service "
+ getAuthPolicyReqMsg.getServiceName()
+ " at " + getAuthPolicyReqMsg.getHostName()
+ " not enabled");
}
}
catch (Exception e)
{
System.err.println("GetAuthPolicy.invoke()- Exception: " + e.toString());
// Write out the response
try
{
GetAuthPolicyRespMsg getAuthPolicyRespMsg = new GetAuthPolicyRespMsg(ProtoDefs.httpServerErrorStatusMsg,
ProtoDefs.httpServerErrorStatusCode);
out.println(getAuthPolicyRespMsg.toString());
}
catch (Exception e2)
{
System.err.println("GetAuthPolicy.invoke()- Exception trying to construct response msg: " + e2.toString());
}
}
}
/*
* Return the method id.
*/
public String getId()
{
return "GetAuthPolicy";
}
}

View File

@@ -0,0 +1,289 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.InputStream;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* GetAuthPolicyReqMsg Class.
*
* This class deals with the message sent by Casa Client when requesting
* authenication policy to authenticate an entity to a particular service.
* The format of the the message is as follows:
*
* <?xml version="1.0" encoding="ISO-8859-1"?>
* <get_auth_policy_req>
* <service>service name</service>
* <host>host name</host>
* </get_auth_policy_req>
*
*/
public class GetAuthPolicyReqMsg
{
protected String m_serviceName = null;
protected String m_hostName = null;
/*
* Class for handling GetAuthPolicyReq msg parsing events.
*/
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
{
private final static int AWAITING_ROOT_ELEMENT_START = 0;
private final static int AWAITING_ROOT_ELEMENT_END = 1;
private final static int AWAITING_SERVICE_ELEMENT_START = 2;
private final static int AWAITING_SERVICE_ELEMENT_END = 3;
private final static int AWAITING_SERVICE_DATA = 4;
private final static int AWAITING_HOST_ELEMENT_START = 5;
private final static int AWAITING_HOST_ELEMENT_END = 6;
private final static int AWAITING_HOST_DATA = 7;
private final static int DONE_PARSING = 8;
private GetAuthPolicyReqMsg m_GetAuthPolicyReqMsg;
private int m_state;
/*
* Constructor
*/
public SAXHandler (GetAuthPolicyReqMsg GetAuthPolicyReqMsg)
{
super();
// Initialize our members
m_GetAuthPolicyReqMsg = GetAuthPolicyReqMsg;
m_state = AWAITING_ROOT_ELEMENT_START;
}
/*
* endDocument() implementation.
*/
public void endDocument () throws SAXException
{
// Verify that we obtained all of the required elements
if (m_state != DONE_PARSING)
{
System.err.println("GetAuthPolicyReqMsg SAXHandler.endDocument()- Missing element");
throw new SAXException("Missing element");
}
}
/*
* startElement() implementation.
*/
public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
{
// Proceed based on our state
switch (m_state)
{
case AWAITING_ROOT_ELEMENT_START:
// Verify that we are processing the expected tag
if (ProtoDefs.getAuthPolicyRequestElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_SERVICE_ELEMENT_START;
}
else
{
System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_SERVICE_ELEMENT_START:
// Verify that we are processing the expected tag
if (ProtoDefs.serviceElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_SERVICE_DATA;
}
else
{
System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_HOST_ELEMENT_START:
// Verify that we are processing the expected tag
if (ProtoDefs.hostElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_HOST_DATA;
}
else
{
System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
default:
System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- State error");
throw new SAXException("State error");
}
}
/*
* endElement() immplementation.
*/
public void endElement (String uri, String name, String qName) throws SAXException
{
// Proceed based on our state
switch (m_state)
{
case AWAITING_ROOT_ELEMENT_END:
// Verify that we are processing the expected tag
if (ProtoDefs.getAuthPolicyRequestElementName.equals(qName))
{
// Advance to the next state
m_state = DONE_PARSING;
}
else
{
System.err.println("GetAuthPolicyReqMsg SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_SERVICE_ELEMENT_END:
// Verify that we are processing the expected tag
if (ProtoDefs.serviceElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_HOST_ELEMENT_START;
}
else
{
System.err.println("GetAuthPolicyReqMsg SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_HOST_ELEMENT_END:
// Verify that we are processing the expected tag
if (ProtoDefs.hostElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_ROOT_ELEMENT_END;
}
else
{
System.err.println("GetAuthPolicyReqMsg SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
default:
System.err.println("GetAuthPolicyReqMsg SAXHandler.startElement()- State error");
throw new SAXException("State error");
}
}
/*
* character() implementation.
*/
public void characters (char ch[], int start, int length) throws SAXException
{
// Proceed based on our state
switch (m_state)
{
case AWAITING_SERVICE_DATA:
// Consume the data
m_GetAuthPolicyReqMsg.m_serviceName = new String(ch, start, length);
// Advance to the next state
m_state = AWAITING_SERVICE_ELEMENT_END;
break;
case AWAITING_SERVICE_ELEMENT_END:
// Consume the data
m_GetAuthPolicyReqMsg.m_serviceName = m_GetAuthPolicyReqMsg.m_serviceName.concat(new String(ch, start, length));
break;
case AWAITING_HOST_DATA:
// Consume the data
m_GetAuthPolicyReqMsg.m_hostName = new String(ch, start, length);
// Advance to the next state
m_state = AWAITING_HOST_ELEMENT_END;
break;
case AWAITING_HOST_ELEMENT_END:
// Consume the data
m_GetAuthPolicyReqMsg.m_hostName = m_GetAuthPolicyReqMsg.m_hostName.concat(new String(ch, start, length));
break;
default:
// Do nothing
break;
}
}
}
/*
* Constructor
*/
public GetAuthPolicyReqMsg (InputStream inStream) throws Exception
{
try
{
// Parse the GetAuthPolicyReqMsg
XMLReader xr = XMLReaderFactory.createXMLReader();
SAXHandler handler = new SAXHandler(this);
xr.setContentHandler(handler);
xr.setErrorHandler(handler);
InputSource source = new InputSource(inStream);
xr.parse(source);
}
catch (SAXException e)
{
System.err.println("GetAuthPolicyReqMsg()- Parse exception: " + e.toString());
throw new Exception("Protocol error");
}
}
/*
* Method to get the service name.
*/
public String getServiceName() throws Exception
{
return m_serviceName;
}
/*
* Method to get the host name.
*/
public String getHostName() throws Exception
{
return m_hostName;
}
}

View File

@@ -0,0 +1,111 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
/**
* GetAuthPolicyRespMsg Class.
*
* This class deals with the message sent to the Casa Client as a
* response to a get authentication token request. The format of
* the message is as follows when the response includes an
* authentication token:
*
* <?xml version="1.0" encoding="ISO-8859-1"?>
* <get_auth_policy_resp>
* <status><description>OK</description>200</status>
* <auth_policy>authentication policy data</auth_policy>
* </get_auth_policy_resp>
*
* The format of the message is as follows when the response does not
* include an authentication token.
*
* <?xml version="1.0" encoding="ISO-8859-1"?>
* <get_auth_policy_resp>
* <status><description>status description</description>status code</status>
* </get_auth_policy_resp>
*
* Plase note that the protocol utilizes the status codes defined
* in the HTTP 1.1 Specification.
*
*/
public class GetAuthPolicyRespMsg
{
String m_msg;
/*
* Constructor for a msg that does not include the authentication policy.
*/
public GetAuthPolicyRespMsg (
String statusDescription,
String statusCode) throws Exception
{
// Get a StringBuffer to help us with the construction of the message
StringBuffer sb = new StringBuffer();
// Start building the message
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
sb.append("<" + ProtoDefs.getAuthPolicyResponseElementName + ">" + "\r\n");
sb.append("<" + ProtoDefs.statusElementName + ">"
+ "<" + ProtoDefs.descriptionElementName + ">" + statusDescription + "</" + ProtoDefs.descriptionElementName + ">"
+ statusCode + "</" + ProtoDefs.statusElementName + ">" + "\r\n");
sb.append("</" + ProtoDefs.getAuthPolicyResponseElementName + ">" + "\r\n");
// The message has now been built, save it.
m_msg = sb.toString();
}
/*
* Constructor for a msg that includes the authentication policy.
*/
public GetAuthPolicyRespMsg (
String statusDescription,
String statusCode,
String authPolicy) throws Exception
{
// Get a StringBuffer to help us with the construction of the message
StringBuffer sb = new StringBuffer();
// Start building the message
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
sb.append("<" + ProtoDefs.getAuthPolicyResponseElementName + ">" + "\r\n");
sb.append("<" + ProtoDefs.statusElementName + ">"
+ "<" + ProtoDefs.descriptionElementName + ">" + ProtoDefs.httpOkStatusMsg + "</" + ProtoDefs.descriptionElementName + ">"
+ ProtoDefs.httpOkStatusCode + "</" + ProtoDefs.statusElementName + ">" + "\r\n");
sb.append("<" + ProtoDefs.authPolicyElementName + ">" + authPolicy + "</" + ProtoDefs.authPolicyElementName + ">" + "\r\n");
sb.append("</" + ProtoDefs.getAuthPolicyResponseElementName + ">" + "\r\n");
// The message has now been built, save it.
m_msg = sb.toString();
}
/*
* Returns a string containing the GetAuthPolicyRespMsg.
*/
public String toString()
{
return m_msg;
}
}

View File

@@ -0,0 +1,343 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.InputStream;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* GetAuthTokReqMsg Class.
*
* This class deals with the message sent by Casa Client when requesting
* a token to authenticate an entity to a particular service. The format of
* the message is as follows:
*
* <?xml version="1.0" encoding="ISO-8859-1"?>
* <get_auth_token_req>
* <service>service name</service>
* <host>host name</host>
* <session_token>session token data</session_token>
* </get_auth_token_req>
*
*/
public class GetAuthTokReqMsg
{
protected String m_serviceName = null;
protected String m_hostName = null;
protected String m_sessionToken = null;
/*
* Class for handling GetAuthTokReq msg parsing events.
*/
private class SAXHandler extends org.xml.sax.helpers.DefaultHandler
{
private final static int AWAITING_ROOT_ELEMENT_START = 0;
private final static int AWAITING_ROOT_ELEMENT_END = 1;
private final static int AWAITING_SERVICE_ELEMENT_START = 2;
private final static int AWAITING_SERVICE_ELEMENT_END = 3;
private final static int AWAITING_SERVICE_DATA = 4;
private final static int AWAITING_HOST_ELEMENT_START = 5;
private final static int AWAITING_HOST_ELEMENT_END = 6;
private final static int AWAITING_HOST_DATA = 7;
private final static int AWAITING_SESSION_TOKEN_ELEMENT_START = 8;
private final static int AWAITING_SESSION_TOKEN_ELEMENT_END = 9;
private final static int AWAITING_SESSION_TOKEN_DATA = 10;
private final static int DONE_PARSING = 11;
private GetAuthTokReqMsg m_GetAuthTokReqMsg;
private int m_state;
/*
* Constructor
*/
public SAXHandler (GetAuthTokReqMsg GetAuthTokReqMsg)
{
super();
// Initialize our members
m_GetAuthTokReqMsg = GetAuthTokReqMsg;
m_state = AWAITING_ROOT_ELEMENT_START;
}
/*
* endDocument() implementation.
*/
public void endDocument () throws SAXException
{
// Verify that we obtained all of the required elements
if (m_state != DONE_PARSING)
{
System.err.println("GetAuthTokReqMsg SAXHandler.endDocument()- Missing element");
throw new SAXException("Missing element");
}
}
/*
* startElement() implementation.
*/
public void startElement (String uri, String name, String qName, org.xml.sax.Attributes atts) throws SAXException
{
// Proceed based on our state
switch (m_state)
{
case AWAITING_ROOT_ELEMENT_START:
// Verify that we are processing the expected tag
if (ProtoDefs.getAuthTokRequestElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_SERVICE_ELEMENT_START;
}
else
{
System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_SERVICE_ELEMENT_START:
// Verify that we are processing the expected tag
if (ProtoDefs.serviceElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_SERVICE_DATA;
}
else
{
System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_HOST_ELEMENT_START:
// Verify that we are processing the expected tag
if (ProtoDefs.hostElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_HOST_DATA;
}
else
{
System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_SESSION_TOKEN_ELEMENT_START:
// Verify that we are processing the expected tag
if (ProtoDefs.sessionTokenElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_SESSION_TOKEN_DATA;
}
else
{
System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
default:
System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- State error");
throw new SAXException("State error");
}
}
/*
* endElement() immplementation.
*/
public void endElement (String uri, String name, String qName) throws SAXException
{
// Proceed based on our state
switch (m_state)
{
case AWAITING_ROOT_ELEMENT_END:
// Verify that we are processing the expected tag
if (ProtoDefs.getAuthTokRequestElementName.equals(qName))
{
// Advance to the next state
m_state = DONE_PARSING;
}
else
{
System.err.println("GetAuthTokReqMsg SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_SERVICE_ELEMENT_END:
// Verify that we are processing the expected tag
if (ProtoDefs.serviceElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_HOST_ELEMENT_START;
}
else
{
System.err.println("GetAuthTokReqMsg SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_HOST_ELEMENT_END:
// Verify that we are processing the expected tag
if (ProtoDefs.hostElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_SESSION_TOKEN_ELEMENT_START;
}
else
{
System.err.println("GetAuthTokReqMsg SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
case AWAITING_SESSION_TOKEN_ELEMENT_END:
// Verify that we are processing the expected tag
if (ProtoDefs.sessionTokenElementName.equals(qName))
{
// Advance to the next state
m_state = AWAITING_ROOT_ELEMENT_END;
}
else
{
System.err.println("GetAuthTokReqMsg SAXHandler.endElement()- Un-expected element");
throw new SAXException("Un-expected element");
}
break;
default:
System.err.println("GetAuthTokReqMsg SAXHandler.startElement()- State error");
throw new SAXException("State error");
}
}
/*
* character() implementation.
*/
public void characters (char ch[], int start, int length) throws SAXException
{
// Proceed based on our state
switch (m_state)
{
case AWAITING_SERVICE_DATA:
// Consume the data
m_GetAuthTokReqMsg.m_serviceName = new String(ch, start, length);
// Advance to the next state
m_state = AWAITING_SERVICE_ELEMENT_END;
break;
case AWAITING_SERVICE_ELEMENT_END:
// Consume the data
m_GetAuthTokReqMsg.m_serviceName = m_GetAuthTokReqMsg.m_serviceName.concat(new String(ch, start, length));
break;
case AWAITING_HOST_DATA:
// Consume the data
m_GetAuthTokReqMsg.m_hostName = new String(ch, start, length);
// Advance to the next state
m_state = AWAITING_HOST_ELEMENT_END;
break;
case AWAITING_HOST_ELEMENT_END:
// Consume the data
m_GetAuthTokReqMsg.m_hostName = m_GetAuthTokReqMsg.m_hostName.concat(new String(ch, start, length));
break;
case AWAITING_SESSION_TOKEN_DATA:
// Consume the data
m_GetAuthTokReqMsg.m_sessionToken = new String(ch, start, length);
// Advance to the next state
m_state = AWAITING_SESSION_TOKEN_ELEMENT_END;
break;
case AWAITING_SESSION_TOKEN_ELEMENT_END:
// Consume the data
m_GetAuthTokReqMsg.m_sessionToken = m_GetAuthTokReqMsg.m_sessionToken.concat(new String(ch, start, length));
break;
default:
// Do nothing
break;
}
}
}
/*
* Constructor
*/
public GetAuthTokReqMsg (InputStream inStream) throws Exception
{
try
{
// Parse the GetAuthTokReqMsg
XMLReader xr = XMLReaderFactory.createXMLReader();
SAXHandler handler = new SAXHandler(this);
xr.setContentHandler(handler);
xr.setErrorHandler(handler);
InputSource source = new InputSource(inStream);
xr.parse(source);
}
catch (SAXException e)
{
System.err.println("GetAuthTokReqMsg()- Parse exception: " + e.toString());
throw new Exception("Protocol error");
}
}
/*
* Method to get the service name.
*/
public String getServiceName() throws Exception
{
return m_serviceName;
}
/*
* Method to get the host name.
*/
public String getHostName() throws Exception
{
return m_hostName;
}
/*
* Method to get the session token.
*/
public String getSessionToken() throws Exception
{
return m_sessionToken;
}
}

View File

@@ -0,0 +1,115 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
/**
* GetAuthTokRespMsg Class.
*
* This class deals with the message sent to the Casa Client as a
* response to a get authentication token request. The format of
* the message is as follows when the response includes an
* authentication token:
*
* <?xml version="1.0" encoding="ISO-8859-1"?>
* <get_auth_tok_resp>
* <status><description>OK</description>200</status>
* <auth_token><lifetime>lifetime value</lifetime>authentication token data</auth_token>
* </get_auth_tok_resp>
*
* The format of the message is as follows when the response does not
* include an authentication token.
*
* <?xml version="1.0" encoding="ISO-8859-1"?>
* <get_auth_tok_resp>
* <status><description>status description</description>status code</status>
* </get_auth_tok_resp>
*
* Plase note that the protocol utilizes the status codes defined
* in the HTTP 1.1 Specification.
*
*/
public class GetAuthTokRespMsg
{
String m_msg;
/*
* Constructor for a msg that does not include the authentication token.
*/
public GetAuthTokRespMsg (
String statusDescription,
String statusCode) throws Exception
{
// Get a StringBuffer to help us with the construction of the message
StringBuffer sb = new StringBuffer();
// Start building the message
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
sb.append("<" + ProtoDefs.getAuthTokResponseElementName + ">" + "\r\n");
sb.append("<" + ProtoDefs.statusElementName + ">"
+ "<" + ProtoDefs.descriptionElementName + ">" + statusDescription + "</" + ProtoDefs.descriptionElementName + ">"
+ statusCode + "</" + ProtoDefs.statusElementName + ">" + "\r\n");
sb.append("</" + ProtoDefs.getAuthTokResponseElementName + ">" + "\r\n");
// The message has now been built, save it.
m_msg = sb.toString();
}
/*
* Constructor for a msg that includes the authentication token.
*/
public GetAuthTokRespMsg (
String statusDescription,
String statusCode,
String authToken,
String authTokenLifetime) throws Exception
{
// Get a StringBuffer to help us with the construction of the message
StringBuffer sb = new StringBuffer();
// Start building the message
sb.append(ProtoDefs.xmlDeclaration + "\r\n");
sb.append("<" + ProtoDefs.getAuthTokResponseElementName + ">" + "\r\n");
sb.append("<" + ProtoDefs.statusElementName + ">"
+ "<" + ProtoDefs.descriptionElementName + ">" + ProtoDefs.httpOkStatusMsg + "</" + ProtoDefs.descriptionElementName + ">"
+ ProtoDefs.httpOkStatusCode + "</" + ProtoDefs.statusElementName + ">" + "\r\n");
sb.append("<" + ProtoDefs.authTokenElementName + ">"
+ "<" + ProtoDefs.lifetimeElementName + ">" + authTokenLifetime + "</" + ProtoDefs.lifetimeElementName + ">"
+ authToken + "</" + ProtoDefs.authTokenElementName + ">" + "\r\n");
sb.append("</" + ProtoDefs.getAuthTokResponseElementName + ">" + "\r\n");
// The message has now been built, save it.
m_msg = sb.toString();
}
/*
* Returns a string containing the GetAuthTokRespMsg.
*/
public String toString()
{
return m_msg;
}
}

View File

@@ -0,0 +1,146 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
/**
* GetAuthToken Class.
*
* This class processes requests for tokens to authenticate an entity
* to a particular service.
*
*/
public class GetAuthToken implements RpcMethod
{
private SvcConfig m_svcConfig;
private EnabledSvcsConfig m_enabledSvcsConfig;
/*
* Constructor.
*/
public GetAuthToken() throws Exception
{
// Nothing to do at this time
}
/*
* Initialize the Rpc method.
*/
public void init(SvcConfig svcConfig, EnabledSvcsConfig enabledSvcsConfig) throws Exception
{
m_svcConfig = svcConfig;
m_enabledSvcsConfig = enabledSvcsConfig;
}
/*
* Process Rpc.
*/
public void invoke(InputStream inStream, PrintWriter out) throws IOException
{
try
{
System.err.println("GetAuthToken.invoke()");
// Parse the GetAuthTokReqMsg sent from the client
GetAuthTokReqMsg getAuthTokReqMsg = new GetAuthTokReqMsg(inStream);
// Verify that the service is enabled
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
{
// 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 e)
{
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)
{
System.err.println("GetAuthToken.invoke()- Exception: " + e.toString());
// Write out the response
try
{
GetAuthTokRespMsg getAuthTokRespMsg = new GetAuthTokRespMsg(ProtoDefs.httpServerErrorStatusMsg,
ProtoDefs.httpServerErrorStatusCode);
out.println(getAuthTokRespMsg.toString());
}
catch (Exception e2)
{
System.err.println("GetAuthToken.invoke()- Exception trying to construct response msg: " + e2.toString());
}
}
}
/*
* Return the method id.
*/
public String getId()
{
return "GetAuthToken";
}
}

View File

@@ -0,0 +1,52 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
/**
*
* Interface exported by users of the SettingsFileUtil class.
*
*/
public interface IVerifySetting
{
/**
* Checks if the specified setting is valid.
*
* @param setting The name of the setting being checked.
* @return True if the specified setting is valid.
*/
boolean validSetting(String setting);
/**
* Checks if the specified setting is valid in conjunction
* with the specified value.
*
* @param setting The name of the setting being checked.
* @param value The value of the specified setting.
* @return The formal name of the setting if found to be valid.
*/
String validSettingNameAndValue(String setting,
String value);
}

View File

@@ -0,0 +1,294 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.*;
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_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.
*/
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;
}
}

View File

@@ -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 <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
/**
*
* Class for the creation and editing of identtoken.settings files.
*
**/
public class IdenTokenSettingsEditor implements IVerifySetting
{
private static final String usage =
"usage: IdenTokenSettingsEditor -op [settingName [settingValue]] -file settingsFilePath\n\n" +
" where:\n" +
" -op - Corresponds to one of the following operations:\n" +
" -create - Create new identoken settings file\n" +
" -list - List settings\n" +
" -get - Get settings, must be followed by settingName parameter\n" +
" -set - Set settings, must be followed by settingName and settingValue parameters\n" +
" -remove - Remove settings\n" +
" -file - Path the the identoken settings file\n" +
" settingName - Name of the setting being retrieved or set\n" +
" settingValue - Value of the setting being set\n\n" +
" The following settings are valid:\n" +
" Attributes\n";
private static final String settings =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<settings>\n" +
"</settings>\n";
/**
* Checks if the specified setting is valid.
*
* @param setting The name of the setting being checked.
* @return True if the specified setting is valid.
*/
public boolean validSetting(String setting)
{
boolean result = false;
if (setting.compareToIgnoreCase(IdenTokenConfig.EncryptAttributes) == 0)
result = true;
else if (setting.compareToIgnoreCase(IdenTokenConfig.Attributes) == 0)
result = true;
else
System.out.println("Invalid setting specified");
return result;
}
/**
* Checks if the specified setting is valid in conjunction
* with the specified value.
*
* @param setting The name of the setting being checked.
* @param value The value of the specified setting.
* @return The formal name of the setting if found to be valid.
*/
public String validSettingNameAndValue(String setting,
String value)
{
String validSetting = null;
if (setting.compareToIgnoreCase(IdenTokenConfig.EncryptAttributes) == 0)
{
// Always succeed
validSetting = IdenTokenConfig.EncryptAttributes;
}
else if (setting.compareToIgnoreCase(IdenTokenConfig.Attributes) == 0)
{
// Always succeed
validSetting = IdenTokenConfig.Attributes;
}
else
System.out.println("Invalid setting specified");
return validSetting;
}
/**
* Applications Entry Point
*
* @param args
*/
public static void main(String[] args)
{
String op = null;
boolean opPerformed = false;
boolean argumentsError = false;
String filePath = null;
String setting = null;
String value = null;
IdenTokenSettingsEditor editor = new IdenTokenSettingsEditor();
// Process the command line arguments
for (int i = 0; i < args.length; i++)
{
// Proceed based on the command
if (args[i].compareToIgnoreCase("-file") == 0)
{
// The next argument should contain the filepath
if (args.length > (i + 1))
{
filePath = args[i + 1];
i++;
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-list") == 0)
{
// List operation requested
if (op == null)
{
op = "list";
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-create") == 0)
{
// List operation requested
if (op == null)
{
op = "create";
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-get") == 0)
{
// Get setting operation requested
if (op == null)
{
op = "get";
// The next argument should contain the setting name
if (args.length > (i + 1))
{
setting = args[i + 1];
i++;
}
else
{
argumentsError = true;
break;
}
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-set") == 0)
{
// Set setting operation requested
if (op == null)
{
op = "set";
// The next two arguments should contain the setting name
// and the setting value.
if (args.length > (i + 2))
{
setting = args[i + 1];
value = args[i + 2];
i += 2;
}
else
{
argumentsError = true;
break;
}
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-remove") == 0)
{
// Remove setting operation requested
if (op == null)
{
op = "remove";
// The next argument should contain the setting name
if (args.length > (i + 1))
{
setting = args[i + 1];
i++;
}
else
{
argumentsError = true;
break;
}
}
else
{
argumentsError = true;
break;
}
}
else
{
argumentsError = true;
}
}
// Proceed based on the specified parameters
if (argumentsError == false)
{
if (filePath != null && op != null)
{
System.out.println("Dealing with settings file: " + filePath);
// Proceed based on the operation requested
if (op.compareTo("list") == 0)
{
opPerformed = SettingsFileUtil.performListOperation(filePath);
}
else if (op.compareTo("create") == 0)
{
opPerformed = SettingsFileUtil.performCreateOperation(filePath, settings);
}
else if (op.compareTo("get") == 0)
{
opPerformed = SettingsFileUtil.performGetOperation(filePath, setting, editor);
}
else if (op.compareTo("set") == 0)
{
opPerformed = SettingsFileUtil.performSetOperation(filePath, setting, value, editor);
}
else if (op.compareTo("remove") == 0)
{
opPerformed = SettingsFileUtil.performRemoveOperation(filePath, setting, editor);
}
else
{
System.err.println("Tool error");
}
}
else
{
argumentsError = true;
}
}
// Display the usage string if we encountered an error with the
// command line arguments.
if (argumentsError)
System.out.print(usage);
// Set the exit code appropriatedly
if (opPerformed)
System.exit(0);
else
System.exit(1);
}
}

View File

@@ -0,0 +1,93 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
/*
* IdentityToken Interface.
*
* This is the interface implemented by Identity Token Providers.
*/
public interface IdentityToken
{
/*
* Initialize the token with parameters.
*/
void initialize(String identityId,
String sourceName,
String targetService,
String targetHost,
SvcConfig svcConfig) throws Exception;
/*
* Initialize the token object with encoded token string.
*/
void initialize(String encodedToken) throws Exception;
/*
* Returns encoded token string.
*
* IMPORTANT: The token string can not contain the substring "]]>"
* within it.
*/
String getEncodedToken() throws Exception;
/*
* Returns a string containing the identity token provider type.
*/
String getProviderType() throws Exception;
/*
* Returns a string containing the identity id.
*/
String getIdentityId() throws Exception;
/*
* Returns a string containing the name associated with the
* identity source.
*/
String getSourceName() throws Exception;
/*
* Returns a string containing the url associated with the
* identity source.
*/
String getSourceUrl() throws Exception;
/*
* Returns a string containing the name of the targeted service.
*/
String getTargetService() throws Exception;
/*
* Returns a string containig the name of the host where the
* targeted service resides.
*/
String getTargetHost() throws Exception;
/*
* Returns the attributes of the identity.
*/
javax.naming.directory.Attributes getAttributes() throws Exception;
}

View File

@@ -0,0 +1,263 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.Serializable;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchResult;
import javax.naming.directory.SearchControls;
import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
import org.ietf.jgss.Oid;
import org.bandit.ia.IAContext;
/**
* Krb5Authenticate Class.
*
* This class implementes an authentication mechanism for
* the processing of authentication requests utilizing a
* Kerberos5 token.
*
*/
public class Krb5Authenticate implements AuthMechanism, Serializable
{
private SvcConfig m_svcConfig;
private AuthMechConfig m_mechConfig;
/*
* GSS Long Lived variables
*/
protected GSSManager m_manager;
protected Oid m_krb5;
protected GSSName m_svcName;
protected GSSCredential m_credential;
/*
* Krb5 Token Class.
*/
private class Krb5Token
{
private String m_principalName = "";
/*
* The format of the Krb5 token is as follows:
*
* Base64.encode(GSS-API Token data));
*/
public Krb5Token(String 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);
try
{
// Create a context and validate the token
GSSContext context = parent.m_manager.createContext(parent.m_credential);
System.err.println("tokenLength = " + tokenBytes.length);
context.acceptSecContext(tokenBytes, 0, tokenBytes.length);
// Save the principal name of the authenticated entity
GSSName principalName = context.getSrcName();
m_principalName = principalName.toString();
// Clean up
context.dispose();
}
catch (GSSException e)
{
System.err.println("Krb5Authenticate Krb5Token()- GSS Exception caught: " + e.getLocalizedMessage());
throw new Exception("Authentication Failure");
}
}
/*
* Returns the name of the authenticated principal
*/
public String getPrincipalName()
{
return m_principalName;
}
}
/*
* Constructor
*/
public Krb5Authenticate() throws Exception
{
// Nothing to do at this time
}
/*
* Initialize the mechanism.
*/
public void init(SvcConfig svcConfig, AuthMechConfig mechConfig) throws Exception
{
m_svcConfig = svcConfig;
m_mechConfig = mechConfig;
String servicePrincipal = mechConfig.getSetting(AuthMechConfig.Krb5ServicePrincipalName);
if (servicePrincipal != null)
{
try
{
// Make sure that the system property "javax.security.auth.useSubjectCredsOnly"
// is set to "false" to avoid having to utilize JAAS (at least if using IBM's JVM)
System.setProperty("javax.security.auth.useSubjectCredsOnly", "false");
// Initalize our GSS variables
//
// Get an instance of the default GSSManager
m_manager = GSSManager.getInstance();
// Create an OID specifying the Krb5 mechanism
m_krb5 = new Oid("1.2.840.113554.1.2.2");
// Create our host based service name
m_svcName = m_manager.createName(servicePrincipal,
GSSName.NT_HOSTBASED_SERVICE,
m_krb5);
// Now acquire our credentials
m_credential = m_manager.createCredential(m_svcName,
GSSCredential.INDEFINITE_LIFETIME,
m_krb5,
GSSCredential.ACCEPT_ONLY);
}
catch (GSSException e)
{
System.err.println("Krb5Authenticate()- GSS Exception caught: " + e.getLocalizedMessage());
throw new Exception("Failed to instantiate needed GSS objects");
}
}
else
{
System.err.println("Krb5Authenticate()- Service Principal Name not configured");
throw new Exception("Service Principal Name not configured");
}
}
/*
* invoke() implementation.
*/
public String invoke(AuthReqMsg authReqMsg) throws Exception
{
String identId = null;
try
{
System.err.println("Krb5Authenticate.invoke()");
// 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, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
env.put(IAContext.IA_REALM_SELECTOR, authReqMsg.getRealm());
DirContext ctx = new InitialDirContext(env);
// Now search for a user with a matching kerberos principal name.
//
// Set up a search control so that the search is scoped to the sub-tree
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// Obtain the start search context - tbd - this will be removed once the functionality flows into Bandit
String searchContext = m_svcConfig.getSetting(SvcConfig.StartSearchContext);
if (searchContext == null)
{
// A start search context was not configured, start from the root.
searchContext = "";
}
// Perform the search
NamingEnumeration answer = ctx.search(searchContext,
"(krbPrincipalName={0})",
new String[] {krb5Token.getPrincipalName()},
controls);
// Proceed based on the result of the search
if (answer.hasMore())
{
// The search succeeded, set the identity id.
SearchResult sr = (SearchResult)answer.next();
if (searchContext.equals(""))
{
identId = sr.getNameInNamespace();
}
else
{
identId = sr.getName() + "," + searchContext;
}
}
else
{
System.err.println("Krb5Authenticate.invoke()- No matching identity entities found");
}
}
catch (NamingException e)
{
// Log the error
System.err.println("Krb5Authenticate.invoke()- NamingException: " + e.getExplanation());
}
catch (Exception e)
{
System.err.println("Krb5Authenticate.invoke()- Exception: " + e.toString());
}
// Return the authentication result
return identId;
}
/*
* Return the mechanism id.
*/
public String getId()
{
return "Krb5Authenticate";
}
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<settings>
<description>This is the authentication mechanism for the Krb5Authenticate scheme. The Krb5Authenticate scheme authenticates entities using Kerberos-V tokens.</description>
<ClassName>com.novell.casa.authtoksvc.Krb5Authenticate</ClassName>
<RelativeClassPath>WEB-INF/classes</RelativeClassPath>
</settings>

View File

@@ -0,0 +1,70 @@
#######################################################################
#
# Copyright (C) 2006 Novell, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this program; if not, write to the Free
# Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Author: Juan Carlos Luciani <jluciani@novell.com>
#
#######################################################################
SUBDIRS =
DIST_SUBDIRS =
JAVAFILES = ProtoDefs.java \
AuthMechConfig.java \
SvcConfig.java \
IdenTokenConfig.java \
AuthTokenConfig.java \
EnabledSvcsConfig.java \
AuthMechanism.java \
Authenticate.java \
RpcMethod.java \
Rpc.java \
GetAuthPolicy.java \
Base64Coder.java \
AuthReqMsg.java \
AuthRespMsg.java \
IdentityToken.java \
CasaIdentityToken.java \
AuthToken.java \
GetAuthPolicyReqMsg.java \
GetAuthPolicyRespMsg.java \
GetAuthToken.java \
GetAuthTokReqMsg.java \
GetAuthTokRespMsg.java \
Krb5Authenticate.java \
PwdAuthenticate.java \
SessionToken.java \
WSSecurity.java \
AuthPolicyEditor.java \
AuthTokenSettingsEditor.java \
IdenTokenSettingsEditor.java \
IVerifySetting.java \
SettingsFileUtil.java \
SvcSettingsEditor.java
EXTRA_DIST = $(JAVAFILES) \
Krb5_mechanism.settings \
Pwd_mechanism.settings
.PHONY: package package-clean package-install package-uninstall
package package-clean package-install package-uninstall:
$(MAKE) -C $(TARGET_OS) $@
maintainer-clean-local:
rm -f Makefile.in

View File

@@ -0,0 +1,86 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
/*
* ProDefs Class.
*
* This class contains constants utilized in the Casa Client/Server
* protocol.
*
*/
public class ProtoDefs
{
/*
* XML Declaration used in the Casa Client/Server protocol
*/
public final static String xmlDeclaration = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>";
/*
* XML Element Name Constants for the documents exchanged between the
* Casa Client and the Casa Server.
*/
public final static String authRequestElementName = "auth_req";
public final static String authResponseElementName = "auth_resp";
public final static String getAuthPolicyRequestElementName = "get_auth_policy_req";
public final static String getAuthPolicyResponseElementName = "get_auth_policy_resp";
public final static String getAuthTokRequestElementName = "get_auth_tok_req";
public final static String getAuthTokResponseElementName = "get_auth_tok_resp";
public final static String authMechTokenElementName = "auth_mech_token";
public final static String statusElementName = "status";
public final static String sessionTokenElementName = "session_token";
public final static String authTokenElementName = "auth_token";
public final static String authPolicyElementName = "auth_policy";
public final static String identTokenElementName = "ident_token";
public final static String lifetimeElementName = "lifetime";
public final static String signatureElementName = "signature";
public final static String typeElementName = "type";
public final static String descriptionElementName = "description";
public final static String serviceElementName = "service";
public final static String hostElementName = "host";
public final static String identIdElementName = "ident_id";
public final static String realmElementName = "realm";
public final static String authSourceElementName = "auth_source";
public final static String mechanismElementName = "mechanism";
public final static String mechanismInfoElementName = "mechanism_info";
/*
* Configurable operating parameters
*/
public String sessionTokenLifetime = "360";
/*
* HTTP Status Codes and Messages
*/
public final static String httpOkStatusCode = "200";
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";
}

View File

@@ -0,0 +1,233 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.Serializable;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.DirContext;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchResult;
import javax.naming.directory.SearchControls;
import javax.naming.NamingException;
import org.bandit.ia.IAContext;
/**
* PwdAuthenticate Class.
*
* This class implementes an authentication mechanism for
* the processing of authentication requests utilizing a
* username/password token.
*
*/
public class PwdAuthenticate implements AuthMechanism, Serializable
{
private SvcConfig m_svcConfig;
private AuthMechConfig m_mechConfig;
/*
* Password Token Class.
*/
private class PwToken
{
private String m_username = "";
private String m_password = "";
/*
* The format of the Pw token is as follows:
*
* Base64.encode(new String("username\r\n" + "password\r\n"));
*/
public PwToken(String encodedToken) throws IOException
{
// Decode the token
String token = Base64Coder.decode(encodedToken);
BufferedReader tokenReader = new BufferedReader(new StringReader(token));
// The second line contains the "username"
m_username = tokenReader.readLine();
// The third line contains the "password"
m_password = tokenReader.readLine();
}
/*
* Returns the username
*/
public String getUsername()
{
return m_username;
}
/*
* Returns the password
*/
public String getPassword()
{
return m_password;
}
}
/*
* Constructor
*/
public PwdAuthenticate() throws Exception
{
// Nothing to do at this time
}
/*
* Initialize the mechanism.
*/
public void init(SvcConfig svcConfig, AuthMechConfig mechConfig) throws Exception
{
m_svcConfig = svcConfig;
m_mechConfig = mechConfig;
}
/*
* invoke() implementation.
*/
public String invoke(AuthReqMsg authReqMsg) throws Exception
{
String identId = null;
try
{
System.err.println("PwdAuthenticate.invoke()");
// Now parse the PW Token
PwToken pwToken = new PwToken(authReqMsg.getAuthMechToken());
// 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, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
env.put(IAContext.IA_REALM_SELECTOR, authReqMsg.getRealm());
DirContext ctx = new InitialDirContext(env);
// Now search for a user with a matching surname.
//
// Set up a search control so that the search is scoped to the sub-tree
SearchControls controls = new SearchControls();
controls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// Obtain the start search context - tbd - this will be removed once the functionality flows into Bandit
String searchContext = m_svcConfig.getSetting(SvcConfig.StartSearchContext);
if (searchContext == null)
{
// A start search context was not configured, start from the root.
searchContext = "";
}
// Perform the search
NamingEnumeration answer = ctx.search(searchContext,
"(cn={0})",
new String[] {pwToken.getUsername()},
controls);
if (!answer.hasMore())
{
System.err.println("PwdAuthenticate.invoke()- No matching identity entities found");
}
// Enumerate through the users returned checking the password
while (answer.hasMore())
{
SearchResult sr = (SearchResult)answer.next();
// 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, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
env2.put(IAContext.IA_REALM_SELECTOR, authReqMsg.getRealm());
env2.put(Context.SECURITY_AUTHENTICATION, "simple");
env2.put(Context.SECURITY_PRINCIPAL, sr.getNameInNamespace());
env2.put(Context.SECURITY_CREDENTIALS, pwToken.getPassword());
if ((new InitialDirContext(env2)) != null)
{
// The password must be valid, set the identity Id.
if (searchContext.equals(""))
{
identId = sr.getName();
}
else
{
identId = sr.getName() + "," + searchContext;
}
break;
}
}
catch (NamingException e)
{
System.err.println("PwdAuthenticate.invoke()- NamingException: " + e.getExplanation());
}
}
// Check if we did not resolve the identity
if (identId == null)
{
System.err.println("PwdAuthenticate.invoke()- Failed to resolve identity for entity " + pwToken.getUsername());
}
}
catch (NamingException e)
{
// Log the error
System.err.println("PwdAuthenticate.invoke()- NamingException on Proxy User: " + e.getExplanation());
}
catch (Exception e)
{
System.err.println("PwdAuthenticate.invoke()- Exception: " + e.toString());
}
// Return the authentication result
return identId;
}
/*
* Return the mechanism id.
*/
public String getId()
{
return "PwdAuthenticate";
}
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<settings>
<description>This is the authentication mechanism for the PwdAuthenticate scheme. The PwdAuthenticate scheme authenticates entities using username/password tokens.</description>
<ClassName>com.novell.casa.authtoksvc.PwdAuthenticate</ClassName>
<RelativeClassPath>WEB-INF/classes</RelativeClassPath>
</settings>

View File

@@ -0,0 +1,299 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.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 String m_appFolderPath = null;
private String m_configFolderPath = null;
private boolean m_enabledSvcsOnly;
protected ReconfigureThread m_reconfigureThread = null;
protected int m_reconfigureInterval; // seconds
private Map m_methodsMap;
/*
* Reconfigure Thread Class.
*
* This class implements a runnable thread that reconfigures an Rpc Servlet instance.
*
*/
private class ReconfigureThread implements Runnable
{
private Rpc m_rpc;
private Thread m_thread;
/*
* Constructor.
*/
public ReconfigureThread (Rpc rpc)
{
m_rpc = rpc;
m_thread = new Thread(this);
m_thread.start();
}
/*
* run() implementation.
*/
public void run ()
{
System.err.println("ReconfigureThread.run()- Running");
while (true)
{
// Sleep an ammount equal the reconfigure interval for the Rpc
try
{
m_thread.sleep(m_rpc.m_reconfigureInterval * 1000);
}
catch (InterruptedException e) { /* nothing to do */ }
// Re-configure the Rpc servlet.
try
{
m_rpc.configureServlet();
// Check if it is no longer necessary to re-configure the servlet
if (m_rpc.m_reconfigureInterval == 0)
{
System.err.println("ReconfigureTask.run()- Configuration changed to no longer perform timed re-configuration");
break;
}
}
catch (Exception e)
{
System.err.println("ReconfigureTask.run()- Exception caught during re-configure process, " + e.toString());
}
}
}
/*
* stop() implementation.
*/
public void stop ()
{
m_thread.stop();
}
}
/*
* Constructor.
*/
public Rpc ()
{
super();
}
/*
* configureServlet() implementation.
*/
protected void configureServlet () throws Exception
{
// Read service configuration
SvcConfig svcConfig = new SvcConfig(m_appFolderPath, m_configFolderPath);
// Get the reconfigure interval
try
{
m_reconfigureInterval = Integer.parseInt(svcConfig.getSetting(SvcConfig.ReconfigureInterval));
}
catch (NumberFormatException e)
{
System.err.println("Rpc.configureServlet()- Invalid reconfigure interval value format");
m_reconfigureInterval = Integer.parseInt(SvcConfig.DefaultReconfigureIntervalValue);
}
// Read enabled services configuration
EnabledSvcsConfig enabledSvcsConfig = new EnabledSvcsConfig(m_configFolderPath, m_enabledSvcsOnly);
// Create a map to keep track of the Rpc methods
Map methodsMap = new HashMap();
// Instantiate the Rpc Methods
RpcMethod getAuthPolicy = new GetAuthPolicy();
getAuthPolicy.init(svcConfig, enabledSvcsConfig);
methodsMap.put(getAuthPolicy.getId(), getAuthPolicy);
RpcMethod authenticate = new Authenticate();
authenticate.init(svcConfig, enabledSvcsConfig);
methodsMap.put(authenticate.getId(), authenticate);
RpcMethod getAuthToken = new GetAuthToken();
getAuthToken.init(svcConfig, enabledSvcsConfig);
methodsMap.put(getAuthToken.getId(), getAuthToken);
// Set the map as the methods map used by the servlet
m_methodsMap = methodsMap;
}
/*
* init() implementation.
*/
public void init (ServletConfig config) throws ServletException
{
super.init(config);
System.err.println("Rpc.init()");
try
{
// Get the path to our configuration folder
//
// First check if it has been specified via a system property
ServletContext context = config.getServletContext();
m_appFolderPath = context.getRealPath(File.separator);
m_configFolderPath = System.getProperty("com.novell.casa.authtoksvc.config");
if (m_configFolderPath == null)
{
// The path to the svc config folder was not specified via a system
// property, assume that it's location is off the WEB-INF folder for
// our web application.
m_configFolderPath = m_appFolderPath + "WEB-INF/conf";
}
// Check if we support services that are not explicitedly enabled
String enabledSvcsOnly = System.getProperty("com.novell.casa.authtoksvc.enabled_svcs_only");
if (enabledSvcsOnly != null
&& enabledSvcsOnly.compareToIgnoreCase("true") == 0)
{
m_enabledSvcsOnly = true;
}
else
{
m_enabledSvcsOnly = false;
}
// Configure ourselves
configureServlet();
// Check if we must start a thread to periodically reconfigure ourselves
if (m_reconfigureInterval != 0)
{
m_reconfigureThread = new ReconfigureThread(this);
}
}
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()");
// Stop our re-configure thread
if (m_reconfigureThread != null)
{
m_reconfigureThread.stop();
}
}
/*
* 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();
}
}

View File

@@ -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 <jluciani@novell.com>
*
***********************************************************************/
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();
}

View File

@@ -0,0 +1,232 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.ByteArrayInputStream;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.client.AxisClient;
import org.apache.axis.configuration.NullProvider;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.axis.message.SOAPBody;
import org.apache.axis.message.MessageElement;
import javax.xml.namespace.QName;
import java.io.*;
/*
* SessionToken class.
*
* This class constructs sessions tokens that clients can present to an ATS
* to prove that an entity has been authenticated to a particular realm.
* The session token consists of a SOAP message secured with WSSecurity
* with the appropriate elements signed and with a timestamp. The body of
* the SOAP message is as follows:
*
* <session_token>
* <realm>realm value</realm>
* <ident_id>identity id value</ident_id>
* </session_token>
*
*/
public class SessionToken
{
private String m_id = null;
private String m_realm = null;
private String m_token;
static final String sessionTokenSoapMsg =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<SOAP-ENV:Envelope" +
" xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\"\n" +
" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
" <SOAP-ENV:Body>" +
" <session_token><realm></realm><ident_id></ident_id></session_token>" +
" </SOAP-ENV:Body>" +
"</SOAP-ENV:Envelope>";
static final private MessageContext axisMsgContext = new MessageContext(new AxisClient(new NullProvider()));
/*
* Constructor
*/
public SessionToken(String id,
String realm,
String lifetime,
SvcConfig svcConfig) throws Exception
{
// Save copies of the input parameters
m_id = id;
m_realm = realm;
// Create SessionTokenMessage
Message sessionTokenMessage = getMessage(realm,
id,
Integer.valueOf(lifetime).intValue(),
svcConfig);
// Now save the message as a string
OutputStream outStream = new ByteArrayOutputStream();
sessionTokenMessage.writeTo(outStream);
m_token = outStream.toString();
outStream.close();
}
/*
* Constructor given a session token string. The constructor
* validates the token as part of its processing.
*/
public SessionToken(String token) throws Exception
{
// Decode the token string
m_token = Base64Coder.decode(token);
// Now instantiate a SOAP message with the string
InputStream inStream = new ByteArrayInputStream(m_token.getBytes());
Message message = new Message(inStream);
// Get access to the SOAP Envelope
SOAPEnvelope envelope = message.getSOAPEnvelope();
// Verify the message
if (WSSecurity.verifyMessage(envelope))
{
// Message verification succeded, now obtain the realm and identity id
// from the message body.
SOAPBody body = (SOAPBody) envelope.getBody();
QName sessionTokenElementName = new QName("session_token");
MessageElement sessionTokenElement = body.getChildElement(sessionTokenElementName);
QName realmElementName = new QName("realm");
MessageElement realmElement = sessionTokenElement.getChildElement(realmElementName);
if (realmElement != null)
{
m_realm = realmElement.getChildNodes().item(0).getNodeValue();
}
QName identIdElementName = new QName("ident_id");
MessageElement identIdElement = sessionTokenElement.getChildElement(identIdElementName);
if (identIdElement != null)
{
m_id = identIdElement.getChildNodes().item(0).getNodeValue();
}
if (m_realm == null || m_id == null)
{
System.out.println("SessionToken()- Required data missing from session token");
throw new Exception("Error: Required data missing from session Token");
}
}
else
{
// Message verification failed
System.err.println("SessionToken()- Invalid Session Token");
throw new Exception("Invalid Session Token");
}
}
/**
* Get SessionToken SOAP Message
*
* @param realm String containing the identity token that should be part of the message
* @param identityId String containing the identity token type
* @param lifetime Lifetime that should be specified in the message timestamp (seconds)
* @param svcConfig Service Config object
* @return <code>Message<code> SessionToken message, null if the method fails.
*/
private Message getMessage(String realm,
String identityId,
int lifetime,
SvcConfig svcConfig)
{
Message secureMessage;
try
{
// Build SOAP Message with an identity token in the body
//
// First create a message and obtain its body
InputStream inStream = new ByteArrayInputStream(sessionTokenSoapMsg.getBytes());
Message message = new Message(inStream);
message.setMessageContext(axisMsgContext);
SOAPBody body = (SOAPBody) message.getSOAPBody();
// Get access to the session_token element
QName sessionTokenElementName = new QName("session_token");
MessageElement sessionTokenElement = body.getChildElement(sessionTokenElementName);
// Get access to the realm element and set its value
QName realmElementName = new QName("realm");
MessageElement realmElement = sessionTokenElement.getChildElement(realmElementName);
realmElement.addTextNode(realm);
// Get access to the ident_id element and set its value
QName identIdElementName = new QName("ident_id");
MessageElement identIdElement = sessionTokenElement.getChildElement(identIdElementName);
identIdElement.addTextNode(identityId);
// Now we need to secure the SOAP message that we created, we are doing to
// do so by adding a timestamp and signing the timestamp as well as the body.
// To do this we are going to leverage WS-Security.
secureMessage = WSSecurity.secureSOAPEnvelope(message.getSOAPEnvelope(),
lifetime,
svcConfig,
false);
}
catch (Exception e)
{
System.out.println("SessionToken.getMessage() - Exception caught building message, error: " + e.getMessage());
secureMessage = null;
}
return secureMessage;
}
/*
* Returns a string containing the session token.
*/
public String toString()
{
return Base64Coder.encode(m_token);
}
/*
* Method to get the Identity Id
*/
public String getIdentId() throws Exception
{
return m_id;
}
/*
* Method to get the Identity Repository Reference (Realm).
*/
public String getRealm() throws Exception
{
return m_realm;
}
}

View File

@@ -0,0 +1,429 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import org.apache.xerces.parsers.DOMParser;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import java.io.*;
import java.io.File;
import java.io.FileInputStream;
/**
*
* Class for the creation and editing of settings files.
*
**/
public class SettingsFileUtil
{
/**
* Gets document for the specified settings file.
*
* @param filePath Path to the settings file.
* @return Document representation of the settings file.
*/
private static Document getSettingsFileDoc(String filePath)
{
Document doc = null;
try
{
// Get an input stream to read from settings file
File f = new File(filePath);
FileInputStream inStream = new FileInputStream(f);
InputSource source = new InputSource(inStream);
DOMParser parser = new DOMParser();
parser.parse(source);
doc = parser.getDocument();
inStream.close();
}
catch (FileNotFoundException e)
{
System.err.println("Settings file " + filePath + " not found");
doc = null;
}
catch (SecurityException e)
{
System.err.println("SecurityException accessing " + filePath);
doc = null;
}
catch (IOException e)
{
System.err.println("IOException accessing " + filePath + " Exception=" + e.toString());
doc = null;
}
catch (SAXException e)
{
System.err.println("Settings file " + filePath + " format error");
doc = null;
}
return doc;
}
/**
* Gets a starting settings document
*
* @param settings String with starting settings document.
* @return Starting settings document.
*/
private static Document getSettingsDoc(String settings)
{
Document doc = null;
try
{
StringReader 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());
}
return doc;
}
/**
* List all of the settings present in the specified file.
*
* @param filePath` Path to the settings file.
* @return True if the operation is successfully performed.
*/
public static boolean performListOperation(String filePath)
{
boolean opPerformed = false;
// List the settings present in the file
Document doc = getSettingsFileDoc(filePath);
if (doc != null)
{
// Go through the elements of the document
Element root = doc.getDocumentElement();
Node child;
Node next = root.getFirstChild();
while ((child = next) != null)
{
next = child.getNextSibling();
if (child.getNodeType() == Node.ELEMENT_NODE)
{
System.out.println(child.getLocalName() + "=" + child.getTextContent());
}
}
opPerformed = true;
}
return opPerformed;
}
/**
* Create settings file.
*
* @param filePath Path to the settings file.
* @param settings String containing an settings document.
* @return True if the operation is successfully performed.
*/
public static boolean performCreateOperation(String filePath,
String settings)
{
boolean opPerformed = false;
// create a settings file
Document doc = getSettingsDoc(settings);
if (doc != null)
{
try
{
File f = new File(filePath);
boolean createStatus = f.createNewFile();
if (createStatus == true)
{
FileOutputStream out = new FileOutputStream(f);
OutputFormat format = new OutputFormat(doc);
XMLSerializer serializer = new XMLSerializer(out, format);
serializer.serialize(doc.getDocumentElement());
out.close();
opPerformed = true;
}
else
{
System.out.println("File " + filePath + " already exists");
}
}
catch (IOException e)
{
System.out.println("Error creating file " + filePath + ", exception: " + e.toString());
}
catch (SecurityException e)
{
System.out.println("SecurityException creating " + filePath);
}
}
return opPerformed;
}
/**
* Gets value of the specified setting in the specified settings file.
*
* @param filePath Path to the settings file.
* @param setting Name of the setting being queried.
* @return True if the operation is successfully performed.
*/
public static boolean performGetOperation(String filePath,
String setting,
IVerifySetting settingVerifier)
{
boolean opPerformed = false;
// Validate the setting name specified
if (settingVerifier.validSetting(setting))
{
// Get settings present in the file
Document doc = getSettingsFileDoc(filePath);
if (doc != null)
{
// Go through the elements of the document until
// we find the one specified.
Element root = doc.getDocumentElement();
Node child;
Node next = root.getFirstChild();
boolean settingFound = false;
while ((child = next) != null
&& settingFound == false)
{
next = child.getNextSibling();
if (child.getNodeType() == Node.ELEMENT_NODE
&& child.getLocalName().compareToIgnoreCase(setting) == 0)
{
System.out.println(child.getLocalName() + "=" + child.getTextContent());
settingFound = true;
}
}
if (settingFound == false)
System.out.println("Not set");
opPerformed = true;
}
}
return opPerformed;
}
/**
* Sets the specified setting in the specified settings file.
*
* @param filePath Path to the settings file.
* @param setting`` Name of the setting to be set.
* @param value Value to be assigned to the setting.
* @return True if the operation is successfully performed.
*/
public static boolean performSetOperation(String filePath,
String setting,
String value,
IVerifySetting settingVerifier)
{
boolean opPerformed = false;
// Validate specified setting name and value
String formalSetting;
if ((formalSetting = settingVerifier.validSettingNameAndValue(setting, value)) != null)
{
// Get settings present in the file
Document doc = getSettingsFileDoc(filePath);
if (doc != null)
{
// Go through the elements of the document until
// we find the one specified.
Element root = doc.getDocumentElement();
Node child;
Node next = (Node) root.getFirstChild();
boolean settingFound = false;
while ((child = next) != null
&& settingFound == false)
{
next = child.getNextSibling();
if (child.getNodeType() == Node.ELEMENT_NODE
&& child.getLocalName().compareToIgnoreCase(setting) == 0)
{
// Change the value of the setting
child.setTextContent(value);
settingFound = true;
}
}
if (settingFound == false)
{
try
{
Element element = doc.createElement(formalSetting);
element.setTextContent(value);
root.appendChild(element);
}
catch (Exception e)
{
System.err.println("Exception caught " + e.toString());
}
}
// Update the file after removing the text nodes
try
{
// Remove text nodes
next = (Node) root.getFirstChild();
while ((child = next) != null)
{
next = child.getNextSibling();
if (child.getNodeType() == Node.TEXT_NODE)
{
// Remove the node
root.removeChild(child);
}
}
// Update file
File f = new File(filePath);
FileOutputStream out = new FileOutputStream(f);
OutputFormat format = new OutputFormat(doc);
XMLSerializer serializer = new XMLSerializer(out, format);
serializer.serialize(doc.getDocumentElement());
out.close();
opPerformed = true;
}
catch (IOException e)
{
System.out.println("Error writing to file " + filePath + ", exception: " + e.toString());
}
catch (SecurityException e)
{
System.out.println("SecurityException writting to file " + filePath);
}
}
}
return opPerformed;
}
/**
* Remove specified setting from the specified settings file.
*
* @param filePath Path to the settings file.
* @param setting Name of the setting to be removed.
* @return True if the operation is successfully performed.
*/
public static boolean performRemoveOperation(String filePath,
String setting,
IVerifySetting settingVerifier)
{
boolean opPerformed = false;
// Validate specified setting name
if (settingVerifier.validSetting(setting))
{
// Get settings present in the file
Document doc = getSettingsFileDoc(filePath);
if (doc != null)
{
// Go through the elements of the document until
// we find the one specified.
Element root = doc.getDocumentElement();
Node child;
Node next = (Node) root.getFirstChild();
boolean settingFound = false;
while ((child = next) != null
&& settingFound == false)
{
next = child.getNextSibling();
if (child.getNodeType() == Node.ELEMENT_NODE
&& child.getLocalName().compareToIgnoreCase(setting) == 0)
{
// Remove the element from the document
root.removeChild(child);
settingFound = true;
// Update the file after removing the text nodes
try
{
// Remove text nodes
next = (Node) root.getFirstChild();
while ((child = next) != null)
{
next = child.getNextSibling();
if (child.getNodeType() == Node.TEXT_NODE)
{
// Remove the node
root.removeChild(child);
}
}
// Update file
File f = new File(filePath);
FileOutputStream out = new FileOutputStream(f);
OutputFormat format = new OutputFormat(doc);
XMLSerializer serializer = new XMLSerializer(out, format);
serializer.serialize(doc.getDocumentElement());
out.close();
opPerformed = true;
}
catch (IOException e)
{
System.out.println("Error writing to file " + filePath + ", exception: " + e.toString());
}
catch (SecurityException e)
{
System.out.println("SecurityException writting to file " + filePath);
}
}
}
if (settingFound == false)
{
// Succeed anyway
opPerformed = true;
}
}
}
return opPerformed;
}
}

View File

@@ -0,0 +1,319 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.*;
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";
public final static String AppRootPath = "AppRootPath";
public final static String ReconfigureInterval = "ReconfigureInterval";
public final static String SigningKeyAliasName = "SigningKeyAliasName";
public final static String SigningKeyPassword = "SigningKeyPassword";
// Default configuration values
public final static String DefaultSessionTokenLifetimeValue = "43200"; // Seconds
public final static String DefaultLifetimeShorterValue = "5"; // Seconds
public final static String DefaultReconfigureIntervalValue = "60"; // Seconds
public final static String DefaultSigningKeyAliasNameValue = "signingKey";
public final static String DefaultSigningKeyPasswordValue = "secret";
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_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.
*/
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 appRootPath, 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 application and config folder path settings to our map
m_svcSettingsMap.put(AppRootPath, appRootPath);
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 + File.separator + m_svcSettingsFileName + " Exception=" + e.toString());
}
catch (FileNotFoundException e)
{
System.err.println("SvcConfig()- File " + svcConfigPath + File.separator + m_svcSettingsFileName + " not found");
}
catch (IOException e)
{
System.err.println("SvcConfig()- IOException caught while trying to read " + svcConfigPath + File.separator + 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 = 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, DefaultSessionTokenLifetimeValue);
}
else if (settingName.equals(LifetimeShorter) == true)
{
value = 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, DefaultLifetimeShorterValue);
}
else if (settingName.equals(ReconfigureInterval) == true)
{
value = DefaultReconfigureIntervalValue;
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(ReconfigureInterval, DefaultReconfigureIntervalValue);
}
else if (settingName.equals(SigningKeyAliasName) == true)
{
value = DefaultSigningKeyAliasNameValue;
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(SigningKeyAliasName, DefaultSigningKeyAliasNameValue);
}
else if (settingName.equals(SigningKeyPassword) == true)
{
value = DefaultSigningKeyPasswordValue;
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(SigningKeyPassword, DefaultSigningKeyPasswordValue);
}
else if (settingName.equals(IdentityAbstractionConfigFile) == true)
{
System.err.println("SvcConfig.getSetting()- Mandatory setting " + IdentityAbstractionConfigFile + " 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;
}
}

View File

@@ -0,0 +1,374 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.File;
/**
*
* Class for the creation and editing of svc.settings files.
*
**/
public class SvcSettingsEditor implements IVerifySetting
{
private static final String usage =
"usage: SvcSettingsEditor -op [settingName [settingValue]] -file settingsFilePath\n\n" +
" where:\n" +
" -op - Corresponds to one of the following operations:\n" +
" -create - Create new svc settings file\n" +
" -list - List settings\n" +
" -get - Get settings, must be followed by settingName parameter\n" +
" -set - Set settings, must be followed by settingName and settingValue parameters\n" +
" -remove - Remove settings\n" +
" -file - Path the the svc settings file\n" +
" settingName - Name of the setting being retrieved or set\n" +
" settingValue - Value of the setting being set\n\n" +
" The following settings are valid:\n" +
" SessionTokenLifetime\n" +
" LifetimeShorter\n" +
" IAConfigFile\n" +
" ReconfigureInterval\n" +
" SigningKeyAliasName\n" +
" SigningKeyPassword\n";
private static final String settings =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<settings>\n" +
" <IAConfigFile>/etc/CASA/authtoken/svc/iaRealms.xml</IAConfigFile>\n" +
"</settings>\n";
/**
* Checks if the specified setting is valid.
*
* @param setting The name of the setting being checked.
* @return True if the specified setting is valid.
*/
public boolean validSetting(String setting)
{
boolean result = false;
if (setting.compareToIgnoreCase(SvcConfig.SessionTokenLifetime) == 0)
result = true;
else if (setting.compareToIgnoreCase(SvcConfig.LifetimeShorter) == 0)
result = true;
else if (setting.compareToIgnoreCase(SvcConfig.IdentityAbstractionConfigFile) == 0)
result = true;
else if (setting.compareToIgnoreCase(SvcConfig.ReconfigureInterval) == 0)
result = true;
else if (setting.compareToIgnoreCase(SvcConfig.SigningKeyAliasName) == 0)
result = true;
else if (setting.compareToIgnoreCase(SvcConfig.SigningKeyPassword) == 0)
result = true;
else
System.out.println("Invalid setting specified");
return result;
}
/**
* Checks if the specified setting is valid in conjunction
* with the specified value.
*
* @param setting The name of the setting being checked.
* @param value The value of the specified setting.
* @return The formal name of the setting if found to be valid.
*/
public String validSettingNameAndValue(String setting,
String value)
{
String validSetting = null;
if (setting.compareToIgnoreCase(SvcConfig.SessionTokenLifetime) == 0)
{
// Verify that we are dealing with a numeric value
try
{
Integer.valueOf(value);
// Good
validSetting = SvcConfig.SessionTokenLifetime;
}
catch (NumberFormatException e)
{
System.out.println("Invalid setting value specified");
}
}
else if (setting.compareToIgnoreCase(SvcConfig.LifetimeShorter) == 0)
{
// Verify that we are dealing with a numeric value
try
{
Integer.valueOf(value);
// Good
validSetting = SvcConfig.LifetimeShorter;
}
catch (NumberFormatException e)
{
System.out.println("Invalid setting value specified");
}
}
else if (setting.compareToIgnoreCase(SvcConfig.IdentityAbstractionConfigFile) == 0)
{
// Output a warning if the specified file does not exist
try
{
File f = new File(value);
if (f.exists() == false)
{
System.out.println("Warning: File " + value + " does not exist");
}
}
catch (SecurityException e)
{
System.out.println("Warning: Not able to access file " + value);
}
// Always succeed
validSetting = SvcConfig.IdentityAbstractionConfigFile;
}
else if (setting.compareToIgnoreCase(SvcConfig.ReconfigureInterval) == 0)
{
// Verify that we are dealing with a numeric value
try
{
Integer.valueOf(value);
// Good
validSetting = SvcConfig.ReconfigureInterval;
}
catch (NumberFormatException e)
{
System.out.println("Invalid setting value specified");
}
}
else if (setting.compareToIgnoreCase(SvcConfig.SigningKeyAliasName) == 0)
{
validSetting = SvcConfig.SigningKeyAliasName;
}
else if (setting.compareToIgnoreCase(SvcConfig.SigningKeyPassword) == 0)
{
validSetting = SvcConfig.SigningKeyPassword;
}
else
System.out.println("Invalid setting specified");
return validSetting;
}
/**
* Applications Entry Point
*
* @param args
*/
public static void main(String[] args)
{
String op = null;
boolean opPerformed = false;
boolean argumentsError = false;
String filePath = null;
String setting = null;
String value = null;
SvcSettingsEditor editor = new SvcSettingsEditor();
// Process the command line arguments
for (int i = 0; i < args.length; i++)
{
// Proceed based on the command
if (args[i].compareToIgnoreCase("-file") == 0)
{
// The next argument should contain the filepath
if (args.length > (i + 1))
{
filePath = args[i + 1];
i++;
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-list") == 0)
{
// List operation requested
if (op == null)
{
op = "list";
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-create") == 0)
{
// List operation requested
if (op == null)
{
op = "create";
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-get") == 0)
{
// Get setting operation requested
if (op == null)
{
op = "get";
// The next argument should contain the setting name
if (args.length > (i + 1))
{
setting = args[i + 1];
i++;
}
else
{
argumentsError = true;
break;
}
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-set") == 0)
{
// Set setting operation requested
if (op == null)
{
op = "set";
// The next two arguments should contain the setting name
// and the setting value.
if (args.length > (i + 2))
{
setting = args[i + 1];
value = args[i + 2];
i += 2;
}
else
{
argumentsError = true;
break;
}
}
else
{
argumentsError = true;
break;
}
}
else if (args[i].compareToIgnoreCase("-remove") == 0)
{
// Remove setting operation requested
if (op == null)
{
op = "remove";
// The next argument should contain the setting name
if (args.length > (i + 1))
{
setting = args[i + 1];
i++;
}
else
{
argumentsError = true;
break;
}
}
else
{
argumentsError = true;
break;
}
}
else
{
argumentsError = true;
}
}
// Proceed based on the specified parameters
if (argumentsError == false)
{
if (filePath != null && op != null)
{
System.out.println("Dealing with settings file: " + filePath);
// Proceed based on the operation requested
if (op.compareTo("list") == 0)
{
opPerformed = SettingsFileUtil.performListOperation(filePath);
}
else if (op.compareTo("create") == 0)
{
opPerformed = SettingsFileUtil.performCreateOperation(filePath, settings);
}
else if (op.compareTo("get") == 0)
{
opPerformed = SettingsFileUtil.performGetOperation(filePath, setting, editor);
}
else if (op.compareTo("set") == 0)
{
opPerformed = SettingsFileUtil.performSetOperation(filePath, setting, value, editor);
}
else if (op.compareTo("remove") == 0)
{
opPerformed = SettingsFileUtil.performRemoveOperation(filePath, setting, editor);
}
else
{
System.err.println("Tool error");
}
}
else
{
argumentsError = true;
}
}
// Display the usage string if we encountered an error with the
// command line arguments.
if (argumentsError)
System.out.print(usage);
// Set the exit code appropriatedly
if (opPerformed)
System.exit(0);
else
System.exit(1);
}
}

View File

@@ -0,0 +1,283 @@
/***********************************************************************
*
* Copyright (C) 2006 Novell, Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail,
* you may find current contact information at www.novell.com.
*
* Author: Juan Carlos Luciani <jluciani@novell.com>
*
***********************************************************************/
package com.novell.casa.authtoksvc;
import java.io.ByteArrayInputStream;
import org.apache.axis.Message;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.ws.security.*;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
import org.apache.ws.security.message.WSSecHeader;
import org.apache.ws.security.message.WSSecSignature;
import org.apache.ws.security.message.WSSecTimestamp;
import org.apache.xml.security.c14n.Canonicalizer;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import javax.xml.soap.MessageFactory;
import java.util.Set;
import java.util.Vector;
/*
* WSSecurity Class.
*
* This class provides static methods for securing and verifying SOAP messages. SOAP messages
* are secured by adding a timestamp and signing the appropriate elements using methods and
* headers defined by WS* specifications.
*
*/
public class WSSecurity
{
static final private WSSecurityEngine secEngine = new WSSecurityEngine();
static final private Crypto crypto = CryptoFactory.getInstance();
/**
* Creates a SOAP message from a document.
*
*/
private static Message toSOAPMessage(Document doc) throws Exception
{
Canonicalizer c14n = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS);
byte[] canonicalMessage = c14n.canonicalizeSubtree(doc);
ByteArrayInputStream in = new ByteArrayInputStream(canonicalMessage);
MessageFactory factory = MessageFactory.newInstance();
return (org.apache.axis.Message) factory.createMessage(null, in);
}
/***
* Returns the first element that containes an Id with value
* <code>uri</code> and <code>namespace</code>.
* <p/>
*
* Copyright Note: The code for this function was copied from file
* WSSecurityUtil.java from package org.apache.ws.security.util.
* The Copyright notice on this file is as follows:
*
* Copyright 2003-2006 The Apache Software Foundation, or their licensors, as
* appropriate.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @param startNode Where to start the search
* @param value Value of the Id attribute
* @param namespace Namespace URI of the Id
* @return The found element or <code>null</code>
*/
private static Element findElementById(Node startNode,
String value,
String namespace)
{
// Just return null if startNode is set to null
if (startNode == null)
{
return null;
}
Node startParent = startNode.getParentNode();
Node processedNode;
while (startNode != null)
{
// start node processing at this point
if (startNode.getNodeType() == Node.ELEMENT_NODE)
{
Element se = (Element) startNode;
if (se.hasAttributeNS(namespace, "Id")
&& value.equals(se.getAttributeNS(namespace, "Id")))
{
return se;
}
}
processedNode = startNode;
startNode = startNode.getFirstChild();
// no child, this node is done.
if (startNode == null)
{
// close node processing, get sibling
startNode = processedNode.getNextSibling();
}
// no more siblings, get parent, all children
// of parent are processed.
while (startNode == null)
{
processedNode = processedNode.getParentNode();
if (processedNode == startParent)
{
return null;
}
// close parent node processing (processed node now)
startNode = processedNode.getNextSibling();
}
}
return null;
}
/**
* Verifies SOAP envelope timestamp and signatures.
*
* @param envelope SOAP envelope with timestamp
* @return <code>boolean</code> True if verification succeeds
* @throws Exception on error
*/
public static boolean verifyMessage(SOAPEnvelope envelope) throws Exception
{
boolean msgVerificationStatus = false;
try
{
boolean timeStampProcessed = false;
boolean signatureProcessed = false;
Vector<WSSecurityEngineResult> results;
Document signedDoc = envelope.getAsDocument();
results = secEngine.processSecurityHeader(signedDoc, null, null, crypto);
if (results != null)
{
for (WSSecurityEngineResult result : results)
{
if (result.getAction() == WSConstants.TS)
{
timeStampProcessed = true;
}
else if (result.getAction() == WSConstants.SIGN)
{
// A signature was processed, verify that the signature was over the timestamp
// and the body.
boolean timeStampSigned = false;
boolean bodySigned = false;
Set signedElements = result.getSignedElements();
for (Object signedElement : signedElements)
{
String elementId = (String) signedElement;
Element element = findElementById(signedDoc.getDocumentElement(), elementId, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
if (element != null)
{
if ("wsu:Timestamp".equalsIgnoreCase(element.getNodeName()))
{
timeStampSigned = true;
}
else if ("SOAP-ENV:Body".equalsIgnoreCase(element.getNodeName()))
{
bodySigned = true;
}
}
}
if (timeStampSigned && bodySigned)
{
signatureProcessed = true;
}
}
}
}
if (timeStampProcessed && signatureProcessed)
{
System.out.println("WSSecurity.verifyMessage() - Validation succeded");
msgVerificationStatus = true;
}
else
{
System.out.println("WSSecurity.verifyMessage() - validation failed");
}
}
catch (WSSecurityException e)
{
System.out.println("WSSecurity.verifyMessage() - Verification failed with error:" + e.getMessage() + " code = " + e.getErrorCode());
}
return msgVerificationStatus;
}
/**
* Add timestamp and sign SOAP message in compliance with WS-Security.
*
* @param envelope String containing a SOAP envelope
* @param timeToLive Value to set the timestamp timeToLive parameter in seconds
* @param svcConfig Service Config object
* @param includeCert True if the message should include the Public Certificate
* @return <code>Message</code> Signed and timestamped SOAP message
* @throws Exception on error
*/
public static Message secureSOAPEnvelope(SOAPEnvelope envelope,
int timeToLive,
SvcConfig svcConfig,
boolean includeCert) throws Exception
{
WSSecSignature signer = new WSSecSignature();
signer.setUserInfo(svcConfig.getSetting(SvcConfig.SigningKeyAliasName),
svcConfig.getSetting(SvcConfig.SigningKeyPassword));
if (includeCert)
{
signer.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER); // Include X509 Cert in message
}
else
{
signer.setKeyIdentifierType(WSConstants.ISSUER_SERIAL); // Use X509 Cert Serial Number and issuer info
}
Document doc = envelope.getAsDocument();
WSSecHeader secHeader = new WSSecHeader();
secHeader.insertSecurityHeader(doc);
WSSecTimestamp timeStamper = new WSSecTimestamp();
timeStamper.setTimeToLive(timeToLive);
timeStamper.build(doc, secHeader);
Vector<WSEncryptionPart> parts = new Vector<WSEncryptionPart>();
String soapNamespace = doc.getDocumentElement().getNamespaceURI();
WSEncryptionPart bodyPart = new WSEncryptionPart("Body", soapNamespace, "");
parts.add(bodyPart);
WSEncryptionPart timeStampPart = new WSEncryptionPart(timeStamper.getId());
parts.add(timeStampPart);
signer.setParts(parts);
Document signedDoc = signer.build(doc, crypto, secHeader);
// Convert the signed document into a SOAP message and return it.
return toSOAPMessage(signedDoc);
}
}