From fb4283af8d6b52a99199e88b4db0adc84739ae93 Mon Sep 17 00:00:00 2001
From: david_page <david_page@localhost>
Date: Sat, 01 Sep 2007 04:19:31 +0000
Subject: [PATCH] Issue 466 partial.
---
opends/src/ads/org/opends/admin/ads/ADSContext.java | 77 ++++++++++++++++--
opends/src/ads/org/opends/admin/ads/SuffixDescriptor.java | 2
opends/src/ads/org/opends/admin/ads/ServerDescriptor.java | 100 ++++++++++++++++++------
opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java | 26 +++---
4 files changed, 155 insertions(+), 50 deletions(-)
diff --git a/opends/src/ads/org/opends/admin/ads/ADSContext.java b/opends/src/ads/org/opends/admin/ads/ADSContext.java
index 5b76525..608433e 100644
--- a/opends/src/ads/org/opends/admin/ads/ADSContext.java
+++ b/opends/src/ads/org/opends/admin/ads/ADSContext.java
@@ -173,7 +173,7 @@
* belongs to an instance key entry, separate from the server entry and
* named by the ds-cfg-key-id attribute from the server entry.
*/
- INSTANCE_KEY_CERT("ds-cfg-public-key-certificate"/*;binary*/,
+ INSTANCE_PUBLIC_KEY_CERTIFICATE("ds-cfg-public-key-certificate"/*;binary*/,
ADSPropertySyntax.CERTIFICATE_BINARY);
private String attrName;
@@ -418,7 +418,8 @@
try
{
dirContext.createSubcontext(dn, attrs).close();
- if (serverProperties.containsKey(ServerProperty.INSTANCE_KEY_CERT))
+ if (serverProperties.containsKey(
+ ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE))
{
registerInstanceKeyCertificate(serverProperties, dn);
}
@@ -462,7 +463,8 @@
BasicAttributes attrs = makeAttrsFromServerProperties(serverProperties);
dirContext.modifyAttributes(dn, InitialLdapContext.REPLACE_ATTRIBUTE,
attrs);
- if (serverProperties.containsKey(ServerProperty.INSTANCE_KEY_CERT))
+ if (serverProperties.containsKey(
+ ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE))
{
registerInstanceKeyCertificate(serverProperties, dn);
}
@@ -481,7 +483,8 @@
/**
* Method called to unregister a server in the ADS. Note that the server's
- * instance key-pair public-key certificate entry (created in registerServer)
+ * instance key-pair public-key certificate entry (created in
+ * <tt>registerServer()</tt>)
* is left untouched.
* @param serverProperties the properties of the server.
* @throws ADSContextException if the server could not be unregistered.
@@ -1400,7 +1403,7 @@
switch(property)
{
- case INSTANCE_KEY_CERT:
+ case INSTANCE_PUBLIC_KEY_CERTIFICATE:
result = null; // used in separate instance key entry
break;
case GROUPS:
@@ -2017,8 +2020,8 @@
*/
/**
- * Returns the parent entry of the server key entries in ADS.
- * @return the parent entry of the server key entries in ADS.
+ Returns the parent entry of the server key entries in ADS.
+ @return the parent entry of the server key entries in ADS.
*/
private static String getInstanceKeysContainerDN()
{
@@ -2041,8 +2044,10 @@
Map<ServerProperty, Object> serverProperties,
LdapName serverEntryDn) throws NamingException
{
- assert serverProperties.containsKey(ServerProperty.INSTANCE_KEY_CERT);
- if (! serverProperties.containsKey(ServerProperty.INSTANCE_KEY_CERT)) {
+ assert serverProperties.containsKey(
+ ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE);
+ if (! serverProperties.containsKey(
+ ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE)) {
return;
}
@@ -2061,8 +2066,10 @@
ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID));
}
keyAttrs.put(new BasicAttribute(
- ServerProperty.INSTANCE_KEY_CERT.getAttributeName() + ";binary",
- serverProperties.get(ServerProperty.INSTANCE_KEY_CERT)));
+ ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE.getAttributeName()
+ + ";binary",
+ serverProperties.get(
+ ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE)));
/* search for public-key certificate entry in ADS DIT */
final String attrIDs[] = { "ds-cfg-key-id" };
@@ -2076,6 +2083,12 @@
keyID = (String)keyIdAttr.get();
}
}
+ /* TODO: It is possible (but unexpected) that the caller specifies a
+ ds-cfg-key-id value for which there is a certificate entry in ADS, but
+ the certificate value does not match that supplied by the caller. The
+ above search would not return the entry, but the below attempt to add
+ an new entry with the supplied ds-cfg-key-id will fail (throw a
+ NameAlreadyBoundException) */
else {
/* create key ID, if it was not supplied in serverProperties */
if (null == keyID) {
@@ -2098,4 +2111,46 @@
(new BasicAttributes(
ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID)));
}
+
+ /**
+ Return the set of valid (i.e., not tagged as compromised) instance key-pair
+ public-key certificate entries in ADS.
+ @return The set of valid (i.e., not tagged as compromised) instance key-pair
+ public-key certificate entries in ADS represented as a Map from ds-cfg-key-id
+ value to ds-cfg-public-key-certificate;binary value Note that the collection
+ might be empty.
+ @throws ADSContextException in case of problems with the entry search.
+ */
+ public Map<String,byte[]> getTrustedCertificates()
+ throws ADSContextException
+ {
+ Map<String, byte[]> keyEntryMap = new HashMap<String, byte[]>();
+ try {
+ final LdapName baseDN = new LdapName(getInstanceKeysContainerDN());
+ final String searchFilter =
+ "(&(objectclass=ds-cfg-instance-key)(!(ds-cfg-key-compromised-time=*)))";
+ final SearchControls searchControls = new SearchControls();
+ searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
+ final String attrIDs[]= {
+ ADSContext.ServerProperty.INSTANCE_KEY_ID.getAttributeName(),
+ ADSContext.ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE
+ .getAttributeName() + ";binary"};
+ searchControls.setReturningAttributes(attrIDs);
+ NamingEnumeration<SearchResult> keyEntries
+ = dirContext.search(baseDN, searchFilter, searchControls);
+ while (keyEntries.hasMore()) {
+ final SearchResult entry = keyEntries.next();
+ final Attributes attrs = entry.getAttributes();
+ final Attribute keyIDAttr = attrs.get(attrIDs[0]);
+ final Attribute keyCertAttr = attrs.get(attrIDs[1]);
+ if (null == keyIDAttr || null == keyCertAttr) continue; // schema viol.
+ keyEntryMap.put((String)keyIDAttr.get(), (byte[])keyCertAttr.get());
+ }
+ }
+ catch (NamingException x) {
+ throw new ADSContextException(
+ ADSContextException.ErrorType.ERROR_UNEXPECTED, x);
+ }
+ return keyEntryMap;
+ }
}
diff --git a/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java b/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
index b69f3a3..ca818f4 100644
--- a/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
+++ b/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
@@ -37,13 +37,11 @@
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.BasicAttribute;
-import javax.naming.directory.BasicAttributes;
-import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.directory.*;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
import org.opends.admin.ads.util.ConnectionUtils;
@@ -338,6 +336,7 @@
}
catch (Throwable t)
{
+ /* ignore */
}
}
return host + ":" + port;
@@ -481,7 +480,7 @@
}
}
adsProperties.put(ADSContext.ServerProperty.ID, getHostPort(true));
- adsProperties.put(ADSContext.ServerProperty.INSTANCE_KEY_CERT,
+ adsProperties.put(ADSContext.ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE,
getInstancePublicKeyCertificate());
}
@@ -717,6 +716,7 @@
}
catch (NameNotFoundException nse)
{
+ /* ignore */
}
desc.serverProperties.put(ServerProperty.IS_REPLICATION_ENABLED,
replicationEnabled ? Boolean.TRUE : Boolean.FALSE);
@@ -769,6 +769,7 @@
}
catch (NameNotFoundException nse)
{
+ /* ignore */
}
ctls = new SearchControls();
@@ -815,23 +816,22 @@
}
catch (NameNotFoundException nse)
{
+ /* ignore */
}
}
/**
- * Updates the instance key public-key certificate value of this context from
- * the local truststore of the instance bound by this context. Any current
- * value of the certificate is overwritten. The intent of this method is to
- * retrieve the instance-key public-key certificate when this context is bound
- * to an instance, and cache it for later use in registering the instance into
- * ADS.
- *
- * @param desc The map to update with the instance key-pair public-key
- * certificate.
- * @param ctx The bound server instance.
- *
- * @throws NamingException if unable to retrieve certificate from bound
- * instance.
+ Updates the instance key public-key certificate value of this context from
+ the local truststore of the instance bound by this context. Any current
+ value of the certificate is overwritten. The intent of this method is to
+ retrieve the instance-key public-key certificate when this context is bound
+ to an instance, and cache it for later use in registering the instance into
+ ADS.
+ @param desc The map to update with the instance key-pair public-key
+ certificate.
+ @param ctx The bound server instance.
+ @throws NamingException if unable to retrieve certificate from bound
+ instance.
*/
private static void updatePublicKeyCertificate(ServerDescriptor desc,
InitialLdapContext ctx) throws NamingException
@@ -845,12 +845,12 @@
it (which induces the CryptoManager to create the public-key
certificate attribute), then repeat the search. */
try {
- final SearchControls sc = new SearchControls();
- sc.setSearchScope(SearchControls.OBJECT_SCOPE);
+ final SearchControls searchControls = new SearchControls();
+ searchControls.setSearchScope(SearchControls.OBJECT_SCOPE);
final String attrIDs[] = { "ds-cfg-public-key-certificate;binary" };
- sc.setReturningAttributes(attrIDs);
- final SearchResult certEntry
- = ctx.search(dn, "(objectclass=ds-cfg-instance-key)", sc).next();
+ searchControls.setReturningAttributes(attrIDs);
+ final SearchResult certEntry = ctx.search(dn,
+ "(objectclass=ds-cfg-instance-key)", searchControls).next();
final Attribute certAttr = certEntry.getAttributes().get(attrIDs[0]);
if (null != certAttr) {
/* attribute ds-cfg-public-key-certificate is a MUST in the schema */
@@ -864,7 +864,7 @@
if (0 == i) {
/* Poke CryptoManager to initialize truststore. Note the special
attribute in the request. */
- final BasicAttributes attrs = new BasicAttributes();
+ final Attributes attrs = new BasicAttributes();
final Attribute oc = new BasicAttribute("objectclass");
oc.add("top");
oc.add("ds-cfg-self-signed-cert-request");
@@ -878,6 +878,53 @@
}
}
+ /**
+ Seeds the bound instance's local ads-truststore with a set of instance
+ key-pair public key certificates. The result is the instance will trust any
+ instance posessing the private key corresponding to one of the public-key
+ certificates. This trust is necessary at least to initialize replication,
+ which uses the trusted certificate entries in the ads-truststore for server
+ authentication.
+ @param ctx The bound instance.
+ @param keyEntryMap The set of valid (i.e., not tagged as compromised)
+ instance key-pair public-key certificate entries in ADS represented as a map
+ from keyID to public-key certificate (binary).
+ @throws NamingException in case an error occurs while updating the instance's
+ ads-truststore via LDAP.
+ */
+ public static void seedAdsTrustStore(
+ InitialLdapContext ctx,
+ Map<String, byte[]> keyEntryMap)
+ throws NamingException
+ {
+ /* TODO: this DN is declared in some core constants file. Create a
+ constants file for the installer and import it into the core. */
+ final String truststoreDnStr = "cn=ads-truststore";
+ final Attribute oc = new BasicAttribute("objectclass");
+ oc.add("top");
+ oc.add("ds-cfg-instance-key");
+ for (Map.Entry<String, byte[]> keyEntry : keyEntryMap.entrySet()){
+ final BasicAttributes keyAttrs = new BasicAttributes();
+ keyAttrs.put(oc);
+ final Attribute rdnAttr = new BasicAttribute(
+ ADSContext.ServerProperty.INSTANCE_KEY_ID.getAttributeName(),
+ keyEntry.getKey());
+ keyAttrs.put(rdnAttr);
+ keyAttrs.put(new BasicAttribute(
+ ADSContext.ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE.
+ getAttributeName() + ";binary", keyEntry.getValue()));
+ final LdapName keyDn = new LdapName((new StringBuilder(rdnAttr.getID()))
+ .append("=").append(Rdn.escapeValue(rdnAttr.get())).append(",")
+ .append(truststoreDnStr).toString());
+ try {
+ ctx.createSubcontext(keyDn, keyAttrs).close();
+ }
+ catch(NameAlreadyBoundException x){
+ ctx.destroySubcontext(keyDn);
+ ctx.createSubcontext(keyDn, keyAttrs).close();
+ }
+ }
+ }
/**
* Returns the number of entries in a given backend using the provided
@@ -915,7 +962,7 @@
}
catch (Exception ex)
{
-
+ /* ignore */
}
return nEntries;
@@ -972,6 +1019,7 @@
areDnsEqual = name1.equals(name2);
} catch (Exception ex)
{
+ /* ignore */
}
return areDnsEqual;
}
diff --git a/opends/src/ads/org/opends/admin/ads/SuffixDescriptor.java b/opends/src/ads/org/opends/admin/ads/SuffixDescriptor.java
index 8bade66..baaaf92 100644
--- a/opends/src/ads/org/opends/admin/ads/SuffixDescriptor.java
+++ b/opends/src/ads/org/opends/admin/ads/SuffixDescriptor.java
@@ -114,7 +114,7 @@
buf.append(getDN());
for (ReplicaDescriptor replica : getReplicas())
{
- buf.append("-"+replica.getServer().getId());
+ buf.append("-").append(replica.getServer().getId());
}
return buf.toString();
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
index 9995e93..f26e545 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
@@ -1867,9 +1867,9 @@
protected void updateADS() throws ApplicationException
{
DataReplicationOptions repl = getUserData().getReplicationOptions();
- boolean remoteServer =
+ boolean isRemoteServer =
repl.getType() == DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY;
- AuthenticationData auth = (remoteServer) ? repl.getAuthenticationData()
+ AuthenticationData auth = (isRemoteServer) ? repl.getAuthenticationData()
: null;
InitialLdapContext remoteCtx = null; // Bound to remote ADS host (if any).
InitialLdapContext localCtx = null; // Bound to local server.
@@ -1879,7 +1879,7 @@
ADSContextException to ApplicationException and clean up JNDI contexts.*/
try
{
- if (remoteServer)
+ if (isRemoteServer)
{
/* In case the user specified an existing topology... */
String ldapUrl = getLdapUrl(auth);
@@ -1921,7 +1921,7 @@
/* Act on local server depending on if using remote or local ADS */
notifyListeners(getFormattedWithPoints(INFO_PROGRESS_CREATING_ADS.get()));
localCtx = createLocalContext();
- if (remoteServer)
+ if (isRemoteServer)
{
/* Create an empty ADS suffix on the local server. */
ADSContext localAdsContext = new ADSContext(localCtx);
@@ -1938,14 +1938,16 @@
/* Register new server in ADS. */
ServerDescriptor server = ServerDescriptor.createStandalone(localCtx);
server.updateAdsPropertiesWithServerProperties();
- if (0 != adsContext.registerOrUpdateServer(server.getAdsProperties()))
- {
+ if (0 == adsContext.registerOrUpdateServer(server.getAdsProperties())) {
+ if (isRemoteServer) registeredNewServerOnRemote = true;
+ } else {
LOG.log(Level.WARNING, "Server was already registered. Updating " +
"server registration.");
}
- else if (remoteServer)
+ if (isRemoteServer)
{
- registeredNewServerOnRemote = true;
+ ServerDescriptor.seedAdsTrustStore(localCtx,
+ adsContext.getTrustedCertificates());
}
notifyListeners(getFormattedDone());
notifyListeners(getLineBreak());
@@ -1960,7 +1962,7 @@
INFO_PROGRESS_CREATING_ADMINISTRATOR.get()));
adsContext.createAdministrator(getAdministratorProperties(
getUserData()));
- if (remoteServer && !createdRemoteAds) createdAdministrator = true;
+ if (isRemoteServer && !createdRemoteAds) createdAdministrator = true;
notifyListeners(getFormattedDone());
notifyListeners(getLineBreak());
checkAbort();
@@ -1982,7 +1984,7 @@
}
catch (NoPermissionException ne)
{
- if (remoteServer)
+ if (isRemoteServer)
{
throw new ApplicationException(
ReturnCode.CONFIGURATION_ERROR,
@@ -2001,7 +2003,7 @@
}
catch (NamingException ne)
{
- if (remoteServer)
+ if (isRemoteServer)
{
throw new ApplicationException(
ReturnCode.CONFIGURATION_ERROR,
@@ -2019,7 +2021,7 @@
{
throw new ApplicationException(
ReturnCode.CONFIGURATION_ERROR,
- ((remoteServer)
+ ((isRemoteServer)
? INFO_REMOTE_ADS_EXCEPTION.get(
getHostDisplay(auth), ace.getReason())
: INFO_ADS_EXCEPTION.get(ace.toString())), ace);
--
Gitblit v1.10.0