Addressed bugs 225066 and 190821.

Also fixed "ReconfigureInterval=0" issue and added the ability
to search using multiple search roots configured on a per-realm
basis in the iaRealms file.
This commit is contained in:
Juan Carlos Luciani 2007-01-17 12:14:29 +00:00
parent a2819af8fd
commit f8decf4b84
16 changed files with 376 additions and 78 deletions

View File

@ -79,6 +79,7 @@ JAVAFILES = src/com/novell/casa/authtoksvc/ProtoDefs.java \
src/com/novell/casa/authtoksvc/AuthPolicyEditor.java \
src/com/novell/casa/authtoksvc/AuthTokenSettingsEditor.java \
src/com/novell/casa/authtoksvc/IdenTokenSettingsEditor.java \
src/com/novell/casa/authtoksvc/RealmsInfo.java \
src/com/novell/casa/authtoksvc/SvcSettingsEditor.java
BUILDDIR = build
@ -119,7 +120,7 @@ AXIS_LIBS = $(AXIS_JARS_DIR)/axis.jar:$(AXIS_JARS_DIR)/saaj.jar:$(AXIS_JARS_DIR)
#AXIS_LIBS = $(AXIS_JARS_DIR)/wss4j-1.5.0.jar
LIBS = /usr/share/java/servletapi5.jar:/usr/share/java/xerces-j2.jar
CLASSPATH = $(AXIS_LIBS):$(IDENT_ABSTRACTION_DIR)/identity-abstraction.jar:$(IDENT_ABSTRACTION_DIR)/bandit-util.jar:$(LIBS)
CLASSPATH = $(AXIS_LIBS):$(IDENT_ABSTRACTION_DIR)/identity-abstraction.jar:$(IDENT_ABSTRACTION_DIR)/bandit-util.jar:$(IDENT_ABSTRACTION_DIR)/castor-1.0.4.jar:$(LIBS)
CUR_DIR := $(shell pwd)

View File

@ -105,7 +105,7 @@ The following is an example svc.settings file:
Note the following about the sample svc.settings file:
- The settngs that you can specify in the svc.settings file are: SessionLifetime,
LifetimeShorter, IAConfigFile, and startSearchContext.
LifetimeShorter, and IAConfigFile.
- The SessionTokenLifetime setting specifies the number of seconds for which a
session token is good for after being issued. The default value for this setting

View File

@ -10,7 +10,6 @@ This file contains a list of the items still outstanding for AuthTokenSvc.
OUTSTANDING ITEMS
- CasaIdentityToken needs to obtain the identity source url from the identity abstraction layer.
- Switch Client/Server communication to use SOAP.(This is under evaluation).
- Add code to verify that client/server communications occur over HTTPS.
- Add logging.

View File

