Skip to content

Commit

Permalink
Fixes to cloning and security domain tables for client auth internald…
Browse files Browse the repository at this point in the history
…b user

The mechanism for getting an ldap connection to the internaldb was incorrect,
both in the Security Domain Session Table and the DatabasePanel.  As a result,
connections to the internaldb failed for accessing the security domain session
table and when trying to clone a master which connects to its database using
client auth.

The thread that handles reading the security domain session table is now only
instantiated when running on a configured security domain master.

Additionally, needed acls for the client auth certificate ldap user have been
moved to manager.ldif.  This includes acls to allow creation and management of
replication agreements and replication users (now being created under
ou=csusers, cn=config)

Added logs to show when ldif import errors occur.  Also made sure to write and
remove master ldap password for use in replication.

Ticket #5

Conflicts resolved:

	pki/base/common/src/com/netscape/cms/servlet/csadmin/AdminAuthenticatePanel.java
	pki/base/common/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java
	pki/base/common/src/com/netscape/cms/servlet/csadmin/LDAPSecurityDomainSessionTable.java
	pki/base/common/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java
	pki/base/common/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java
	pki/base/migrate/80/MigrateSecurityDomain.java
	pki/base/util/src/com/netscape/cmsutil/ldap/LDAPUtil.java
  • Loading branch information
vakwetu committed Mar 9, 2012
1 parent 8b9dc39 commit ada9213
Show file tree
Hide file tree
Showing 16 changed files with 380 additions and 209 deletions.
1 change: 1 addition & 0 deletions pki/base/ca/shared/conf/CS.cfg.in
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,7 @@ preop.internaldb.schema.ldif=/usr/share/[PKI_FLAVOR]/ca/conf/schema.ldif
preop.internaldb.ldif=/usr/share/[PKI_FLAVOR]/ca/conf/database.ldif
preop.internaldb.data_ldif=/usr/share/[PKI_FLAVOR]/ca/conf/db.ldif,/usr/share/[PKI_FLAVOR]/ca/conf/acl.ldif
preop.internaldb.index_ldif=
preop.internaldb.manager_ldif=/usr/share/[PKI_FLAVOR]/ca/conf/manager.ldif
preop.internaldb.post_ldif=/usr/share/[PKI_FLAVOR]/ca/conf/index.ldif,/usr/share/[PKI_FLAVOR]/ca/conf/vlv.ldif,/usr/share/[PKI_FLAVOR]/ca/conf/vlvtasks.ldif
preop.internaldb.wait_dn=cn=index1160589769, cn=index, cn=tasks, cn=config
internaldb.multipleSuffix.enable=false
Expand Down
48 changes: 48 additions & 0 deletions pki/base/ca/shared/conf/manager.ldif
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# acis for cert manager

dn: ou=csusers,cn=config
objectClass: top
objectClass: organizationalUnit
ou: csusers

dn: {rootSuffix}
changetype: modify
add: aci
aci: (targetattr=*)(version 3.0; acl "cert manager access"; allow (all) userdn = "ldap:///{dbuser}";)

dn: cn=ldbm database,cn=plugins,cn=config
changetype: modify
add: aci
aci: (targetattr=*)(version 3.0; acl "Cert Manager access for VLV searches"; allow (read) userdn="ldap:///{dbuser}";)

dn: cn=config
changetype: modify
add: aci
aci: (targetattr != aci)(version 3.0; aci "cert manager read access"; allow (read, search, compare) userdn = "ldap:///{dbuser}";)

dn: ou=csusers,cn=config
changetype: modify
add: aci
aci: (targetattr != aci)(version 3.0; aci "cert manager manage replication users"; allow (all) userdn = "ldap:///{dbuser}";)

dn: cn="{rootSuffix}",cn=mapping tree,cn=config
changetype: modify
add: aci
aci: (targetattr=*)(version 3.0;acl "cert manager: Add Replication Agreements";allow (add) userdn = "ldap:///{dbuser}";)

