diff options
10 files changed, 811 insertions, 8 deletions
diff --git a/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginRequest.java b/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginRequest.java index dbc481688..77081654b 100644 --- a/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginRequest.java +++ b/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginRequest.java @@ -33,6 +33,8 @@ public class ExtendedLoginRequest extends TPSMessage { put(INVALID_PWD_NAME, invalid_pw); put(BLOCKED_NAME, blocked); put(MSG_TYPE_NAME, msgTypeToInt(MsgType.MSG_EXTENDED_LOGIN_REQUEST)); + put(TITLE_NAME, title); + put (DESCRIPTION_NAME, description); this.params = params; } diff --git a/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginResponse.java b/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginResponse.java index 8ae7ad66a..29e9b72af 100644 --- a/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginResponse.java +++ b/base/common/src/org/dogtagpki/tps/msg/ExtendedLoginResponse.java @@ -32,6 +32,16 @@ public class ExtendedLoginResponse extends TPSMessage { //ToDo process the actual params } + public ExtendedLoginResponse(OpType theOp, String uid, String password, Map<String, String> theExtensions) { + + put(OPERATION_TYPE_NAME, opTypeToInt(theOp)); + put(MSG_TYPE_NAME, msgTypeToInt(MsgType.MSG_EXTENDED_LOGIN_RESPONSE)); + authParams = theExtensions; + put(SCREEN_NAME_NAME, uid); + put(PASSWORD_NAME, password); + + } + public static void main(String[] args) { } diff --git a/base/common/src/org/dogtagpki/tps/msg/TPSMessage.java b/base/common/src/org/dogtagpki/tps/msg/TPSMessage.java index c6e7cf7a7..39af93c7d 100644 --- a/base/common/src/org/dogtagpki/tps/msg/TPSMessage.java +++ b/base/common/src/org/dogtagpki/tps/msg/TPSMessage.java @@ -69,6 +69,8 @@ public class TPSMessage { public static final String SCREEN_NAME_NAME = "screen_name"; public static final String PASSWORD_NAME = "password"; public static final String PIN_REQUIRED_NAME = "pin_required"; + public static final String TITLE_NAME = "title"; + public static final String DESCRIPTION_NAME = "description"; public static final String NEXT_VALUE_NAME = "next_value"; public static final String VALUE_NAME = "value"; public static final String PIN_NAME = "pin"; @@ -451,10 +453,18 @@ public class TPSMessage { case MSG_EXTENDED_LOGIN_REQUEST: break; case MSG_EXTENDED_LOGIN_RESPONSE: + result = + new ExtendedLoginResponse(op_val, + get(SCREEN_NAME_NAME), + get(PASSWORD_NAME), + extsMap); break; case MSG_LOGIN_REQUEST: break; case MSG_LOGIN_RESPONSE: + result = + new LoginResponse(get(SCREEN_NAME_NAME), + get(PASSWORD_NAME)); break; case MSG_NEW_PIN_REQUEST: break; diff --git a/base/server/cms/src/com/netscape/cms/authentication/UidPwdDirAuthentication.java b/base/server/cms/src/com/netscape/cms/authentication/UidPwdDirAuthentication.java index ffa8ea42f..85fe19635 100644 --- a/base/server/cms/src/com/netscape/cms/authentication/UidPwdDirAuthentication.java +++ b/base/server/cms/src/com/netscape/cms/authentication/UidPwdDirAuthentication.java @@ -154,9 +154,11 @@ public class UidPwdDirAuthentication extends DirBasedAuthentication return userdn; } catch (ELdapException e) { + CMS.debug("Authenticating: User authentication failure: "+e); log(ILogger.LL_FAILURE, CMS.getLogMessage("CANNOT_CONNECT_LDAP", e.toString())); throw e; } catch (LDAPException e) { + CMS.debug("Authenticating: User authentication failure: "+e); switch (e.getLDAPResultCode()) { case LDAPException.NO_SUCH_OBJECT: case LDAPException.LDAP_PARTIAL_RESULTS: diff --git a/base/tps-tomcat/shared/conf/CS.cfg.in b/base/tps-tomcat/shared/conf/CS.cfg.in index abee88f4d..4772bfc5c 100644 --- a/base/tps-tomcat/shared/conf/CS.cfg.in +++ b/base/tps-tomcat/shared/conf/CS.cfg.in @@ -34,6 +34,17 @@ auths.impl.UidPwdPinDirAuth.class=com.netscape.cms.authentication.UidPwdPinDirAu auths.instance.AgentCertAuth.agentGroup=Certificate Manager Agents auths.instance.AgentCertAuth.pluginName=AgentCertAuth auths.instance.TokenAuth.pluginName=TokenAuth +auths.instance.ldap1.ui.retries=3 +auths.instance.ldap1.ui.title.en=LDAP Authentication +auths.instance.ldap1.ui.description.en=This authenticates user against the LDAP directory. +auths.instance.ldap1.ui.id.UID.description.en=LDAP User ID +auths.instance.ldap1.ui.id.UID.name.en=LDAP User ID +auths.instance.ldap1.ui.id.UID.credMap.authCred=uid +auths.instance.ldap1.ui.id.UID.credMap.msgCred=screen_name +auths.instance.ldap1.ui.id.PASSWORD.description.en=LDAP Password +auths.instance.ldap1.ui.id.PASSWORD.name.en=LDAP Password +auths.instance.ldap1.ui.id.PASSWORD.credMap.authCred=pwd +auths.instance.ldap1.ui.id.PASSWORD.credMap.msgCred=password auths.instance.ldap1.dnpattern= auths.instance.ldap1.ldapByteAttributes= auths.instance.ldap1.ldapStringAttributes=mail,cn,uid @@ -43,7 +54,7 @@ auths.instance.ldap1.ldap.minConns=3 auths.instance.ldap1.ldap.ldapauth.authtype=BasicAuth auths.instance.ldap1.ldap.ldapauth.bindDN= auths.instance.ldap1.ldap.ldapauth.bindPWPrompt=ldap1 -auths.instance.ldap1.ldap.ldapauth.clientCertNickname= +auths.instance.ldap1.ldap.ldapauth.clientCertNickname=subsystemCert cert-[PKI_INSTANCE_NAME] auths.instance.ldap1.ldap.ldapconn.host=localhost auths.instance.ldap1.ldap.ldapconn.port=389 auths.instance.ldap1.ldap.ldapconn.secureConn=false @@ -1318,8 +1329,8 @@ target._018=# target._019=######################################## target.agent_approve.list=Profiles target.Authentication_Sources.displayname=Authentication Source -target.Authentication_Sources.list=0,1 -target.Authentication_Sources.pattern=auth\.instance\.$name\..* +target.Authentication_Sources.list=ldap1 +target.Authentication_Sources.pattern=auths\.instance\.$name\..* target.configure.list=Profiles,Subsystem_Connections,Profile_Mappings,Authentication_Sources target.Generals.displayname=General target.Generals.pattern=^applet\..*\|^general\..*\|^failover.pod.enable\|^channel\..* diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSubsystem.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSubsystem.java index 1d5c9d2b9..30696bbdb 100644 --- a/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSubsystem.java +++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/TPSSubsystem.java @@ -17,6 +17,7 @@ // --- END COPYRIGHT BLOCK --- package org.dogtagpki.server.tps; +import org.dogtagpki.server.tps.authentication.AuthenticationManager; import org.dogtagpki.server.tps.cms.ConnectionManager; import org.dogtagpki.server.tps.config.ConfigDatabase; import org.dogtagpki.server.tps.config.ConnectorDatabase; @@ -66,6 +67,7 @@ public class TPSSubsystem implements IAuthority, ISubsystem { public ProfileMappingDatabase profileMappingDatabase; public TokenDatabase tokenDatabase; public ConnectionManager connManager; + public AuthenticationManager authManager; public TPSEngine engine; @Override @@ -109,6 +111,8 @@ public class TPSSubsystem implements IAuthority, ISubsystem { CMS.debug("TPSSubsystem: startup() begins"); connManager = new ConnectionManager(); connManager.initConnectors(); + authManager = new AuthenticationManager(); + authManager.initAuthInstances(); CMS.debug("TPSSubsystem: startup() ends."); } @@ -189,6 +193,10 @@ public class TPSSubsystem implements IAuthority, ISubsystem { return connManager; } + public AuthenticationManager getAuthenticationManager() { + return authManager; + } + public org.mozilla.jss.crypto.X509Certificate getSubsystemCert() throws EBaseException, NotInitializedException, ObjectNotFoundException, TokenException { IConfigStore cs = CMS.getConfigStore(); diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/AuthUIParameter.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/AuthUIParameter.java new file mode 100644 index 000000000..b014bd3d5 --- /dev/null +++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/AuthUIParameter.java @@ -0,0 +1,86 @@ +// --- 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) 2014 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package org.dogtagpki.server.tps.authentication; + +import java.util.HashMap; + +import com.netscape.certsrv.base.EBaseException; + +/* + * AuthUIParameters is a class for per locale parameter sets + * + * @author cfu + */ +public class AuthUIParameter { + + private String paramId; + /* + * auths.instance.<authInst>.ui.id.<param>.name.<locale>=<name> + * auths.instance.<authInst>.ui.id.<param>.description.<locale>=<description> + * e.g. + * auths.instance.ldap1.ui.id.PASSWORD.description.en=LDAP Password + * auths.instance.ldap1.ui.id.PASSWORD.name.en=LDAP Password + * auths.instance.ldap1.ui.id.UID.description.en=LDAP User ID + * auths.instance.ldap1.ui.id.UID.name.en=LDAP User ID + * + * for each id param <locale, name> + */ + private HashMap<String, String> uiParamIdName; + private HashMap<String, String> uiParamIdDescription; + + public AuthUIParameter(String id) + throws EBaseException { + paramId = id; + uiParamIdName = new HashMap<String, String>(); + uiParamIdDescription = new HashMap<String, String>(); + } + + public void setParamName(String locale, String name) { + uiParamIdName.put(locale, name); + } + + public String getParamName(String locale) { + return uiParamIdName.get(locale); + } + + public void setParamDescription(String locale, String desc) { + uiParamIdDescription.put(locale, desc); + } + + public String getParamDescription(String locale) { + return uiParamIdDescription.get(locale); + } + + public String toString(String locale) { + String name = getParamName(locale); + if (name == null) + name = getParamName("en"); + + String desc = getParamDescription(locale); + if (desc == null) + desc = getParamDescription("en"); + + String string = + "id=" + paramId + + "&name=" + name + + "&description=" + desc + + "&type=string" + + "&option="; + return string; + } +} diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/AuthenticationManager.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/AuthenticationManager.java new file mode 100644 index 000000000..4cfee3e6f --- /dev/null +++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/AuthenticationManager.java @@ -0,0 +1,264 @@ +// --- 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) 2014 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package org.dogtagpki.server.tps.authentication; + +import java.util.Enumeration; +import java.util.Hashtable; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; + +/** + * AuthenticationManager is a class for management of authentication + * instances + * + * @author cfu + */ +public class AuthenticationManager +{ + private Hashtable<String, TPSAuthenticator> authInstances; + + public AuthenticationManager() { + } + + /* + * initAuthInstances initializes authentication manager instances + * + * configuration e.g. + * + * auths.instance.ldap1.ui.description.en=This authenticates user against the LDAP directory. + * auths.instance.ldap1.ui.title.en=LDAP Authentication + * auths.instance.ldap1.ui.id.PASSWORD.description.en=LDAP Password + * auths.instance.ldap1.ui.id.PASSWORD.name.en=LDAP Password + * auths.instance.ldap1.ui.id.PASSWORD.credMap.authCred=pwd + * auths.instance.ldap1.ui.id.PASSWORD.credMap.msgCred=password + * auths.instance.ldap1.ui.id.UID.description.en=LDAP User ID + * auths.instance.ldap1.ui.id.UID.name.en=LDAP User ID + * auths.instance.ldap1.ui.id.UID.credMap.authCred=uid + * auths.instance.ldap1.ui.id.UID.credMap.msgCred=screen_name + * auths.instance.ldap1.ui.retries=1 + * + * # the following are handled by the IAuthManager itself + * auths.instance.ldap1.dnpattern= + * auths.instance.ldap1.ldap.basedn=dc=idm,dc=lab,dc=bos,dc=redhat,dc=com + * auths.instance.ldap1.ldap.ldapauth.authtype=BasicAuth + * auths.instance.ldap1.ldap.ldapauth.bindDN= + * auths.instance.ldap1.ldap.ldapauth.bindPWPrompt=ldap1 + * auths.instance.ldap1.ldap.ldapauth.clientCertNickname= + * auths.instance.ldap1.ldap.ldapconn.host=vm-060.idm.lab.bos.redhat.com + * auths.instance.ldap1.ldap.ldapconn.port=389 + * auths.instance.ldap1.ldap.ldapconn.secureConn=False + * auths.instance.ldap1.ldap.ldapconn.version=3 + * auths.instance.ldap1.ldap.maxConns=15 + * auths.instance.ldap1.ldap.minConns=3 + * auths.instance.ldap1.ldapByteAttributes= + * auths.instance.ldap1.ldapStringAttributes=mail,cn,uid + * auths.instance.ldap1.pluginName=UidPwdDirAuth + */ + public void initAuthInstances() throws EBaseException { + CMS.debug("AuthenticationManager: initAuthInstances(): begins."); + IConfigStore conf = CMS.getConfigStore(); + IConfigStore authInstSubstore = conf.getSubStore("auths.instance"); + Enumeration<String> auth_enu = authInstSubstore.getSubStoreNames(); + authInstances = new Hashtable<String, TPSAuthenticator>(); + while (auth_enu.hasMoreElements()) { + String authInstID = auth_enu.nextElement(); + CMS.debug("AuthenticationManager: initAuthInstances(): initializing authentication instance " + authInstID); + IConfigStore authInstSub = + authInstSubstore.getSubStore(authInstID); + TPSAuthenticator authInst = + createAuthentication(authInstSub, authInstID); + authInstances.put(authInstID, authInst); + CMS.debug("AuthenticationManager: initAuthInstances(): authentication instance " + + authInstID + + " initialized."); + } + CMS.debug("AuthenticationManager: initAuthInstances(): ends."); + } + + /* + * createAuthentication creates and returns an Authenticaiton + * + * @param conf config store of the authentication instance + * @return Authentication the authentication instance + */ + private TPSAuthenticator createAuthentication(IConfigStore conf, String authInstID) + throws EBaseException { + + CMS.debug("AuthenticationManager: createAuthentication(): begins for " + + authInstID); + + if (conf == null || conf.size() <= 0) { + CMS.debug("AuthenticationManager: createAuthentication(): conf null or empty."); + throw new EBaseException("called with null config store"); + } + + TPSAuthenticator auth = new TPSAuthenticator(authInstID); + + IConfigStore uiSub = conf.getSubStore("ui"); + if (uiSub == null) { + CMS.debug("AuthenticationManager: createAuthentication(): conf " + + conf.getName() + ".ui" + " null or empty."); + throw new EBaseException("config " + conf.getName() + ".ui" + " not found"); + } + + // init ui title + IConfigStore uiTitleSub = uiSub.getSubStore("title"); + if (uiTitleSub == null) { + CMS.debug("AuthenticationManager: createAuthentication(): conf " + + uiSub.getName() + ".title" + " null or empty."); + throw new EBaseException("config " + uiSub.getName() + ".title" + " not found"); + } + + Enumeration<String> uiTitle_enu = uiTitleSub.getPropertyNames(); + + while (uiTitle_enu.hasMoreElements()) { + String locale = uiTitle_enu.nextElement(); + String title = uiTitleSub.getString(locale); + if (title.isEmpty()) { + CMS.debug("AuthenticationManager: createAuthentication(): title for locale " + + locale + " not found"); + continue; + } + auth.setUiTitle(locale, title); + CMS.debug("AuthenticationManager: createAuthentication(): added title=" + + title + ", locale= " + locale); + } + + // init ui description + IConfigStore uiDescSub = uiSub.getSubStore("description"); + if (uiDescSub == null) { + CMS.debug("AuthenticationManager: createAuthentication(): conf " + + uiSub.getName() + ".description" + " null or empty."); + throw new EBaseException("config " + uiSub.getName() + ".description" + " not found"); + } + Enumeration<String> uiDesc_enu = uiDescSub.getPropertyNames(); + + while (uiDesc_enu.hasMoreElements()) { + String locale = uiDesc_enu.nextElement(); + String description = uiDescSub.getString(locale); + if (description.isEmpty()) { + CMS.debug("AuthenticationManager: createAuthentication(): description for locale " + + locale + " not found"); + continue; + } + auth.setUiDescription(locale, description); + CMS.debug("AuthenticationManager: createAuthentication(): added description=" + + description + ", locale= " + locale); + } + + // init ui parameters + IConfigStore uiParamSub = uiSub.getSubStore("id"); + if (uiParamSub == null) { + CMS.debug("AuthenticationManager: createAuthentication(): conf " + + uiSub.getName() + ".id" + " null or empty."); + throw new EBaseException("config " + uiSub.getName() + ".id" + " not found"); + } + Enumeration<String> uiParam_enu = uiParamSub.getSubStoreNames(); + while (uiParam_enu.hasMoreElements()) { + String id = uiParam_enu.nextElement(); + CMS.debug("AuthenticationManager: createAuthentication(): id param=" + + id); + IConfigStore idNameSub = uiParamSub.getSubStore(id + ".name"); + if (idNameSub == null) { + CMS.debug("AuthenticationManager: createAuthentication(): conf " + + uiParamSub.getName() + ".name" + " null or empty."); + continue; + } + + AuthUIParameter up = new AuthUIParameter(id); + Enumeration<String> idName_enu = idNameSub.getPropertyNames(); + while (idName_enu.hasMoreElements()) { + String locale = idName_enu.nextElement(); + String name = idNameSub.getString(locale); + if (name.isEmpty()) { + CMS.debug("AuthenticationManager: createAuthentication(): name for locale " + + locale + " not found"); + continue; + } + CMS.debug("AuthenticationManager: createAuthentication(): name =" + + name + " for locale " + locale); + up.setParamName(locale, name); + } + + IConfigStore idDescSub = uiParamSub.getSubStore(id + ".description"); + if (idDescSub == null) { + CMS.debug("AuthenticationManager: createAuthentication(): conf " + + uiParamSub.getName() + ".description" + " null or empty."); + continue; + } + Enumeration<String> idDesc_enu = idDescSub.getPropertyNames(); + while (idDesc_enu.hasMoreElements()) { + String locale = idDesc_enu.nextElement(); + String desc = idDescSub.getString(locale); + if (desc.isEmpty()) { + CMS.debug("AuthenticationManager: createAuthentication(): description for locale " + + locale + " not found"); + continue; + } + CMS.debug("AuthenticationManager: createAuthentication(): desc =" + + desc); + up.setParamDescription(locale, desc); + } + + auth.setUiParam(id, up); + CMS.debug("AuthenticationManager: createAuthentication(): added param=" + + id); + + IConfigStore credMapSub = uiParamSub.getSubStore(id + ".credMap"); + if (credMapSub == null) { + CMS.debug("AuthenticationManager: createAuthentication(): conf " + + uiParamSub.getName() + ".credMapsub" + " null or empty."); + continue; + } + String authCred = credMapSub.getString("authCred"); + if (authCred.isEmpty()) { + CMS.debug("AuthenticationManager: createAuthentication(): conf " + + credMapSub.getName() + ".authCred" + " null or empty."); + continue; + } + String msgCred = credMapSub.getString("msgCred"); + if (msgCred.isEmpty()) { + CMS.debug("AuthenticationManager: createAuthentication(): conf " + + credMapSub.getName() + ".msgCred" + " null or empty."); + continue; + } + // map the auth mgr required cred to cred name in request message + auth.setCredMap(authCred, msgCred); + + CMS.debug("AuthenticationManager: createAuthentication(): added cred map=" + + authCred + ":" + msgCred); + } + + Integer retries = uiSub.getInteger("retries", 1); + auth.setNumOfRetries(retries.intValue()); + + CMS.debug("AuthenticationManager: createAuthentication(): completed for " + + authInstID); + return auth; + } + + /* + * gets an established Authentication instance + */ + public TPSAuthenticator getAuthInstance(String id) { + return authInstances.get(id); + } +} diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/TPSAuthenticator.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/TPSAuthenticator.java new file mode 100644 index 000000000..8083343f5 --- /dev/null +++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/authentication/TPSAuthenticator.java @@ -0,0 +1,130 @@ +// --- 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) 2014 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package org.dogtagpki.server.tps.authentication; + +import java.util.HashMap; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.base.EBaseException; + +/** + * Authentication is a class for an authentication instance + * + * @author cfu + */ +public class TPSAuthenticator { + private String id; + private IAuthManager authManager; + + /* + * for auths instance ui <locale, value> + * e.g. + * auths.instance.ldap1.ui.description.en= + * This authenticates user against the LDAP directory. + * auths.instance.ldap1.ui.title.en=LDAP Authentication + */ + private HashMap<String, String> uiTitle; + private HashMap<String, String> uiDescription; + + private HashMap<String, AuthUIParameter> uiParameters; + /* + * credMap is for authentication manager required + * credential names (authCred) mapping to the + * client message credentail names (msgCred) + * e.g. + * auths.instance.ldap1.ui.id.UID.credMap.authCred=uid + * auths.instance.ldap1.ui.id.UID.credMap.msgCred=screen_name + * auths.instance.ldap1.ui.id.PASSWORD.credMap.authCred=pwd + * auths.instance.ldap1.ui.id.PASSWORD.credMap.msgCred=password + */ + private HashMap<String, String> credMap; + + // retries if the user entered the wrong password/securid + private int maxLoginRetries = 1; + + /* + * Authentication constructor + * @param authId authentication instance id + */ + public TPSAuthenticator(String authId) + throws EBaseException { + id = authId; + // retrieves and set authentication manager + IAuthSubsystem authSub = + (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + authManager = authSub.getAuthManager(authId); + uiTitle = new HashMap<String, String>(); + uiDescription = new HashMap<String, String>(); + uiParameters = new HashMap<String, AuthUIParameter>(); + credMap = new HashMap<String, String>(); + } + + public String getID() { + return id; + } + + public IAuthManager getAuthManager() { + return authManager; + } + + public void setUiTitle(String locale, String title) { + uiTitle.put(locale, title); + } + + public String getUiTitle(String locale) { + return uiTitle.get(locale); + } + + public void setUiDescription(String locale, String desc) { + uiDescription.put(locale, desc); + } + + public String getUiDescription(String locale) { + return uiDescription.get(locale); + } + + public void setUiParam(String id, AuthUIParameter up) { + uiParameters.put(id, up); + } + + public AuthUIParameter getUiParam(String id) { + return uiParameters.get(id); + } + + public HashMap<String, AuthUIParameter> getUiParamSet() { + return uiParameters; + } + + public void setCredMap(String authCred, String msgCred) { + credMap.put(authCred, msgCred); + } + + public String getCredMap(String authCred) { + return credMap.get(authCred); + } + + public int getNumOfRetries() { + return maxLoginRetries; + } + + public void setNumOfRetries(int num) { + maxLoginRetries = num; + } +} diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java index f054b7e64..ede210c57 100644 --- a/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java +++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/processor/TPSProcessor.java @@ -21,10 +21,15 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import org.dogtagpki.server.tps.TPSSession; import org.dogtagpki.server.tps.TPSSubsystem; +import org.dogtagpki.server.tps.authentication.AuthUIParameter; +import org.dogtagpki.server.tps.authentication.TPSAuthenticator; import org.dogtagpki.server.tps.channel.SecureChannel; import org.dogtagpki.server.tps.cms.TKSComputeRandomDataResponse; import org.dogtagpki.server.tps.cms.TKSComputeSessionKeyResponse; @@ -42,13 +47,21 @@ import org.dogtagpki.tps.main.TPSBuffer; import org.dogtagpki.tps.main.TPSException; import org.dogtagpki.tps.msg.BeginOp; import org.dogtagpki.tps.msg.EndOp.TPSStatus; +import org.dogtagpki.tps.msg.ExtendedLoginRequest; +import org.dogtagpki.tps.msg.ExtendedLoginResponse; +import org.dogtagpki.tps.msg.LoginRequest; +import org.dogtagpki.tps.msg.LoginResponse; import org.dogtagpki.tps.msg.StatusUpdateRequest; +import org.dogtagpki.tps.msg.TPSMessage; import org.dogtagpki.tps.msg.TokenPDURequest; import org.dogtagpki.tps.msg.TokenPDUResponse; import org.mozilla.jss.CryptoManager.NotInitializedException; import org.mozilla.jss.pkcs11.PK11SymKey; import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthCredentials; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthToken; import com.netscape.certsrv.base.EBaseException; import com.netscape.certsrv.base.EPropertyNotFound; import com.netscape.certsrv.base.IConfigStore; @@ -561,6 +574,237 @@ public class TPSProcessor { return contents; } + /** + * getAuthentication gets Authentication per configuration + * + * @param prefix config prefix for tokenType + * @param tokenType the tokenType(profile) + * @return Authentication + */ + public TPSAuthenticator getAuthentication(String prefix, String tokenType) + throws EBaseException { + CMS.debug("TPSProcessor.getAuthentication"); + if (prefix.isEmpty() || tokenType.isEmpty()) { + CMS.debug("TPSProcessor.getAuthentication: missing parameters: prefix or tokenType"); + throw new EBaseException("TPSProcessor.getAuthentication: missing parameters: prefix or tokenType"); + } + IConfigStore configStore = CMS.getConfigStore(); + String configName = prefix + "." + tokenType + ".auth.id"; + String authId; + + CMS.debug("TPSProcessor.getAuthentication: getting config: " + + configName); + authId = configStore.getString(configName); + + TPSSubsystem subsystem = + (TPSSubsystem) CMS.getSubsystem(TPSSubsystem.ID); + TPSAuthenticator authInst = + subsystem.getAuthenticationManager().getAuthInstance(authId); + return authInst; + } + + /** + * authenticateUser authenticates a user using specified authentication + * + * @param op "enrollment", "format", or "pinReset" //TODO: for tokendb activity log + * @param prefix "op.enroll", "op.format", or "op.pinReset" + * @param tokenType the profile name + * @param userCred IAuthCredentials obtained from a successful requestUserId call + */ + public void authenticateUser( + String op, + TPSAuthenticator userAuth, + IAuthCredentials userCred) + throws EBaseException, TPSException { + /** + * TODO: isExternalReg is not handled until decision made + */ + CMS.debug("TPSProcessor.authenticateUser"); + if (op.isEmpty() || userAuth == null || userCred == null) { + CMS.debug("TPSProcessor.authenticateUser: missing parameter(s): op, userAuth, or userCred"); + throw new EBaseException("TPSProcessor.getAuthentication: missing parameter(s): op, userAuth, or userCred"); + } + IAuthManager auth = userAuth.getAuthManager(); + + try { + // Authenticate user + IAuthToken aToken = auth.authenticate(userCred); + if (aToken != null) + CMS.debug("TPSProcessor.authenticateUser: authentication success"); + else { + CMS.debug("TPSProcessor.authenticateUser: authentication failure with aToken null"); + throw new TPSException("TPS error user authentication failed.", + TPSStatus.STATUS_ERROR_LOGIN); + } + } catch (EBaseException e) { + CMS.debug("TPSProcessor.authenticateUser: authentication failure:" + e); + throw new TPSException("TPS error user authentication failed.", + TPSStatus.STATUS_ERROR_LOGIN); + } + } + + /** + * requestUserId sends message to client to request for user credential + * per authentication plugin + * + * @param op "enrollment", "format", or "pinReset" //TODO: for tokendb activity log + * @param cuid token CUID //TODO: for tokendb activity log + * @param extensions message extensions + * @return IAuthCredentials containing user credential needed for authentication + */ + IAuthCredentials requestUserId(String op, String cuid, TPSAuthenticator auth, Map<String, String> extensions) + throws IOException, TPSException, EBaseException { + CMS.debug("TPSProcessor.requestUserId"); + if (op.isEmpty() || + cuid.isEmpty() || auth == null || extensions == null) { + CMS.debug("TPSProcessor.requestUserId: missing parameter(s): op, cuid, auth, or extensions"); + throw new EBaseException("TPSProcessor.requestUserId: missing parameter(s): op, cuid, auth, or extensions"); + } + + IAuthCredentials login; + if (extensions != null && + extensions.get("extendedLoginRequest") != null) { + // default locale will be "en" + String locale = extensions.get("locale"); + if (extensions.get("locale") == null) { + locale = "en"; + } + // title + String title = auth.getUiTitle(locale); + if (title.isEmpty()) + title = auth.getUiTitle("en"); + // description + String description = auth.getUiDescription(locale); + if (description.isEmpty()) + description = auth.getUiTitle("en"); + // parameters + HashMap<String, AuthUIParameter> authParamSet = auth.getUiParamSet(); + Set<String> params = new HashSet<String>(); + for (Map.Entry<String, AuthUIParameter> entry: authParamSet.entrySet()) { + params.add(auth.getUiParam(entry.getKey()).toString(locale)); + CMS.debug("TPSProcessor.requestUserId: for extendedLoginRequest, added param: " + + auth.getUiParam(entry.getKey()).toString(locale)); + } + + login = requestExtendedLogin(0 /* invalid_pw */, 0 /* blocked */, + params, title, description, auth); + } else { + login = requestLogin(0 /* invalid_pw */, 0 /* blocked */, auth); + } + + return login; + } + + /** + * mapCredFromMsgResponse fills up authManager required auth credentials + * with mapped values from client + * configuration example: + * + * auths.instance.ldap1.ui.id.UID.credMap.msgCred=screen_name + * auths.instance.ldap1.ui.id.UID.credMap.authCred=uid + * + * auths.instance.ldap1.ui.id.PASSWORD.credMap.msgCred=password + * auths.instance.ldap1.ui.id.PASSWORD.credMap.authCred=pwd + * + * @param response the message response to be mapped + * @param auth the authentication for mapping consultation + * @return IAuthCredentials auth credential for auth manager + */ + public IAuthCredentials mapCredFromMsgResponse(TPSMessage response, TPSAuthenticator auth) + throws EBaseException { + CMS.debug("TPSProcessor.mapCredFromMsgResponse"); + if (response == null || auth == null) { + CMS.debug("TPSProcessor.mapCredFromMsgResponse: missing parameter(s): response or auth"); + throw new EBaseException("TPSProcessor.mapCredFromMsgResponse: missing parameter(s): response or auth"); + } + IAuthCredentials login = + new com.netscape.certsrv.authentication.AuthCredentials(); + + String[] requiredCreds = auth.getAuthManager().getRequiredCreds(); + for (String cred : requiredCreds) { + String name = auth.getCredMap(cred); + login.set(cred, response.get(name)); + } + + return login; + } + + /** + * Requests login ID and password from user. + */ + public IAuthCredentials requestExtendedLogin(int invalidPW, int blocked, + Set<String> parameters, + String title, + String description, + TPSAuthenticator auth) + throws IOException, TPSException, EBaseException { + + CMS.debug("TPSProcessor.requestExtendedLogin"); + if (parameters == null || title.isEmpty() || + description.isEmpty() || auth == null) { + CMS.debug("TPSProcessor.requestExtendedLogin: missing parameter(s): parameters, title, description, or auth"); + throw new EBaseException( + "TPSProcessor.requestExtendedLogin: missing parameter(s): parameters, title, description, or auth"); + } + ExtendedLoginRequest loginReq = + new ExtendedLoginRequest(invalidPW, blocked, parameters, title, description); + + try { + session.write(loginReq); + } catch (IOException e) { + CMS.debug("TPSProcessor.requestExtendedLogin failed WriteMsg: " + e.toString()); + throw e; + } + CMS.debug("TPSProcessor.requestExtendedLogin: extendedLoginRequest sent"); + + ExtendedLoginResponse loginResp = null; + try { + loginResp = (ExtendedLoginResponse) session.read(); + } catch (IOException e) { + CMS.debug("TPSProcessor.requestExtendedLogin failed ReadMsg: " + e.toString()); + throw e; + } + + IAuthCredentials login = mapCredFromMsgResponse(loginResp, auth); + + return login; + } + + /** + * Requests login ID and password from user. + */ + public IAuthCredentials requestLogin(int invalidPW, int blocked, + TPSAuthenticator auth) + throws IOException, TPSException, EBaseException { + + CMS.debug("TPSProcessor.requestLogin"); + if (auth == null) { + CMS.debug("TPSProcessor.requestLogin: missing parameter(s): parameters, title, description, or auth"); + throw new EBaseException( + "TPSProcessor.requestLogin: missing parameter(s): parameters, title, description, or auth"); + } + LoginRequest loginReq = new LoginRequest(invalidPW, blocked); + + try { + session.write(loginReq); + } catch (IOException e) { + CMS.debug("TPSProcessor.requestLogin failed WriteMsg: " + e.toString()); + throw e; + } + CMS.debug("TPSProcessor.requestLogin: loginRequest sent"); + + LoginResponse loginResp = null; + try { + loginResp = (LoginResponse) session.read(); + } catch (IOException e) { + CMS.debug("TPSProcessor.requestLogin failed ReadMsg: " + e.toString()); + throw e; + } + + IAuthCredentials login = mapCredFromMsgResponse(loginResp, auth); + return login; + } + protected void format() throws TPSException, IOException { IConfigStore configStore = CMS.getConfigStore(); @@ -585,7 +829,7 @@ public class TPSProcessor { TPSEngine.CFG_DEF_NETKEY_INSTANCE_AID); CMS.debug("In TPS_Processor.Format. CardManagerAID: " + CardManagerAID + " NetKeyAID: " + NetKeyAID); this.isExternalReg = configStore.getBoolean(External_Reg_Cfg, false); - CMS.debug("In TPS_Processor.Format isExternalReg: " + isExternalReg); + CMS.debug("In TPSProcessor.format isExternalReg: " + isExternalReg); } catch (EBaseException e1) { CMS.debug("TPS_Processor.Format: Internal Error obtaining mandatory config values. Error: " + e1); throw new TPSException("TPS error getting config values from config store.", @@ -638,16 +882,52 @@ public class TPSProcessor { CMS.debug("TPSProcessor.format: major_version " + major_version + " minor_version: " + minor_version + " app_major_version: " + app_major_version + " app_minor_version: " + app_minor_version); + String tokenType; + IAuthCredentials userCred; if (isExternalReg) { //ToDo, do some external Reg stuff along with authentication + tokenType = "externalRegAddToToken"; } else { - //ToDo, Do some authentication + CMS.debug("In TPSProcessor.format isExternalReg: OFF"); + tokenType = getTokenType(TPSEngine.OP_FORMAT_PREFIX, major_version, minor_version, cuid, msn, + beginMsg.getExtensions()); + + CMS.debug("TPSProcessor.format: calculated tokenType: " + tokenType); + } - String tokenType = getTokenType(TPSEngine.OP_FORMAT_PREFIX, major_version, minor_version, cuid, msn, - beginMsg.getExtensions()); + // isExternalReg : user already authenticated earlier + if (!isExternalReg) { + // authenticate per profile/tokenType configuration + String configName = TPSEngine.OP_FORMAT_PREFIX + "." + tokenType + ".auth.enable"; + boolean isAuthRequired; + try { + CMS.debug("TPSProcessor.format: getting config: " + configName); + isAuthRequired = configStore.getBoolean(configName, true); + } catch (EBaseException e) { + CMS.debug("TPSProcessor.format: Internal Error obtaining mandatory config values. Error: " + e); + throw new TPSException("TPS error getting config values from config store.", + TPSStatus.STATUS_ERROR_MISCONFIGURATION); + } + if (isAuthRequired) { + try { + TPSAuthenticator userAuth = + getAuthentication(TPSEngine.OP_FORMAT_PREFIX, tokenType); + userCred = requestUserId("format", cuid, userAuth, beginMsg.getExtensions()); + authenticateUser("format", userAuth, userCred); + } catch (Exception e) { + // all exceptions are considered login failure + CMS.debug("TPSProcessor.format:: authentication exception thrown: " + e); + throw new TPSException("TPS error user authentication failed.", + TPSStatus.STATUS_ERROR_LOGIN); + } + } + } - CMS.debug("TPS_Processor.format: calculated tokenType: " + tokenType); + /** + * TODO: + * isExternalReg is not handled beyond this point until decided + */ //Now check provided profile |