Changes to allow the reading of REALM Proxy User Credentials from miCASA

in order to avoid having those credentials in the clear in the
iaRealms.xml file.
This commit is contained in:
Juan Carlos Luciani 2007-05-09 22:54:35 +00:00
parent 90afeed839
commit 9c139d4a2b
9 changed files with 282 additions and 136 deletions

View File

@ -143,7 +143,7 @@ CLASSES = $(addprefix $(BUILDDIR)/, $(JAVAFILES:%.java=%.class))
XMLSEC_LIBS = $(XMLSEC_JARS_DIR)/xmlsec-1.4.0.jar
LIBS = /usr/share/java/servletapi5.jar:/usr/share/java/xerces-j2.jar:/usr/share/java/log4j.jar
LIBS = /usr/share/java/servletapi5.jar:/usr/share/java/xerces-j2.jar:/usr/share/java/log4j.jar:/usr/lib/miCASA.jar
CLASSPATH = $(XMLSEC_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

@ -716,6 +716,11 @@ public final class CasaIdentityToken implements IdentityToken
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory");
env.put(Realm.REALM_CONFIG_LOCATION, svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
env.put(Realm.REALM_SELECTOR, sourceName);
if (svcConfig.m_realmsInfo.proxyCredentialsInRealmFile(sourceName) == false)
{
env.put(Context.SECURITY_PRINCIPAL, svcConfig.m_realmsInfo.proxyUsernameCredential(sourceName));
env.put(Context.SECURITY_CREDENTIALS, svcConfig.m_realmsInfo.proxyPasswordCredential(sourceName));
}
int retries = 3;
while (retries != 0)

View File

@ -211,6 +211,11 @@ public final class Krb5Authenticate implements AuthMechanism, Serializable
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory");
env.put(Realm.REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
env.put(Realm.REALM_SELECTOR, authReqMsg.getRealm());
if (m_svcConfig.m_realmsInfo.proxyCredentialsInRealmFile(authReqMsg.getRealm()) == false)
{
env.put(Context.SECURITY_PRINCIPAL, m_svcConfig.m_realmsInfo.proxyUsernameCredential(authReqMsg.getRealm()));
env.put(Context.SECURITY_CREDENTIALS, m_svcConfig.m_realmsInfo.proxyPasswordCredential(authReqMsg.getRealm()));
}
int retries = 3;
while (retries != 0)

View File

@ -186,6 +186,11 @@ public final class PwdAuthenticate implements AuthMechanism, Serializable
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory");
env.put(Realm.REALM_CONFIG_LOCATION, m_svcConfig.getSetting(SvcConfig.IdentityAbstractionConfigFile));
env.put(Realm.REALM_SELECTOR, authReqMsg.getRealm());
if (m_svcConfig.m_realmsInfo.proxyCredentialsInRealmFile(authReqMsg.getRealm()) == false)
{
env.put(Context.SECURITY_PRINCIPAL, m_svcConfig.m_realmsInfo.proxyUsernameCredential(authReqMsg.getRealm()));
env.put(Context.SECURITY_CREDENTIALS, m_svcConfig.m_realmsInfo.proxyPasswordCredential(authReqMsg.getRealm()));
}
int retries = 3;
while (retries != 0)

View File

@ -37,10 +37,14 @@ import org.bandit.util.config.Realm;
import org.apache.log4j.Logger;
import java.io.FileReader;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Map;
import java.util.HashMap;
import com.novell.casa.NetCredential;
import com.novell.casa.MiCasa;
/**
* RealmsInfo class.
* <p>
@ -73,6 +77,9 @@ public class RealmsInfo
// Map for holding ream key/values
protected Map<String, String> m_keyValueMap = new HashMap<String, String>();
protected String[] m_searchRoots = null;
protected boolean m_proxyUserCredentialsInRealmsFile = true;
protected String m_proxyUserName = null;
protected String m_proxyUserPassword = null;
}
// Map for holding ream information
@ -87,162 +94,214 @@ public class RealmsInfo
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++)
FileReader fileReader = null;
try
{
RealmsTypeItem realmsTypeItem = realmsType.getRealmsTypeItem(i);
org.bandit.util.config.gen.Realm realm = realmsTypeItem.getRealm();
if (realm.getDesc().equalsIgnoreCase("Directory"))
fileReader = new FileReader(realmConfigFilePath);
RealmsType realmsType = Realms.unmarshal(fileReader);
for (int i = 0; i < realmsType.getRealmsTypeItemCount(); i++)
{
// We are dealing with a directory realm
RealmInfo realmInfo = new RealmInfo();
RealmTypeItem[] realmTypeItems = realm.getRealmTypeItem();
String principalName = null;
for (int ii = 0; ii < realmTypeItems.length; ii++)
RealmsTypeItem realmsTypeItem = realmsType.getRealmsTypeItem(i);
org.bandit.util.config.gen.Realm realm = realmsTypeItem.getRealm();
if (realm.getDesc().equalsIgnoreCase("Directory"))
{
// Find the configure Proxy User Name for the realm and any configured
// search roots.
if (realmTypeItems[ii].getConnection() == null)
// We are dealing with a directory realm
RealmInfo realmInfo = new RealmInfo();
RealmTypeItem[] realmTypeItems = realm.getRealmTypeItem();
String principalName = null;
String principalPassword = null;
for (int ii = 0; ii < realmTypeItems.length; ii++)
{
Env env[] = realmTypeItems[ii].getEnv();
if (env != null)
// Find the configure Proxy User Name for the realm and any configured
// search roots.
if (realmTypeItems[ii].getConnection() == null)
{
for (int iii = 0; iii < env.length; iii++)
Env env[] = realmTypeItems[ii].getEnv();
if (env != null)
{
if (env[iii].getProp().equalsIgnoreCase("java.naming.security.principal"))
for (int iii = 0; iii < env.length; iii++)
{
// We found the proxy user name. Save it in case it is needed later.
principalName = env[iii].getValue();
}
else if (env[iii].getProp().equalsIgnoreCase("com.novell.casa.authtoksvc.searchroot"))
{
// 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)
if (env[iii].getProp().equalsIgnoreCase("java.naming.security.principal"))
{
realmInfo.m_searchRoots = new String[1];
realmInfo.m_searchRoots[0] = env[iii].getValue();
// We found the proxy user name. Save it in case it is needed later.
principalName = env[iii].getValue();
}
else
else if (env[iii].getProp().equalsIgnoreCase("java.naming.security.credentials"))
{
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;
// We found the proxy password. Save it in case it is needed later.
principalPassword = env[iii].getValue();
}
else if (env[iii].getProp().equalsIgnoreCase("com.novell.casa.authtoksvc.searchroot"))
{
// 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 if (env[iii].getProp().equalsIgnoreCase("com.novell.casa.authtoksvc.directory_type"))
{
// We are dealing with a directory type, decode it and record the result.
String realmDirectoryType = env[iii].getValue();
if (realmDirectoryType.equalsIgnoreCase("eDir"))
{
realmInfo.m_keyValueMap.put(RealmType, eDirectoryRealm);
}
else if (realmDirectoryType.equalsIgnoreCase("ActiveDirectory"))
{
realmInfo.m_keyValueMap.put(RealmType, ActiveDirectoryRealm);
}
else
{
// Ignore parameter
m_log.debug("Constructor()- Unknown directory type");
}
}
else if (env[iii].getProp().equalsIgnoreCase("com.novell.casa.authtoksvc.contextless_search_string"))
{
// We are dealing with the contextless search string, keep track of it.
realmInfo.m_keyValueMap.put(CntxtlessSearchString, env[iii].getValue());
}
}
else if (env[iii].getProp().equalsIgnoreCase("com.novell.casa.authtoksvc.directory_type"))
}
}
else
{
LDAPConnector connector = (LDAPConnector) realmTypeItems[ii].getConnection();
realmInfo.m_keyValueMap.put(RealmUrl, connector.getAddress(0));
}
}
// Check if we need to read the proxy user credentials from miCASA
if (principalName == null || principalPassword == null)
{
realmInfo.m_proxyUserCredentialsInRealmsFile = false;
// We need to access miCASA to obtain the credentials
try
{
MiCasa store = new MiCasa();
NetCredential nc = store.getCredential(0, realm.getId(), null, 0);
realmInfo.m_proxyUserName = principalName = nc.getUsername();
realmInfo.m_proxyUserPassword = principalPassword = nc.getPassword();
}
catch (Exception e)
{
m_log.warn("Constructor()- Exception caught obtaining proxy user credentials from miCASA, msg = " + e.getMessage());
}
}
// Check if we must try to determine the directory type
if (realmInfo.m_keyValueMap.get(RealmType) == null)
{
// The directory type has not been determined, check if the proxy username was configured.
if (principalName != null)
{
// The proxy user name was configured, 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 env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory");
env.put(Realm.REALM_CONFIG_LOCATION, realmConfigFilePath);
env.put(Realm.REALM_SELECTOR, realm.getId());
if (realmInfo.m_proxyUserCredentialsInRealmsFile == false)
{
env.put(Context.SECURITY_PRINCIPAL, realmInfo.m_proxyUserName);
env.put(Context.SECURITY_CREDENTIALS, realmInfo.m_proxyUserPassword);
}
int retries = 3;
while (retries != 0)
{
// Instantiate DirContext watching for an exception since it
// would be an indication that we should not retry the
// operation.
DirContext ctx;
try
{
// We are dealing with a directory type, decode it and record the result.
String realmDirectoryType = env[iii].getValue();
if (realmDirectoryType.equalsIgnoreCase("eDir"))
{
realmInfo.m_keyValueMap.put(RealmType, eDirectoryRealm);
}
else if (realmDirectoryType.equalsIgnoreCase("ActiveDirectory"))
ctx = new InitialDirContext(env);
}
catch (Exception e)
{
m_log.warn("Constructor()- Exception caught instantiating DirContext, msg = " + e.getMessage());
// Stop retrying
break;
}
// Now do the attribute lookup watching for a service unavailable
// exception as an indication that we should retry the operation.
try
{
String[] attributesNeeded = new String[1];
attributesNeeded[0] = "sAMAccountName";
Attributes attributes = ctx.getAttributes(principalName, attributesNeeded);
NamingEnumeration ae = attributes.getAll();
if (ae != null && ae.hasMore())
{
realmInfo.m_keyValueMap.put(RealmType, ActiveDirectoryRealm);
}
else
{
// Ignore parameter
m_log.debug("Constructor()- Unknown directory type");
realmInfo.m_keyValueMap.put(RealmType, eDirectoryRealm);
}
}
else if (env[iii].getProp().equalsIgnoreCase("com.novell.casa.authtoksvc.contextless_search_string"))
catch (ServiceUnavailableException e)
{
// We are dealing with the contextless search string, keep track of it.
realmInfo.m_keyValueMap.put(CntxtlessSearchString, env[iii].getValue());
m_log.warn("Constructor()- ServiceUnavailable exception caught looking up attributes, msg = " + e.getMessage());
// Retry the operation
retries --;
continue;
}
catch (Exception e)
{
m_log.warn("Constructor()- Exception caught looking up attributes, msg = " + e.getMessage());
}
}
}
}
else
{
LDAPConnector connector = (LDAPConnector) realmTypeItems[ii].getConnection();
realmInfo.m_keyValueMap.put(RealmUrl, connector.getAddress(0));
}
}
// Check if we must try to determine the directory type
if (realmInfo.m_keyValueMap.get(RealmType) == null)
{
// The directory type has not been determined, check if the proxy username was configured.
if (principalName != null)
{
// The proxy user name was configured, 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 env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "org.bandit.ia.IAInitialCtxFactory");
env.put(Realm.REALM_CONFIG_LOCATION, realmConfigFilePath);
env.put(Realm.REALM_SELECTOR, realm.getId());
int retries = 3;
while (retries != 0)
{
// Instantiate DirContext watching for an exception since it
// would be an indication that we should not retry the
// operation.
DirContext ctx;
try
{
ctx = new InitialDirContext(env);
}
catch (Exception e)
{
m_log.warn("Constructor()- Exception caught instantiating DirContext, msg = " + e.getMessage());
// Stop retrying
// No need to retry
break;
}
// Now do the attribute lookup watching for a service unavailable
// exception as an indication that we should retry the operation.
try
{
String[] attributesNeeded = new String[1];
attributesNeeded[0] = "sAMAccountName";
Attributes attributes = ctx.getAttributes(principalName, attributesNeeded);
NamingEnumeration ae = attributes.getAll();
if (ae != null && ae.hasMore())
{
realmInfo.m_keyValueMap.put(RealmType, ActiveDirectoryRealm);
}
else
{
realmInfo.m_keyValueMap.put(RealmType, eDirectoryRealm);
}
}
catch (ServiceUnavailableException e)
{
m_log.warn("Constructor()- ServiceUnavailable exception caught looking up attributes, msg = " + e.getMessage());
// Retry the operation
retries --;
continue;
}
catch (Exception e)
{
m_log.warn("Constructor()- Exception caught looking up attributes, msg = " + e.getMessage());
}
// No need to retry
break;
}
else
{
// The principal name was not configured, default to eDir.
realmInfo.m_keyValueMap.put(RealmType, eDirectoryRealm);
}
}
else
{
// The principal name was not configured, default to eDir.
realmInfo.m_keyValueMap.put(RealmType, eDirectoryRealm);
}
}
m_realmsMap.put(realm.getId(), realmInfo);
m_realmsMap.put(realm.getId(), realmInfo);
}
}
}
catch (Exception e)
{
m_log.error("Constructor()- Exception caught, msg = " + e.getMessage());
}
finally
{
if (fileReader != null)
{
try
{
fileReader.close();
}
catch (IOException e)
{
// Do nothing
}
}
}
}
@ -306,4 +365,50 @@ public class RealmsInfo
else
return null;
}
/**
* Proxy Credentials In Realms File.
*
* @param realmId Realm id.
* @return True if present.
*/
final boolean proxyCredentialsInRealmFile(String realmId)
{
RealmInfo realmInfo = m_realmsMap.get(realmId);
if (realmInfo != null)
return realmInfo.m_proxyUserCredentialsInRealmsFile;
else
// Assume yes
return true;
}
/**
* Proxy Username Credential.
*
* @param realmId Realm id.
* @return Username or null.
*/
final String proxyUsernameCredential(String realmId)
{
RealmInfo realmInfo = m_realmsMap.get(realmId);
if (realmInfo != null)
return realmInfo.m_proxyUserName;
else
return null;
}
/**
* Proxy Password Credential.
*
* @param realmId Realm id.
* @return Password or null.
*/
final String proxyPasswordCredential(String realmId)
{
RealmInfo realmInfo = m_realmsMap.get(realmId);
if (realmInfo != null)
return realmInfo.m_proxyUserPassword;
else
return null;
}
}

View File

@ -54,4 +54,4 @@ server.loader=${catalina.home}/server/classes,${catalina.home}/server/lib/*.jar
# "foo/*.jar": Add all the JARs of the specified folder as class
# repositories
# "foo/bar.jar": Add bar.jar as a class repository
shared.loader=${catalina.base}/shared/classes,${catalina.base}/shared/lib/*.jar,/usr/share/java/identity-abstraction/*.jar
shared.loader=${catalina.base}/shared/classes,${catalina.base}/shared/lib/*.jar,/usr/share/java/identity-abstraction/*.jar,/usr/lib/miCASA.jar

View File

@ -1,3 +1,27 @@
-------------------------------------------------------------------
Wed May 9 16:38:14 MDT 2007 - jluciani@novell.com
- Added the capability to read REALM credentials from miCASA to
avoid having the credentials in the clear in the iaRealms.xml
file. This change adds a dependency on CASA and partially
addresses BUG265414.
- Created a utility that allows users to edit the iaRealms.xml
file. This was necessary to support the CASA ATS Yast Module
enhancements.
- Fixed settings and policy utilities to output error messages
to stderr instead of stdout to avoid messing up the CASA ATS
Yast Module.
- Fixed the SPEC files to set the appropriate home folder for
the casaatsd user.
- Temporary changed the SPEC files to allow the casaatsd user
to have a shell. This change will be reverted as soon as
the CASAcli is updated to allow a root user to pass the
UID of the user being targeted.
-------------------------------------------------------------------
Fri Apr 20 15:40:01 MDT 2007 - jluciani@novell.com

View File

@ -18,7 +18,7 @@
Name: @PACKAGE@
URL: http://www.novell.com/products
BuildRequires: gcc-c++ glib2-devel identity-abstraction insserv libstdc++ libstdc++-devel mono-devel pkgconfig servletapi5 sysvinit xerces-j2 xml-commons-apis
BuildRequires: java-sdk-1.5.0 update-alternatives log4j jakarta-commons-logging pwdutils
BuildRequires: java-sdk-1.5.0 update-alternatives log4j jakarta-commons-logging pwdutils CASA-devel
%define prefix /usr
License: LGPL
Group: Applications/System
@ -30,7 +30,7 @@ Summary: Novell CASA Authentication Token Service
Source: %{name}-%{version}.tar.bz2
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Requires: jre >= 1.5.0
Requires: servletapi5 tomcat5 sysvinit insserv identity-abstraction sed log4j xerces-j2
Requires: servletapi5 tomcat5 sysvinit insserv identity-abstraction sed log4j xerces-j2 CASA
PreReq: %fillup_prereq %insserv_prereq
PreReq: /usr/bin/awk, /usr/bin/test, /bin/grep, /bin/cat, /usr/bin/install, /bin/pwd
PreReq: /usr/sbin/groupadd, /usr/sbin/useradd, /usr/sbin/userdel, /usr/bin/getent
@ -221,7 +221,8 @@ fi
user_present=`getent passwd | grep ^casaatsd`
if [ -z "$user_present" ] ; then
/usr/sbin/useradd -c "casaatsd System User" -s /bin/false -r -d /var/lib/CASA/authtoken/svc -g casaauth casaatsd 2> /dev/null || :
# /usr/sbin/useradd -c "casaatsd System User" -s /bin/false -r -d /var/lib/CASA/authtoken/svc -g casaauth casaatsd 2> /dev/null || :
/usr/sbin/useradd -c "casaatsd System User" -s /bin/bash -r -d /var/lib/CASA/authtoken/svc -g casaauth casaatsd 2> /dev/null || :
fi

View File

@ -18,7 +18,7 @@
Name: @PACKAGE@
URL: http://www.novell.com/products
BuildRequires: gcc-c++ glib2-devel identity-abstraction insserv libstdc++ libstdc++-devel mono-devel pkgconfig servletapi5 sysvinit xerces-j2 jdk novell-zenworks-java-links xml-commons-apis
BuildRequires: java-sdk-1.5.0 update-alternatives log4j jakarta-commons-logging pwdutils
BuildRequires: java-sdk-1.5.0 update-alternatives log4j jakarta-commons-logging pwdutils CASA-devel
%define prefix /usr
License: LGPL
Group: Applications/System
@ -30,7 +30,7 @@ Summary: Novell CASA Authentication Token Service
Source: %{name}-%{version}.tar.bz2
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Requires: jre >= 1.5.0
Requires: novell-zenworks-tomcat sysvinit insserv identity-abstraction sed jdk novell-zenworks-java-links log4j xerces-j2
Requires: novell-zenworks-tomcat sysvinit insserv identity-abstraction sed jdk novell-zenworks-java-links log4j xerces-j2 CASA
PreReq: %fillup_prereq %insserv_prereq
PreReq: /usr/bin/awk, /usr/bin/test, /bin/grep, /bin/cat, /usr/bin/install, /bin/pwd
PreReq: /usr/sbin/groupadd, /usr/sbin/useradd, /usr/sbin/userdel, /usr/bin/getent
@ -221,7 +221,8 @@ fi
user_present=`getent passwd | grep ^casaatsd`
if [ -z "$user_present" ] ; then
/usr/sbin/useradd -c "casaatsd System User" -s /bin/false -r -d /var/lib/CASA/authtoken/svc -g casaauth casaatsd 2> /dev/null || :
# /usr/sbin/useradd -c "casaatsd System User" -s /bin/false -r -d /var/lib/CASA/authtoken/svc -g casaauth casaatsd 2> /dev/null || :
/usr/sbin/useradd -c "casaatsd System User" -s /bin/bash -r -d /var/lib/CASA/authtoken/svc -g casaauth casaatsd 2> /dev/null || :
fi