// --- BEGIN COPYRIGHT BLOCK --- // 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; version 2 of the License. // // 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., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package com.netscape.cms.authentication; // ldap java sdk import java.util.Enumeration; import java.util.Locale; import java.util.Vector; import netscape.ldap.LDAPAttribute; import netscape.ldap.LDAPAttributeSet; import netscape.ldap.LDAPConnection; import netscape.ldap.LDAPEntry; import netscape.ldap.LDAPException; import netscape.ldap.LDAPObjectClassSchema; import netscape.ldap.LDAPSchema; import netscape.ldap.LDAPSearchResults; import netscape.ldap.LDAPv2; import com.netscape.certsrv.apps.CMS; import com.netscape.certsrv.authentication.AuthToken; import com.netscape.certsrv.authentication.EAuthInternalError; import com.netscape.certsrv.authentication.EAuthUserError; import com.netscape.certsrv.authentication.EInvalidCredentials; import com.netscape.certsrv.authentication.EMissingCredential; import com.netscape.certsrv.authentication.IAuthCredentials; import com.netscape.certsrv.base.EBaseException; import com.netscape.certsrv.base.EPropertyNotFound; import com.netscape.certsrv.base.IArgBlock; import com.netscape.certsrv.base.IConfigStore; import com.netscape.certsrv.base.IExtendedPluginInfo; import com.netscape.certsrv.ldap.ELdapException; import com.netscape.certsrv.ldap.ILdapConnFactory; import com.netscape.certsrv.logging.ILogger; /** * uid/pwd directory based authentication manager *
*
* @version $Revision$, $Date$
*/
public class PortalEnroll extends DirBasedAuthentication {
/* configuration parameter keys */
protected static final String PROP_LDAPAUTH = "ldapauth";
protected static final String PROP_AUTHTYPE = "authtype";
protected static final String PROP_BINDDN = "bindDN";
protected static final String PROP_BINDPW = "bindPW";
protected static final String PROP_LDAPCONN = "ldapconn";
protected static final String PROP_HOST = "host";
protected static final String PROP_PORT = "port";
protected static final String PROP_SECURECONN = "secureConn";
protected static final String PROP_VERSION = "version";
protected static final String PROP_OBJECTCLASS = "objectclass";
/* required credentials to authenticate. uid and pwd are strings. */
public static final String CRED_UID = "uid";
public static final String CRED_PWD = "userPassword";
protected static String[] mRequiredCreds = { CRED_UID, CRED_PWD };
/* ldap configuration sub-store */
private IArgBlock argblk = null;
private String mObjectClass = null;
private String mBindDN = null;
private String mBaseDN = null;
private ILdapConnFactory mLdapFactory = null;
private LDAPConnection mLdapConn = null;
// contains all nested superiors' required attrs in the form of a
// vector of "required" attributes in Enumeration
Vector
*
* @param name - The name for this authentication manager instance.
* @param implName - The name of the authentication manager plugin.
* @param config - The configuration store for this instance.
* @exception EBaseException If an error occurs during initialization.
*/
public void init(String name, String implName, IConfigStore config)
throws EBaseException {
super.init(name, implName, config);
/* Get Bind DN for directory server */
mConfig = mLdapConfig.getSubStore(PROP_LDAPAUTH);
mBindDN = mConfig.getString(PROP_BINDDN);
if ((mBindDN == null) || (mBindDN.length() == 0) || (mBindDN == ""))
throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", "binddn"));
/* Get Bind DN for directory server */
mBaseDN = mLdapConfig.getString(PROP_BASEDN);
if ((mBaseDN == null) || (mBaseDN.length() == 0) || (mBaseDN == ""))
throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", "basedn"));
/* Get Object clase name for enrollment */
mObjectClass = mLdapConfig.getString(PROP_OBJECTCLASS);
if (mObjectClass == null || mObjectClass.length() == 0)
throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", "objectclass"));
/* Get connect parameter */
mLdapFactory = CMS.getLdapBoundConnFactory();
mLdapFactory.init(mLdapConfig);
mLdapConn = mLdapFactory.getConn();
log(ILogger.LL_INFO, CMS.getLogMessage("CMS_AUTH_PORTAL_INIT"));
}
/**
* Authenticates a user based on uid, pwd in the directory.
*
* @param authCreds The authentication credentials.
* @return The user's ldap entry dn.
* @exception EInvalidCredentials If the uid and password are not valid
* @exception EBaseException If an internal error occurs.
*/
protected String authenticate(LDAPConnection conn,
IAuthCredentials authCreds,
AuthToken token)
throws EBaseException {
String uid = null;
String pwd = null;
String dn = null;
argblk = authCreds.getArgBlock();
// authenticate by binding to ldap server with password.
try {
// get the uid.
uid = (String) authCreds.get(CRED_UID);
if (uid == null) {
throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_UID));
}
// get the password.
pwd = (String) authCreds.get(CRED_PWD);
if (pwd == null) {
throw new EMissingCredential(CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_PWD));
}
if (pwd.equals("")) {
// anonymous binding not allowed
throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
}
// get user dn.
LDAPSearchResults res = conn.search(mBaseDN,
LDAPv2.SCOPE_SUB, "(uid=" + uid + ")", null, false);
if (res.hasMoreElements()) {
res.nextElement(); // consume the entry
throw new EAuthUserError(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_ATTRIBUTE_VALUE",
"UID already exists."));
} else {
dn = regist(token, uid);
if (dn == null)
throw new EAuthUserError(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_ATTRIBUTE_VALUE",
"Could not add user " + uid + "."));
}
// bind as user dn and pwd - authenticates user with pwd.
conn.authenticate(dn, pwd);
// set uid in the token.
token.set(CRED_UID, uid);
log(ILogger.LL_INFO, "portal authentication is done");
return dn;
} catch (ELdapException e) {
log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_ERROR", e.toString()));
throw e;
} catch (LDAPException e) {
switch (e.getLDAPResultCode()) {
case LDAPException.NO_SUCH_OBJECT:
case LDAPException.LDAP_PARTIAL_RESULTS:
log(ILogger.LL_SECURITY,
CMS.getLogMessage("CMS_AUTH_ADD_USER_ERROR", conn.getHost(), Integer.toString(conn.getPort())));
throw new EAuthInternalError(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR",
"Check Configuration detail."));
case LDAPException.INVALID_CREDENTIALS:
log(ILogger.LL_SECURITY,
CMS.getLogMessage("CMS_AUTH_BAD_PASSWORD", uid));
throw new EInvalidCredentials(CMS.getUserMessage("CMS_AUTHENTICATION_INVALID_CREDENTIAL"));
case LDAPException.SERVER_DOWN:
log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_SERVER_DOWN"));
throw new ELdapException(
CMS.getUserMessage("CMS_LDAP_SERVER_UNAVAILABLE", conn.getHost(), "" + conn.getPort()));
default:
log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_ERROR", e.getMessage()));
throw new ELdapException(
CMS.getUserMessage("CMS_LDAP_OTHER_LDAP_EXCEPTION",
e.errorCodeToString()));
}
} catch (EBaseException e) {
if (e.getMessage().equalsIgnoreCase(CMS.getUserMessage("CMS_BASE_ATTRIBUTE_NOT_FOUND")) == true)
log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_MAKE_DN_ERROR", e.toString()));
throw e;
}
}
/**
* Returns a list of configuration parameter names.
* The list is passed to the configuration console so instances of
* this implementation can be configured through the console.
*
* @return String array of configuration parameter names.
*/
public String[] getConfigParams() {
return (mConfigParams);
}
public String[] getExtendedPluginInfo(Locale locale) {
String[] s = {
PROP_DNPATTERN + ";string;Template for cert" +
" Subject Name. ($dn.xxx - get value from user's LDAP " +
"DN. $attr.yyy - get value from LDAP attributes in " +
"user's entry.) Default: " + DEFAULT_DNPATTERN,
"ldap.ldapconn.host;string,required;" + "LDAP host to connect to",
"ldap.ldapconn.port;number,required;" + "LDAP port number (default 389, or 636 if SSL)",
"ldap.objectclass;string,required;SEE DOCUMENTATION for Object Class. "
+ "Default is inetOrgPerson.",
"ldap.ldapconn.secureConn;boolean;" + "Use SSL to connect to directory?",
"ldap.ldapconn.version;choice(3,2);" + "LDAP protocol version",
"ldap.ldapauth.bindDN;string,required;DN to bind as for Directory Manager. "
+ "For example 'CN=Directory Manager'",
"ldap.ldapauth.bindPWPrompt;password;Enter password used to bind as " +
"the above user",
"ldap.ldapauth.authtype;choice(BasicAuth,SslClientAuth);"
+ "How to bind to the directory (for pin removal only)",
"ldap.ldapauth.clientCertNickname;string;If you want to use "
+ "SSL client auth to the directory, set the client "
+ "cert nickname here",
"ldap.basedn;string,required;Base DN to start searching " +
"under. If your user's DN is 'uid=jsmith, o=company', you " +
"might want to use 'o=company' here",
"ldap.minConns;number;number of connections " +
"to keep open to directory server",
"ldap.maxConns;number;when needed, connection " +
"pool can grow to this many connections",
IExtendedPluginInfo.HELP_TEXT +
";This authentication plugin checks to see if a user " +
"exists in the directory. If not, then the user is created " +
"with the requested password.",
IExtendedPluginInfo.HELP_TOKEN + ";configuration-authrules-portalauth"
};
return s;
}
/**
* Returns array of required credentials for this authentication manager.
*
* @return Array of required credentials.
*/
public String[] getRequiredCreds() {
return mRequiredCreds;
}
/**
* adds a user to the directory.
*
* @return dn upon success and null upon failure.
* @param token authentication token
* @param uid the user's id.
*/
public String regist(AuthToken token, String uid) {
String dn = "uid=" + uid + "," + mBaseDN;
/* Specify the attributes of the entry */
Vector