@ -80,6 +80,7 @@ public final class AuthToken
*
* @param identityId Id of the authenticated identity.
* @param realm Realm where the identity id is valid.
* @param realmUrl Realm Url.
* @param targetService Name of the targeted service.
* @param targetHost Host where the targeted service resides.
* @param svcConfig Service configuration object.
@ -88,6 +89,7 @@ public final class AuthToken
*/
public AuthToken(String identityId,
String realm,
String realmUrl,
String targetService,
String targetHost,
SvcConfig svcConfig,
@ -108,6 +110,7 @@ public final class AuthToken
CasaIdentityToken identityToken = new CasaIdentityToken(enabledSvcsConfig.getIdenTokenConfig(targetHost, targetService));
identityToken.initialize(identityId,
realm,
realmUrl,
targetService,
targetHost,
svcConfig);

View File

@ -684,6 +684,7 @@ public final class CasaIdentityToken implements IdentityToken
*
* @param identityId Identity identifier.
* @param sourceName Name of the realm where the identityId is valid.
* @param sourceUrl URL to the realm (identity data source).
* @param targetService Name of service being targeted.
* @param targetHost Host where the targeted service resides.
* @param svcConfig Service configuration object.
@ -691,6 +692,7 @@ public final class CasaIdentityToken implements IdentityToken
*/
public final void initialize (String identityId,
String sourceName,
String sourceUrl,
String targetService,
String targetHost,
SvcConfig svcConfig) throws Exception
@ -698,7 +700,7 @@ public final class CasaIdentityToken implements IdentityToken
// Save input parameters
m_identityId = identityId;
m_sourceName = sourceName;
m_sourceUrl = "ldap://myldaphost.novell.com:389"; // tbd - Obtain from Identity Abstraction layer
m_sourceUrl = sourceUrl;
m_service = targetService;
m_host = targetHost;

View File

@ -89,6 +89,7 @@ public final class GetAuthToken implements RpcMethod
// Create the Authentication Token
AuthToken authToken = new AuthToken(sessionToken.getIdentId(),
sessionToken.getRealm(),
m_svcConfig.m_realmsInfo.getUrl(sessionToken.getRealm()),
getAuthTokReqMsg.getServiceName(),
getAuthTokReqMsg.getHostName(),
m_svcConfig,

View File

@ -36,6 +36,7 @@ public interface IdentityToken
*
* @param identityId Identity identifier.
* @param sourceName Name of the realm where the identityId is valid.
* @param sourceUrl URL to the realm (identity data source).
* @param targetService Name of service being targeted.
* @param targetHost Host where the targeted service resides.
* @param svcConfig Service configuration object.
@ -43,6 +44,7 @@ public interface IdentityToken
*/
void initialize(String identityId,
String sourceName,
String sourceUrl,
String targetService,
String targetHost,
SvcConfig svcConfig) throws Exception;

View File

@ -215,17 +215,42 @@ public final class Krb5Authenticate implements AuthMechanism, Serializable
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)
// Obtain the search roots
String[] searchRoots = m_svcConfig.m_realmsInfo.getSearchRoots(authReqMsg.getRealm());
if (searchRoots == null)
{
// A start search context was not configured, start from the root.
searchContext = "";
// No configured search roots
searchRoots = new String[] {""};
}
// Perform the search
NamingEnumeration<SearchResult> answer = ctx.search(searchContext,
"(krbPrincipalName={0})",
// Determine the search string to be utilized based on the type of directory
// associated with the realm.
String searchString;
String realmType = m_svcConfig.m_realmsInfo.getType(authReqMsg.getRealm());
if (realmType != null)
{
if (realmType.compareToIgnoreCase(RealmsInfo.eDirectoryRealm) == 0)
searchString = "(krbPrincipalName={0})";
else if (realmType.compareToIgnoreCase(RealmsInfo.ActiveDirectoryRealm) == 0)
searchString = "(userPrincipalName={0})";
else
{
System.err.println("Krb5Authenticate.invoke()- Unsupported realm type " + realmType);
throw new Exception("Realm configuration error");
}
}
else
{
System.err.println("Krb5Authenticate.invoke()- Failed to obtain realm type for realm " + authReqMsg.getRealm());
throw new Exception("Realm configuration error");
}
// Go through the search roots stopping if the identity is resolved.
for (int i = 0; i < searchRoots.length && identId == null; i++)
{
// Perform search for this root
NamingEnumeration<SearchResult> answer = ctx.search(searchRoots[i],
searchString,
new String[] {krb5Token.getPrincipalName()},
controls);
@ -234,13 +259,13 @@ public final class Krb5Authenticate implements AuthMechanism, Serializable
{
// The search succeeded, set the identity id.
SearchResult sr = answer.next();
if (searchContext.equals(""))
if (searchRoots[i].equals(""))
{
identId = sr.getNameInNamespace();
}
else
{
identId = sr.getName() + "," + searchContext;
identId = sr.getName() + "," + searchRoots[i];
}
}
else
@ -248,6 +273,7 @@ public final class Krb5Authenticate implements AuthMechanism, Serializable
System.err.println("Krb5Authenticate.invoke()- No matching identity entities found");
}
}
}
catch (NamingException e)
{
// Log the error

View File

@ -56,6 +56,7 @@ JAVAFILES = ProtoDefs.java \
IVerifySetting.java \
SettingsFileUtil.java \
SettingsFileSAXHandler.java \
RealmsInfo.java \
SvcSettingsEditor.java
EXTRA_DIST = $(JAVAFILES) \

View File

@ -184,23 +184,44 @@ public final class PwdAuthenticate implements AuthMechanism, Serializable
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)
// Obtain the search roots
String[] searchRoots = m_svcConfig.m_realmsInfo.getSearchRoots(authReqMsg.getRealm());
if (searchRoots == null)
{
// A start search context was not configured, start from the root.
searchContext = "";
// No configured search roots
searchRoots = new String[] {""};
}
// Perform the search
NamingEnumeration<SearchResult> answer = ctx.search(searchContext,
"(cn={0})",
// Determine the search string to be utilized based on the type of directory
// associated with the realm.
String searchString;
String realmType = m_svcConfig.m_realmsInfo.getType(authReqMsg.getRealm());
if (realmType != null)
{
if (realmType.compareToIgnoreCase(RealmsInfo.eDirectoryRealm) == 0)
searchString = "(cn={0})";
else if (realmType.compareToIgnoreCase(RealmsInfo.ActiveDirectoryRealm) == 0)
searchString = "(sAMAccountName={0})";
else
{
System.err.println("PwdAuthenticate.invoke()- Unsupported realm type " + realmType);
throw new Exception("Realm configuration error");
}
}
else
{
System.err.println("PwdAuthenticate.invoke()- Failed to obtain realm type for realm " + authReqMsg.getRealm());
throw new Exception("Realm configuration error");
}
// Go through the search roots stopping if the identity is resolved.
for (int i = 0; i < searchRoots.length && identId == null; i++)
{
// Perform search for this root
NamingEnumeration<SearchResult> answer = ctx.search(searchRoots[i],
searchString,
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())
@ -221,13 +242,13 @@ public final class PwdAuthenticate implements AuthMechanism, Serializable
if ((new InitialDirContext(env2)) != null)
{
// The password must be valid, set the identity Id.
if (searchContext.equals(""))
if (searchRoots[i].equals(""))
{
identId = sr.getName();
}
else
{
identId = sr.getName() + "," + searchContext;
identId = sr.getName() + "," + searchRoots[i];
}
break;
}
@ -237,6 +258,7 @@ public final class PwdAuthenticate implements AuthMechanism, Serializable
System.err.println("PwdAuthenticate.invoke()- NamingException: " + e.getExplanation());
}
}
}
// Check if we did not resolve the identity
if (identId == null)

