| opends/resource/config/config.ldif | ●●●●● patch | view | raw | blame | history | |
| opends/src/messages/messages/core.properties | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/core/CryptoManagerSync.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/core/DirectoryServer.java | ●●●●● patch | view | raw | blame | history | |
| opends/src/server/org/opends/server/types/CryptoManager.java | ●●●●● patch | view | raw | blame | history |
opends/resource/config/config.ldif
@@ -67,7 +67,7 @@ objectClass: top objectClass: ds-cfg-access-control-handler objectClass: ds-cfg-dsee-compat-access-control-handler ds-cfg-global-aci: (extop="1.3.6.1.4.1.26027.1.6.1 || 1.3.6.1.4.1.4203.1.11.1 || 1.3.6.1.4.1.1466.20037 || 1.3.6.1.4.1.4203.1.11.3") (version 3.0; acl "Anonymous extended operation access"; allow(read) userdn="ldap:///anyone";) ds-cfg-global-aci: (extop="1.3.6.1.4.1.26027.1.6.1 || 1.3.6.1.4.1.26027.1.6.3 || 1.3.6.1.4.1.4203.1.11.1 || 1.3.6.1.4.1.1466.20037 || 1.3.6.1.4.1.4203.1.11.3") (version 3.0; acl "Anonymous extended operation access"; allow(read) userdn="ldap:///anyone";) ds-cfg-global-aci: (targetcontrol="2.16.840.1.113730.3.4.2 || 2.16.840.1.113730.3.4.17 || 2.16.840.1.113730.3.4.19 || 1.3.6.1.4.1.4203.1.10.2 || 1.3.6.1.4.1.42.2.27.8.5.1 || 2.16.840.1.113730.3.4.16") (version 3.0; acl "Anonymous control access"; allow(read) userdn="ldap:///anyone";) ds-cfg-global-aci: (targetattr!="userPassword||authPassword")(version 3.0; acl "Anonymous read access"; allow (read,search,compare) userdn="ldap:///anyone";) ds-cfg-global-aci: (targetattr="*")(version 3.0; acl "Self entry modification"; allow (write) userdn="ldap:///self";) opends/src/messages/messages/core.properties
@@ -1735,11 +1735,14 @@ to decrypt the supplied data because there was an error reading from the \ input stream: %s SEVERE_ERR_CRYPTOMGR_IMPORT_KEY_ENTRY_FAILED_TO_DECODE_687=CryptoManager \ failed to import the symmetric key entry "%s" because there is no symmetric \ key attribute value that can be decoded by this instance" failed to import the symmetric key entry "%s" because it could not obtain a \ symmetric key attribute value that can be decoded by this instance" SEVERE_ERR_CRYPTOMGR_IMPORT_KEY_ENTRY_FAILED_OTHER_688=CryptoManager failed \ to import the symmetric key entry "%s": %s MILD_ERR_CRYPTOMGR_INVALID_SYMMETRIC_KEY_ALGORITHM_689=CryptoManager failed \ to instantiate a KeyGenerator for algorithm "%s": %s SEVERE_ERR_CRYPTOMGR_SYMMETRIC_KEY_ENTRY_ADD_FAILED_690=CryptoManager failed \ to add locally produced symmetric key entry "%s": %s SEVERE_ERR_CRYPTOMGR_IMPORT_KEY_ENTRY_FAILED_TO_ADD_KEY_691=CryptoManager \ failed to import the symmetric key entry "%s" because it could not add \ a symmetric key attribute value that can be decoded by this instance" opends/src/server/org/opends/server/core/CryptoManagerSync.java
File was renamed from opends/src/server/org/opends/server/core/TrustStoreSyncThread.java @@ -27,14 +27,12 @@ package org.opends.server.core; import org.opends.server.api.DirectoryThread; import org.opends.server.api.Backend; import org.opends.server.api.BackendInitializationListener; import org.opends.server.api.ServerShutdownListener; import org.opends.server.api.ChangeNotificationListener; import org.opends.server.loggers.debug.DebugTracer; import static org.opends.server.loggers.debug.DebugLogger.getTracer; import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; import static org.opends.server.loggers.debug.DebugLogger.getTracer; import org.opends.server.loggers.ErrorLogger; import org.opends.server.types.*; import org.opends.server.types.operation.PostResponseAddOperation; @@ -51,16 +49,12 @@ import static org.opends.server.config.ConfigConstants.OC_CRYPTO_MAC_KEY; import org.opends.server.protocols.internal.InternalClientConnection; import org.opends.server.protocols.internal.InternalSearchOperation; import org.opends.server.protocols.internal.InternalSearchListener; import org.opends.server.controls.PersistentSearchChangeType; import org.opends.server.controls.EntryChangeNotificationControl; import static org.opends.messages.CoreMessages.*; import org.opends.messages.Message; import org.opends.admin.ads.ADSContext; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; import java.util.LinkedHashSet; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -68,12 +62,12 @@ import java.util.HashMap; /** * This class defines a thread that synchronizes certificates from the admin * data branch into the trust store backend. * This class defines an object that synchronizes certificates from the admin * data branch into the trust store backend, and synchronizes secret-key entries * from the admin data branch to the crypto manager secret-key cache. */ public class TrustStoreSyncThread extends DirectoryThread implements ServerShutdownListener, BackendInitializationListener, InternalSearchListener, ChangeNotificationListener public class CryptoManagerSync implements BackendInitializationListener, ChangeNotificationListener { /** * The debug log tracer for this object. @@ -82,10 +76,6 @@ // A lock and condition for notifying this thread. private Lock lock; private Condition condition; // The DN of the administration suffix. private DN adminSuffixDN; @@ -110,18 +100,6 @@ // A filter on object class to select key entries. private SearchFilter keySearchFilter; // Indicates whether the ADS suffix backend is initialized. private boolean adminBackendInitialized; // Indicates whether the trust store backend is initialized. private boolean trustStoreBackendInitialized; // Indicates whether a shutdown request has been received. private boolean shutdownRequested; // Indicates whether the initial search has been done. private boolean searchDone; // The instance key objectclass. private ObjectClass ocInstanceKey; @@ -134,22 +112,10 @@ /** * Creates a new instance of this trust store synchronization thread. */ public TrustStoreSyncThread() public CryptoManagerSync() { super("Trust Store Synchronization Thread"); setDaemon(true); shutdownRequested = false; adminBackendInitialized = false; trustStoreBackendInitialized = false; searchDone = false; DirectoryServer.registerShutdownListener(this); DirectoryServer.registerBackendInitializationListener(this); lock = new ReentrantLock(); condition = lock.newCondition(); try { adminSuffixDN = DN.decode(ADSContext.getAdministrationSuffixDN()); @@ -184,58 +150,14 @@ if (DirectoryServer.getBackendWithBaseDN(adminSuffixDN) != null) { adminBackendInitialized = true; searchAdminSuffix(); } if (DirectoryServer.getBackendWithBaseDN(trustStoreRootDN) != null) { trustStoreBackendInitialized = true; } DirectoryServer.registerChangeNotificationListener(this); } // We would need this to detect changes if the admin branch was remote. // private SearchOperation runPersistentSearch() // { // InternalClientConnection conn = // InternalClientConnection.getRootConnection(); // LinkedHashSet<String> attributes = new LinkedHashSet<String>(0); // // // Specify the persistent search control. // Set<PersistentSearchChangeType> changeTypes = // new HashSet<PersistentSearchChangeType>(); // changeTypes.add(PersistentSearchChangeType.ADD); // changeTypes.add(PersistentSearchChangeType.DELETE); // changeTypes.add(PersistentSearchChangeType.MODIFY); // // boolean changesOnly = false; // boolean returnECs = true; // // PersistentSearchControl psc = // new PersistentSearchControl(changeTypes, changesOnly, returnECs); // ArrayList<Control> controls = new ArrayList<Control>(1); // controls.add(psc); // // InternalSearchOperation searchOperation = // new InternalSearchOperation( // conn, // InternalClientConnection.nextOperationID(), // InternalClientConnection.nextMessageID(), // controls, // adminSuffixDN, SearchScope.WHOLE_SUBTREE, // DereferencePolicy.NEVER_DEREF_ALIASES, // 0, 0, // false, instanceKeyFilter, attributes, // this); // // searchOperation.run(); // // return searchOperation; // } private SearchOperation runSearch() private void searchAdminSuffix() { InternalClientConnection conn = InternalClientConnection.getRootConnection(); @@ -252,30 +174,10 @@ DereferencePolicy.NEVER_DEREF_ALIASES, 0, 0, false, keySearchFilter, attributes, this); null); searchOperation.run(); return searchOperation; } /** * Performs an initial search on the ADS branch when enabled, then listens * for changes within the branch, writing certificates from instance key * entries to the trust store backend. */ public void run() { while (!shutdownRequested) { try { if (!searchDone && adminBackendInitialized && trustStoreBackendInitialized) { SearchOperation searchOperation = runSearch(); ResultCode resultCode = searchOperation.getResultCode(); if (resultCode != ResultCode.SUCCESS) { @@ -285,14 +187,14 @@ searchOperation.getErrorMessage().toString()); ErrorLogger.logError(message); } searchDone = true; DirectoryServer.registerChangeNotificationListener(this); } // Wait until a backend changes state or a shutdown is requested. awaitCondition(); for (SearchResultEntry searchEntry : searchOperation.getSearchEntries()) { try { handleInternalSearchEntry(searchEntry); } catch (Exception e) catch (DirectoryException e) { if (debugEnabled()) { @@ -304,58 +206,7 @@ ErrorLogger.logError(message); } } } /** * {@inheritDoc} */ public String getShutdownListenerName() { return "Trust Store Synchronization Thread"; } /** * {@inheritDoc} */ public void processServerShutdown(Message reason) { shutdownRequested = true; notifyCondition(); } private void notifyCondition() { lock.lock(); try { condition.signalAll(); } finally { lock.unlock(); } } private void awaitCondition() { lock.lock(); try { condition.await(); } catch (InterruptedException e) { // ignore } finally { lock.unlock(); } } @@ -364,8 +215,6 @@ */ public void performBackendInitializationProcessing(Backend backend) { boolean notify = false; DN[] baseDNs = backend.getBaseDNs(); if (baseDNs != null) { @@ -373,21 +222,10 @@ { if (baseDN.equals(adminSuffixDN)) { adminBackendInitialized = true; notify = true; } else if (baseDN.equals(trustStoreRootDN)) { trustStoreBackendInitialized = true; notify = true; searchAdminSuffix(); } } } if (notify) { notifyCondition(); } } /** @@ -395,37 +233,10 @@ */ public void performBackendFinalizationProcessing(Backend backend) { boolean notify = false; DN[] baseDNs = backend.getBaseDNs(); if (baseDNs != null) { for (DN baseDN : baseDNs) { if (baseDN.equals(adminSuffixDN)) { adminBackendInitialized = false; notify = true; } else if (baseDN.equals(trustStoreRootDN)) { adminBackendInitialized = false; notify = true; } } // No implementation required. } if (notify) { notifyCondition(); } } /** * {@inheritDoc} */ public void handleInternalSearchEntry(InternalSearchOperation searchOperation, SearchResultEntry searchEntry) private void handleInternalSearchEntry(SearchResultEntry searchEntry) throws DirectoryException { if (searchEntry.hasObjectClass(ocInstanceKey)) @@ -638,16 +449,6 @@ /** * {@inheritDoc} */ public void handleInternalSearchReference( InternalSearchOperation searchOperation, SearchResultReference searchReference) throws DirectoryException { // No implementation required. } /** * {@inheritDoc} */ public void handleAddOperation(PostResponseAddOperation addOperation, Entry entry) { opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -1427,8 +1427,8 @@ } // Start a thread to synchronize the trust store. new TrustStoreSyncThread().start(); // Create an object to synchronize ADS with the crypto manager. new CryptoManagerSync(); // If we should write a copy of the config on successful startup, then do // so now. opends/src/server/org/opends/server/types/CryptoManager.java
@@ -38,6 +38,7 @@ import java.security.cert.CertificateFactory; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import java.util.zip.DataFormatException; import java.util.zip.Deflater; import java.util.zip.Inflater; @@ -58,6 +59,7 @@ import org.opends.server.config.ConfigConstants; import org.opends.server.core.DirectoryServer; import org.opends.server.core.AddOperation; import org.opends.server.core.ModifyOperation; import static org.opends.server.loggers.debug.DebugLogger.*; import org.opends.server.loggers.debug.DebugTracer; import static org.opends.server.util.StaticUtils.*; @@ -65,12 +67,24 @@ import org.opends.server.util.SelectableCertificateKeyManager; import org.opends.server.util.StaticUtils; import org.opends.server.util.Base64; import org.opends.server.util.ServerConstants; import static org.opends.server.util.ServerConstants.OC_TOP; import org.opends.server.protocols.internal.InternalClientConnection; import org.opends.server.protocols.internal.InternalSearchOperation; import org.opends.server.protocols.asn1.ASN1OctetString; import org.opends.server.protocols.ldap.ExtendedRequestProtocolOp; import org.opends.server.protocols.ldap.LDAPMessage; import org.opends.server.protocols.ldap.LDAPControl; import org.opends.server.protocols.ldap.ExtendedResponseProtocolOp; import org.opends.server.protocols.ldap.LDAPResultCode; import org.opends.server.schema.DirectoryStringSyntax; import org.opends.server.schema.IntegerSyntax; import org.opends.server.schema.BinarySyntax; import org.opends.server.tools.LDAPConnection; import org.opends.server.tools.LDAPConnectionOptions; import org.opends.server.tools.LDAPReader; import org.opends.server.tools.LDAPWriter; import org.opends.server.extensions.GetSymmetricKeyExtendedOperation; /** This class implements the Directory Server cryptographic framework, @@ -123,6 +137,9 @@ // The DN of the ADS secret keys container. private static DN secretKeysDN; // The DN of the ADS servers container. private static DN serversDN; // Indicates whether the schema references have been initialized. private static boolean schemaInitDone = false; @@ -227,6 +244,8 @@ DN.decode("cn=instance keys")); secretKeysDN = adminSuffixDN.concat( DN.decode("cn=secret keys")); serversDN = adminSuffixDN.concat( DN.decode("cn=Servers")); } catch (DirectoryException ex) { if (debugEnabled()) { @@ -1803,6 +1822,8 @@ entry.getAttributeValue(attrCompromisedTime, DirectoryStringSyntax.DECODER); boolean isCompromised = compromisedTime != null; ArrayList<String> symmetricKeys = new ArrayList<String>(); entry.getAttributeValues(attrSymmetricKey, DirectoryStringSyntax.DECODER, @@ -1819,19 +1840,52 @@ if (secretKey == null) { // Request the value from another server. String symmetricKey = getSymmetricKey(symmetricKeys); if (symmetricKey == null) { throw new CryptoManagerException( ERR_CRYPTOMGR_IMPORT_KEY_ENTRY_FAILED_TO_DECODE.get( entry.getDN().toString())); } boolean isCompromised = compromisedTime != null; secretKey = decodeSymmetricKeyAttribute(symmetricKey); CipherKeyEntry.importCipherKeyEntry(this, keyID, transformation, secretKey, keyLengthBits, secretKey, keyLengthBits, ivLengthBits, isCompromised); // Write the value to the entry. InternalClientConnection internalConnection = InternalClientConnection.getRootConnection(); List<Modification> modifications = new ArrayList<Modification>(1); Attribute attribute = new Attribute(ConfigConstants.ATTR_CRYPTO_SYMMETRIC_KEY, symmetricKey); modifications.add( new Modification(ModificationType.ADD, attribute, false)); ModifyOperation internalModify = internalConnection.processModify(entry.getDN(), modifications); if (internalModify.getResultCode() != ResultCode.SUCCESS) { throw new CryptoManagerException( ERR_CRYPTOMGR_IMPORT_KEY_ENTRY_FAILED_TO_ADD_KEY.get( entry.getDN().toString())); } } else { CipherKeyEntry.importCipherKeyEntry(this, keyID, transformation, secretKey, keyLengthBits, ivLengthBits, isCompromised); } } catch (DirectoryException ex) { @@ -1845,6 +1899,115 @@ } /** * Given a set of other servers' symmetric key values for * a given secret key, use the Get Symmetric Key extended * operation to request this server's symmetric key value. * * @param symmetricKeys The known symmetric key values for * a given secret key. * * @return The symmetric key value for this server, or null if * none could be obtained. */ private String getSymmetricKey(List<String> symmetricKeys) { InternalClientConnection internalConnection = InternalClientConnection.getRootConnection(); for (String symmetricKey : symmetricKeys) { try { // Get the server instance key ID from the symmetric key. String[] elements = symmetricKey.split(":", 0); String instanceKeyID = elements[0]; // Find the server entry from the instance key ID. String filter = "(" + ConfigConstants.ATTR_CRYPTO_KEY_ID + "=" + instanceKeyID + ")"; InternalSearchOperation internalSearch = internalConnection.processSearch( serversDN, SearchScope.SUBORDINATE_SUBTREE, SearchFilter.createFilterFromString(filter)); if (internalSearch.getResultCode() != ResultCode.SUCCESS) continue; LinkedList<SearchResultEntry> resultEntries = internalSearch.getSearchEntries(); for (SearchResultEntry resultEntry : resultEntries) { AttributeType hostnameAttr = DirectoryServer.getAttributeType("hostname", true); String hostname = resultEntry.getAttributeValue( hostnameAttr, DirectoryStringSyntax.DECODER); AttributeType ldapPortAttr = DirectoryServer.getAttributeType("ldapport", true); Integer ldapPort = resultEntry.getAttributeValue( ldapPortAttr, IntegerSyntax.DECODER); // Connect to the server. AtomicInteger nextMessageID = new AtomicInteger(1); LDAPConnectionOptions connectionOptions = new LDAPConnectionOptions(); LDAPConnection connection = new LDAPConnection(hostname, ldapPort, connectionOptions, System.out, System.err); //FIXME connection.connectToHost(null, null, nextMessageID); try { LDAPReader reader = connection.getLDAPReader(); LDAPWriter writer = connection.getLDAPWriter(); // Send the Get Symmetric Key extended request. ASN1OctetString requestValue = GetSymmetricKeyExtendedOperation.encodeRequestValue( symmetricKey, getInstanceKeyID()); ExtendedRequestProtocolOp extendedRequest = new ExtendedRequestProtocolOp( ServerConstants. OID_GET_SYMMETRIC_KEY_EXTENDED_OP, requestValue); ArrayList<LDAPControl> controls = new ArrayList<LDAPControl>(); LDAPMessage requestMessage = new LDAPMessage(nextMessageID.getAndIncrement(), extendedRequest, controls); writer.writeMessage(requestMessage); LDAPMessage responseMessage = reader.readMessage(); ExtendedResponseProtocolOp extendedResponse = responseMessage.getExtendedResponseProtocolOp(); if (extendedResponse.getResultCode() == LDAPResultCode.SUCCESS) { // Got our symmetric key value. return extendedResponse.getValue().stringValue(); } } finally { connection.close(nextMessageID); } } } catch (Exception e) { // Just try another server. } } // Give up. return null; } /** * Imports a mac key entry from an entry in ADS. * * @param entry The ADS mac key entry to be imported. The @@ -1879,6 +2042,8 @@ entry.getAttributeValue(attrCompromisedTime, DirectoryStringSyntax.DECODER); boolean isCompromised = compromisedTime != null; ArrayList<String> symmetricKeys = new ArrayList<String>(); entry.getAttributeValues(attrSymmetricKey, DirectoryStringSyntax.DECODER, @@ -1895,17 +2060,47 @@ if (secretKey == null) { // Request the value from another server. String symmetricKey = getSymmetricKey(symmetricKeys); if (symmetricKey == null) { throw new CryptoManagerException( ERR_CRYPTOMGR_IMPORT_KEY_ENTRY_FAILED_TO_DECODE.get( entry.getDN().toString())); } boolean isCompromised = compromisedTime != null; secretKey = decodeSymmetricKeyAttribute(symmetricKey); MacKeyEntry.importMacKeyEntry(this, keyID, algorithm, secretKey, keyLengthBits, isCompromised); // Write the value to the entry. InternalClientConnection internalConnection = InternalClientConnection.getRootConnection(); List<Modification> modifications = new ArrayList<Modification>(1); Attribute attribute = new Attribute(ConfigConstants.ATTR_CRYPTO_SYMMETRIC_KEY, symmetricKey); modifications.add( new Modification(ModificationType.ADD, attribute, false)); ModifyOperation internalModify = internalConnection.processModify(entry.getDN(), modifications); if (internalModify.getResultCode() != ResultCode.SUCCESS) { throw new CryptoManagerException( ERR_CRYPTOMGR_IMPORT_KEY_ENTRY_FAILED_TO_ADD_KEY.get( entry.getDN().toString())); } } else { MacKeyEntry.importMacKeyEntry(this, keyID, algorithm, secretKey, keyLengthBits, isCompromised); } } catch (DirectoryException ex) {