dn: cn="{rootSuffix}",cn=mapping tree,cn=config
changetype: modify
add: aci
aci: (targetattr=*)(targetfilter="(|(objectclass=nsds5Replica)(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement)(objectClass=nsMappingTree))")(version 3.0; acl "cert manager: Modify Replication Agreements"; allow (read, write, search) userdn = "ldap:///{dbuser}";)

dn: cn="{rootSuffix}",cn=mapping tree,cn=config
changetype: modify
add: aci
aci: (targetattr=*)(targetfilter="(|(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement))")(version 3.0;acl "cert manager: Remove Replication Agreements";allow (delete) userdn = "ldap:///{dbuser}";)

dn: cn=tasks,cn=config
changetype: modify
add: aci
aci: (targetattr=*)(version 3.0; acl "cert manager: Run tasks after replica re-initialization"; allow (add) userdn = "ldap:///{dbuser}";)


Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,13 @@ public void update(HttpServletRequest request,
if (!cstype.equals("ca")) {
c1.append(",preop.ca.hostname,preop.ca.httpport,preop.ca.httpsport,preop.ca.list,preop.ca.pkcs7,preop.ca.type");
}

String content = "uid="+uid+"&pwd="+pwd+"&op=get&names=cloning.module.token,instanceId,internaldb.basedn,internaldb.ldapauth.password,internaldb.replication.password,internaldb.ldapconn.host,internaldb.ldapconn.port,internaldb.ldapauth.bindDN"+c1.toString()+"&substores="+s1.toString();
s1.append(",internaldb,internaldb.ldapauth,internaldb.ldapconn");
String content =
"uid=" + uid
+ "&pwd=" + pwd
+ "&op=get&names=cloning.module.token,instanceId,"
+ "internaldb.ldapauth.password,internaldb.replication.password"
+ c1.toString() + "&substores=" + s1.toString();

boolean success = updateConfigEntries(host, httpsport, true,
"/"+cstype+"/admin/"+cstype+"/getConfigEntries", content, config,
Expand Down
197 changes: 100 additions & 97 deletions pki/base/common/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
package com.netscape.cms.servlet.csadmin;

import java.util.*;
import java.io.*;
import com.netscape.certsrv.base.*;
import com.netscape.certsrv.apps.*;
import netscape.ldap.*;
import com.netscape.cmsutil.password.*;
import com.netscape.certsrv.ldap.ELdapException;
import com.netscape.certsrv.ldap.ILdapConnFactory;

/**
* This object stores the values for IP, uid and group based on the cookie id in LDAP.
Expand All @@ -32,9 +32,14 @@ public class LDAPSecurityDomainSessionTable
implements ISecurityDomainSessionTable {

private long m_timeToLive;
private ILdapConnFactory mLdapConnFactory = null;

public LDAPSecurityDomainSessionTable(long timeToLive) {
public LDAPSecurityDomainSessionTable(long timeToLive) throws ELdapException, EBaseException {
m_timeToLive = timeToLive;
IConfigStore cs = CMS.getConfigStore();
IConfigStore internaldb = cs.getSubStore("internaldb");
mLdapConnFactory = CMS.getLdapBoundConnFactory();
mLdapConnFactory.init(internaldb);
}

public int addEntry(String sessionId, String ip,
Expand All @@ -56,7 +61,7 @@ public int addEntry(String sessionId, String ip,

try {
// create session entry (if it does not exist)
conn = getLDAPConn();
conn = mLdapConnFactory.getConn();

LDAPEntry entry = null;
LDAPAttributeSet attrs = null;
Expand Down Expand Up @@ -100,7 +105,7 @@ public int addEntry(String sessionId, String ip,
}

try {
conn.disconnect();
mLdapConnFactory.returnConn(conn);
} catch (Exception e) {
CMS.debug("SecurityDomainSessionTable:addEntry: Error in disconnecting from database: " + e);
}
Expand All @@ -114,7 +119,7 @@ public int removeEntry(String sessionId) {
try {
String basedn = cs.getString("internaldb.basedn");
String dn = "cn=" + sessionId + ",ou=sessions,ou=Security Domain," + basedn;
conn = getLDAPConn();
conn = mLdapConnFactory.getConn();
conn.delete(dn);
status = SUCCESS;
} catch (Exception e) {
Expand All @@ -125,7 +130,7 @@ public int removeEntry(String sessionId) {
}
}
try {
conn.disconnect();
mLdapConnFactory.returnConn(conn);
} catch (Exception e) {
CMS.debug("SecurityDomainSessionTable: removeEntry: Error in disconnecting from database: " + e);
}
Expand All @@ -142,15 +147,15 @@ public boolean isSessionIdExist(String sessionId) {
String filter = "(cn=" + sessionId + ")";
String[] attrs = { "cn" };

conn = getLDAPConn();
conn = mLdapConnFactory.getConn();
LDAPSearchResults res = conn.search(sessionsdn, LDAPv2.SCOPE_SUB, filter, attrs, false);
if (res.getCount() > 0) ret = true;
} catch(Exception e) {
CMS.debug("SecurityDomainSessionTable: unable to query session " + sessionId + ": " + e);
}

try {
conn.disconnect();
mLdapConnFactory.returnConn(conn);
} catch (Exception e) {
CMS.debug("SecurityDomainSessionTable: isSessionIdExist: Error in disconnecting from database: " + e);
}
Expand All @@ -169,7 +174,7 @@ public Enumeration getSessionIds() {
String filter = "(objectclass=securityDomainSessionEntry)";
String[] attrs = { "cn" };

conn = getLDAPConn();
conn = mLdapConnFactory.getConn();
LDAPSearchResults res = conn.search(sessionsdn, LDAPv2.SCOPE_SUB, filter, attrs, false);
while (res.hasMoreElements()) {
LDAPEntry entry = res.next();
Expand All @@ -188,7 +193,7 @@ public Enumeration getSessionIds() {
}

try {
conn.disconnect();
mLdapConnFactory.returnConn(conn);
} catch (Exception e) {
CMS.debug("SecurityDomainSessionTable: getSessionIds: Error in disconnecting from database: " + e);
}
Expand All @@ -205,7 +210,7 @@ private String getStringValue(String sessionId, String attr) {
String sessionsdn = "ou=sessions,ou=Security Domain," + basedn;
String filter = "(cn=" + sessionId + ")";
String[] attrs = { attr };
conn = getLDAPConn();
conn = mLdapConnFactory.getConn();
LDAPSearchResults res = conn.search(sessionsdn, LDAPv2.SCOPE_SUB, filter, attrs, false);
if (res.getCount() > 0) {
LDAPEntry entry = res.next();
Expand All @@ -216,7 +221,7 @@ private String getStringValue(String sessionId, String attr) {
}

try {
conn.disconnect();
mLdapConnFactory.returnConn(conn);
} catch (Exception e) {
CMS.debug("SecurityDomainSessionTable: isSessionIdExist: Error in disconnecting from database: " + e);
}
Expand Down Expand Up @@ -258,87 +263,19 @@ public int getSize() {
String filter = "(objectclass=securityDomainSessionEntry)";
String[] attrs = { "cn" };

conn = getLDAPConn();
conn = mLdapConnFactory.getConn();
LDAPSearchResults res = conn.search(sessionsdn, LDAPv2.SCOPE_SUB, filter, attrs, false);
ret = res.getCount();
} catch(Exception e) {
CMS.debug("SecurityDomainSessionTable: unable to query sessionIds: " + e);
}

try {
conn.disconnect();
mLdapConnFactory.returnConn(conn);
} catch (Exception e) {
CMS.debug("SecurityDomainSessionTable: getSessionIds: Error in disconnecting from database: " + e);
}

return ret;
}

private LDAPConnection getLDAPConn()
throws IOException
{
IConfigStore cs = CMS.getConfigStore();

String host = "";
String port = "";
String pwd = null;
String binddn = "";
String security = "";
String clientNick = "";

IPasswordStore pwdStore = CMS.getPasswordStore();

if (pwdStore != null) {
//CMS.debug("SecurityDomainSessionTable: getLDAPConn: password store available");
pwd = pwdStore.getPassword("internaldb");
}

if ( pwd == null) {
throw new IOException("SecurityDomainSessionTable: Failed to obtain password from password store");
}

try {
host = cs.getString("internaldb.ldapconn.host");
port = cs.getString("internaldb.ldapconn.port");
binddn = cs.getString("internaldb.ldapauth.bindDN");
security = cs.getString("internaldb.ldapconn.secureConn");
clientNick = cs.getString("internaldb.ldapauth.clientCertNickname");
} catch (Exception e) {
CMS.debug("SecurityDomainSessionTable: getLDAPConn" + e.toString());
throw new IOException(
"Failed to retrieve LDAP information from CS.cfg.");
}

int p = -1;

try {
p = Integer.parseInt(port);
} catch (Exception e) {
CMS.debug("SecurityDomainSessionTable getLDAPConn: " + e.toString());
throw new IOException("Port is not valid");
}

LDAPConnection conn = null;
if (!clientNick.equals("")) {
CMS.debug("SecurityDomainSessionTable getLDAPConn: creating secure (SSL) client auth connection for internal ldap");
conn = new LDAPConnection(CMS.getLdapJssSSLSocketFactory(clientNick));
} else if (security.equals("true")) {
//CMS.debug("SecurityDomainSessionTable getLDAPConn: creating secure (SSL) connection for internal ldap");
conn = new LDAPConnection(CMS.getLdapJssSSLSocketFactory());
} else {
//CMS.debug("SecurityDomainSessionTable getLDAPConn: creating non-secure (non-SSL) connection for internal ldap");
conn = new LDAPConnection();
}

//CMS.debug("SecurityDomainSessionTable connecting to " + host + ":" + p);
try {
conn.connect(host, p, binddn, pwd);
} catch (LDAPException e) {
CMS.debug("SecurityDomainSessionTable getLDAPConn: " + e.toString());
throw new IOException("Failed to connect to the internal database.");
}

return conn;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,15 @@ private void getConfigEntriesFromMaster(HttpServletRequest request,
s1.append(",");
s1.append("ca.connector.KRA");
}

content = "op=get&names=cloning.token,instanceId,internaldb.basedn,internaldb.ldapauth.password,internaldb.replication.password,internaldb.ldapconn.host,internaldb.ldapconn.port,internaldb.ldapauth.bindDN"+c1.toString()+"&substores="+s1.toString()+"&xmlOutput=true&sessionID="+session_id;

s1.append(",internaldb,internaldb.ldapauth,internaldb.ldapconn");

content =
"op=get&names=cloning.token,instanceId,internaldb.basedn,internaldb.ldapauth.password,"
+ "internaldb.replication.password" + c1.toString()
+ "&substores=" + s1.toString()
+ "&xmlOutput=true&sessionID="
+ session_id;
boolean success = updateConfigEntries(master_hostname, master_port, true,
"/"+cstype+"/admin/"+cstype+"/getConfigEntries", content, config, response);
if (!success) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -601,19 +601,11 @@ public boolean updateConfigEntries(String hostname, int port, boolean https,
}
}

if (name.equals("internaldb.ldapconn.host")) {
config.putString("preop.internaldb.master.hostname", v);
} else if (name.equals("internaldb.ldapconn.port")) {
config.putString("preop.internaldb.master.port", v);
} else if (name.equals("internaldb.ldapauth.bindDN")) {
config.putString("preop.internaldb.master.binddn", v);
} else if (name.equals("internaldb.basedn")) {
if (name.equals("internaldb.basedn")) {
config.putString(name, v);
config.putString("preop.internaldb.master.basedn", v);
} else if (name.equals("internaldb.ldapauth.password")) {
config.putString("preop.internaldb.master.bindpwd", v);
} else if (name.equals("internaldb.replication.password")) {
config.putString("preop.internaldb.master.replicationpwd", v);
config.putString("preop.internaldb.master.basedn", v);
} else if (name.startsWith("internaldb")) {
config.putString(name.replaceFirst("internaldb", "preop.internaldb.master"), v);
} else if (name.equals("instanceId")) {
config.putString("preop.master.instanceId", v);
} else if (name.equals("cloning.cert.signing.nickname")) {
Expand Down Expand Up @@ -662,6 +654,23 @@ public boolean updateConfigEntries(String hostname, int port, boolean https,
}
}

// set master ldap password (if it exists) temporarily in password store
// in case it is needed for replication. Not stored in password.conf.
try {
String master_pwd = config.getString("preop.internaldb.master.ldapauth.password", "");
if (!master_pwd.equals("")) {
config.putString("preop.internaldb.master.ldapauth.bindPWPrompt", "master_internaldb");
String passwordFile = config.getString("passwordFile");
IConfigStore psStore = CMS.createFileConfigStore(passwordFile);
psStore.putString("master_internaldb", master_pwd);
psStore.commit(false);
}
} catch (Exception e) {
CMS.debug("updateConfigEntries: Failed to temporarily store master bindpwd: " + e.toString());
e.printStackTrace();
throw new IOException(e.toString());
}

return true;
} else if (status.equals(AUTH_FAILURE)) {
reloginSecurityDomain(response);
Expand Down
23 changes: 12 additions & 11 deletions pki/base/common/src/com/netscape/cmscore/apps/CMSEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -261,18 +261,19 @@ public void init(ISubsystem owner, IConfigStore config)
String secdomain_source = config.getString("securitydomain.source", "memory");
String secdomain_check_interval = config.getString("securitydomain.checkinterval", "5000");

if (secdomain_source.equals("ldap")) {
mSecurityDomainSessionTable = new LDAPSecurityDomainSessionTable((new Long(flush_timeout)).longValue());
} else {
mSecurityDomainSessionTable = new SecurityDomainSessionTable((new Long(flush_timeout)).longValue());
}
if ((state == 1) && (!sd.equals("existing"))) {
// check session domain table only if this is a
// configured security domain host

if (secdomain_source.equals("ldap")) {
mSecurityDomainSessionTable = new LDAPSecurityDomainSessionTable((new Long(flush_timeout)).longValue());
} else {
mSecurityDomainSessionTable = new SecurityDomainSessionTable((new Long(flush_timeout)).longValue());
}

mSDTimer = new Timer();
SessionTimer timertask = new SessionTimer(mSecurityDomainSessionTable);

mSDTimer = new Timer();
SessionTimer timertask = new SessionTimer(mSecurityDomainSessionTable);
if ((state != 1) || (sd.equals("existing"))) {
// for non-security domain hosts or if not yet configured,
// do not check session domain table
} else {
mSDTimer.schedule(timertask, 5, (new Long(secdomain_check_interval)).longValue());
}

Expand Down
1 change: 1 addition & 0 deletions pki/base/kra/shared/conf/CS.cfg.in
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ preop.internaldb.schema.ldif=/usr/share/[PKI_FLAVOR]/kra/conf/schema.ldif
preop.internaldb.ldif=/usr/share/[PKI_FLAVOR]/kra/conf/database.ldif
preop.internaldb.data_ldif=/usr/share/[PKI_FLAVOR]/kra/conf/db.ldif,/usr/share/[PKI_FLAVOR]/kra/conf/acl.ldif
preop.internaldb.index_ldif=
preop.internaldb.manager_ldif=/usr/share/[PKI_FLAVOR]/ca/conf/manager.ldif
preop.internaldb.post_ldif=/usr/share/[PKI_FLAVOR]/kra/conf/index.ldif,/usr/share/[PKI_FLAVOR]/kra/conf/vlv.ldif,/usr/share/[PKI_FLAVOR]/kra/conf/vlvtasks.ldif
preop.internaldb.wait_dn=cn=index1160527115, cn=index, cn=tasks, cn=config
internaldb.multipleSuffix.enable=false
Expand Down

0 comments on commit ada9213

Please sign in to comment.