View File

@ -0,0 +1,211 @@
/***********************************************************************
*
* 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.bandit.util.config.gen.*;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.Attributes;
import org.bandit.ia.IAContext;
import org.bandit.util.config.Realm;
import java.io.FileReader;
import java.util.Hashtable;
import java.util.Map;
import java.util.HashMap;
/**
* RealmsInfo class.
* <p>
* Class for obtaining information about the configured realms.
*/
public class RealmsInfo
{
// Internal constants
private final static String RealmUrl = "Url";
private final static String RealmType = "Type";
/**
* String returned by getType method for Active Directory realms.
*/
public final static String ActiveDirectoryRealm = "AD";
/**
* String returned by getType method for eDirectory realms.
*/
public final static String eDirectoryRealm = "eDir";
/**
* Internal class for holding information associated with a realm
*/
private final class RealmInfo
{
// Map for holding ream key/values
protected Map<String, String> m_keyValueMap = new HashMap<String, String>();
protected String[] m_searchRoots = null;
}
// Map for holding ream information
private final Map<String, RealmInfo> m_realmsMap = new HashMap<String, RealmInfo>();
/**
* Constructor.
*
* @param realmConfigFilePath Path to iaRealms configuration file.
* @throws Exception
*/
RealmsInfo(String realmConfigFilePath) throws Exception
{
// Go through all of the configured realms
FileReader fileReader = new FileReader(realmConfigFilePath);
RealmsType realmsType = Realms.unmarshal(fileReader);
for (int i = 0; i < realmsType.getRealmsTypeItemCount(); i++)
{
RealmsTypeItem realmsTypeItem = realmsType.getRealmsTypeItem(i);
org.bandit.util.config.gen.Realm realm = realmsTypeItem.getRealm();
if (realm.getDesc().compareToIgnoreCase("Directory") == 0)
{
// We are dealing with a directory realm
RealmInfo realmInfo = new RealmInfo();
RealmTypeItem[] realmTypeItems = realm.getRealmTypeItem();
for (int ii = 0; ii < realmTypeItems.length; ii++)
{
// Find the configure Proxy User Name for the realm and any configured
// search roots.
if (realmTypeItems[ii].getConnection() == null)
{
Env env[] = realmTypeItems[ii].getEnv();
if (env != null)
{
for (int iii = 0; iii < env.length; iii++)
{
if (env[iii].getProp().compareToIgnoreCase("java.naming.security.principal") == 0)
{
// We found the proxy user, now use it to determine whether or not
// we are dealing with an Active Directory Server.
//
// Open a directory context and use it to read the "sAMAccountName"
// users attribute which theoretically should only be valid on an AD
// server.
Hashtable env2 = new Hashtable();
env2.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory");
env2.put(Realm.REALM_CONFIG_LOCATION, realmConfigFilePath);
env2.put(Realm.REALM_SELECTOR, realm.getId());
DirContext ctx = new InitialDirContext(env2);
String[] attributesNeeded = new String[1];
attributesNeeded[0] = "sAMAccountName";
Attributes attributes = ctx.getAttributes(env[iii].getValue(), attributesNeeded);
NamingEnumeration ae = attributes.getAll();
if (ae != null && ae.hasMore())
{
realmInfo.m_keyValueMap.put(RealmType, ActiveDirectoryRealm);
}
else
{
realmInfo.m_keyValueMap.put(RealmType, eDirectoryRealm);
}
}
else if (env[iii].getProp().compareToIgnoreCase("com.novell.casa.authtoksvc.searchroot") == 0)
{
// We are dealing with a search root, keep track of it. Make sure to preserve the order
// in which they are found.
if (realmInfo.m_searchRoots == null)
{
realmInfo.m_searchRoots = new String[1];
realmInfo.m_searchRoots[0] = env[iii].getValue();
}
else
{
String[] newSearchRoots = new String[realmInfo.m_searchRoots.length + 1];
System.arraycopy(realmInfo.m_searchRoots, 0, newSearchRoots, 0, realmInfo.m_searchRoots.length);
newSearchRoots[realmInfo.m_searchRoots.length] = env[iii].getValue();
realmInfo.m_searchRoots = newSearchRoots;
}
}
}
}
}
else
{
LDAPConnector connector = (LDAPConnector) realmTypeItems[ii].getConnection();
realmInfo.m_keyValueMap.put(RealmUrl, connector.getAddress(0));
}
}
m_realmsMap.put(realm.getId(), realmInfo);
}
}
}
/**
* Get Realm Type.
*
* @param realmId Realm id.
* @return Realm type or null if no match found.
*/
String getType(String realmId)
{
RealmInfo realmInfo = m_realmsMap.get(realmId);
if (realmInfo != null)
return realmInfo.m_keyValueMap.get(RealmType);
else
return null;
}
/**
* Get Realm Url.
*
* @param realmId Realm id.
* @return Realm url or null if no match found.
*/
final String getUrl(String realmId)
{
RealmInfo realmInfo = m_realmsMap.get(realmId);
if (realmInfo != null)
return realmInfo.m_keyValueMap.get(RealmUrl);
else
return null;
}
/**
* Get Search Roots.
*
* @param realmId Realm id.
* @return String array with search roots or null if no match found.
*/
final String[] getSearchRoots(String realmId)
{
RealmInfo realmInfo = m_realmsMap.get(realmId);
if (realmInfo != null)
return realmInfo.m_searchRoots;
else
return null;
}
}

View File

@ -24,6 +24,8 @@
package com.novell.casa.authtoksvc;
import org.bandit.ia.IAContext;
import java.util.*;
import java.io.*;
@ -99,6 +101,9 @@ public final class Rpc extends javax.servlet.http.HttpServlet implements javax.s
{
m_rpc.configureServlet();
// Also force IA to re-read its configuration
IAContext.clearRealmCache();
// Check if it is no longer necessary to re-configure the servlet
if (m_rpc.m_reconfigureInterval == 0)
{

View File

@ -49,7 +49,6 @@ public final class SvcConfig
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";
@ -63,6 +62,11 @@ public final class SvcConfig
public final static String DefaultSigningKeyAliasNameValue = "signingKey";
public final static String DefaultSigningKeyPasswordValue = "secret";
/**
* RealmsInfo object for public use.
*/
public RealmsInfo m_realmsInfo = null;
// Minimum configuration values
private final static int MinimumTokenLifetimeValue = 360; // Seconds
private final static int MinimumLifetimeShorterValue = 5; // Seconds
@ -171,7 +175,8 @@ public final class SvcConfig
try
{
reconfigureInterval = Integer.valueOf(getSetting(ReconfigureInterval)).intValue();
if (reconfigureInterval < MinimumReconfigureIntervalValue)
if (reconfigureInterval != 0
&& reconfigureInterval < MinimumReconfigureIntervalValue)
{
System.err.println("SvcConfig()- Configured reconfigure interval too small, defaulting to "
+ Integer.toString(MinimumReconfigureIntervalValue) + " seconds");
@ -188,6 +193,9 @@ public final class SvcConfig
// Update the map with the new value for the setting
m_svcSettingsMap.put(ReconfigureInterval, Integer.toString(MinimumReconfigureIntervalValue));
}
// Lets create a RealmsInfo object for public use
m_realmsInfo = new RealmsInfo(getSetting(IdentityAbstractionConfigFile));
}
catch (SAXException e)
{

View File

@ -10,13 +10,9 @@
<bci:env prop="java.naming.security.authentication" value="simple"/>
<bci:env prop="java.naming.security.principal" value="PROXY_USER_NAME"/>
<bci:env prop="java.naming.security.credentials" value="PROXY_USER_PW"/>
<bci:env prop="java.naming.referral" value="follow"/>>
<bci:connection xsi:type="bci:LDAPConnector">
<bci:address>ldaps://LDAP_HOST_NAME:LDAP_LISTEN_PORT</bci:address>
</bci:connection>
</bci:realm>
<bci:realm desc="Realm Join Definition" id="E263CCC1-8F9D-4551-B786-068AA84E8564">
<bci:connection xsi:type="bci:JoinConnector">
<bci:realmID>REALM</bci:realmID>
</bci:connection>
</bci:realm>
</bci:realms>

View File

@ -1,3 +1,22 @@
-------------------------------------------------------------------
Wed Jan 17 16:52:46 MST 2007 - jluciani@novell.com
- Fixed BUG225066 (Uninstall doesn't cleanup).
- Addressed BUG190821 (CASA-AD - Display name is being used
instead of the account name).
- Added the ability to search an identity source using
more than one context (search root).
- Fixed problem that was keeping us from disabling the
auto-reconfigure feature by setting the service
reconfigure interval to 0.
- The upgrade path for the ATS was not cleaning up the
appropriate webapp folder so the new webapp was not
getting re-deployed.
-------------------------------------------------------------------
Fri Jan 12 10:23:06 MST 2007 - jluciani@novell.com

View File

@ -240,11 +240,12 @@ fi
%stop_on_removal casa_atsd
%postun
#Undeploy our webapp
rm -drf %{prefix}/share/java/CASA/authtoken/svc/webapps/CasaAuthTokenSvc
# Always undeploy our webapp to force re-deployment on upgrade cases
rm -drf /srv/www/casaats/webapps/CasaAuthTokenSvc
%restart_on_update casa_atsd
%insserv_cleanup
# Do not do anything else if this is an upgrade
if test "$1" == 1; then
exit 0
@ -337,6 +338,7 @@ userdel casaatsd
%postun -n CASA_auth_token_jaas_support
# Nothing to do in this preun script
%files -n CASA_auth_token_jaas_support
%defattr(-,root,root)
%dir %{prefix}/share/java/CASA