mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noel Rouvignac
03.24.2014 1a331f7254cb81f5176d577dfb7859af5b7e729f
opendj3-server-dev/src/server/org/opends/server/crypto/CryptoManagerImpl.java
@@ -27,65 +27,62 @@
 */
package org.opends.server.crypto;
import org.forgerock.i18n.LocalizableMessage;
import static org.opends.messages.CoreMessages.*;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.ByteArrayInputStream;
import java.io.PrintStream;
import java.io.*;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.text.ParseException;
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;
import java.text.ParseException;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.KeyManager;
import javax.net.ssl.TrustManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509ExtendedKeyManager;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.util.Reject;
import org.opends.admin.ads.ADSContext;
import org.opends.server.admin.std.server.CryptoManagerCfg;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.std.server.CryptoManagerCfg;
import org.opends.server.api.Backend;
import org.opends.server.backends.TrustStoreBackend;
import org.opends.server.config.ConfigException;
import org.opends.server.config.ConfigConstants;
import org.opends.server.core.DirectoryServer;
import org.opends.server.config.ConfigException;
import org.opends.server.core.AddOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyOperation;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import static org.opends.server.util.StaticUtils.*;
import org.forgerock.util.Reject;
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.ldap.ExtendedRequestProtocolOp;
import org.opends.server.protocols.ldap.LDAPMessage;
import org.opends.server.protocols.ldap.ExtendedResponseProtocolOp;
import org.opends.server.protocols.ldap.LDAPMessage;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.schema.BinarySyntax;
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.types.*;
import org.forgerock.opendj.ldap.ByteString;
import org.opends.server.util.Base64;
import org.opends.server.util.SelectableCertificateKeyManager;
import org.opends.server.util.ServerConstants;
import org.opends.server.util.StaticUtils;
import static org.opends.messages.CoreMessages.*;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
/**
 This class implements the Directory Server cryptographic framework,
@@ -112,7 +109,7 @@
{
  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
  // Various schema element references.
  /** Various schema element references. */
  private static AttributeType attrKeyID;
  private static AttributeType attrPublicKeyCertificate;
  private static AttributeType attrTransformation;
@@ -126,87 +123,95 @@
  private static ObjectClass   ocCipherKey;
  private static ObjectClass   ocMacKey;
  // The DN of the local truststore backend.
  /** The DN of the local truststore backend. */
  private static DN localTruststoreDN;
  // The DN of the ADS instance keys container.
  /** The DN of the ADS instance keys container. */
  private static DN instanceKeysDN;
  // The DN of the ADS secret keys container.
  /** The DN of the ADS secret keys container. */
  private static DN secretKeysDN;
  // The DN of the ADS servers container.
  /** The DN of the ADS servers container. */
  private static DN serversDN;
  // Indicates whether the schema references have been initialized.
  /** Indicates whether the schema references have been initialized. */
  private static boolean schemaInitDone = false;
  // The secure random number generator used for key generation,
  // initialization vector PRNG seed...
  /**
   * The secure random number generator used for key generation, initialization
   * vector PRNG seed...
   */
  private static final SecureRandom secureRandom = new SecureRandom();
  // The random number generator used for initialization vector
  // production.
  /**
   * The random number generator used for initialization vector production.
   */
  private static final Random pseudoRandom
          = new Random(secureRandom.nextLong());
  // The first byte in any ciphertext produced by CryptoManager is the
  // prologue version. At present, this constant is both the version written
  // and the expected version. If a new version is introduced (e.g., to allow
  // embedding the HMAC key identifier and signature in a signed backup) the
  // prologue version will likely need to be configurable at the granularity
  // of the CryptoManager client (e.g., password encryption might use version 1,
  // while signed backups might use version 2.
  /**
   * The first byte in any ciphertext produced by CryptoManager is the prologue
   * version. At present, this constant is both the version written and the
   * expected version. If a new version is introduced (e.g., to allow embedding
   * the HMAC key identifier and signature in a signed backup) the prologue
   * version will likely need to be configurable at the granularity of the
   * CryptoManager client (e.g., password encryption might use version 1, while
   * signed backups might use version 2.
   */
  private static final int CIPHERTEXT_PROLOGUE_VERSION = 1 ;
  // The map from encryption key ID to CipherKeyEntry (cache). The
  // cache is accessed by methods that request, publish, and import
  // keys.
  /**
   * The map from encryption key ID to CipherKeyEntry (cache). The cache is
   * accessed by methods that request, publish, and import keys.
   */
  private final Map<KeyEntryID, CipherKeyEntry> cipherKeyEntryCache
          = new ConcurrentHashMap<KeyEntryID, CipherKeyEntry>();
  // The map from encryption key ID to MacKeyEntry (cache). The cache
  // is accessed by methods that request, publish, and import keys.
  /**
   * The map from encryption key ID to MacKeyEntry (cache). The cache is
   * accessed by methods that request, publish, and import keys.
   */
  private final Map<KeyEntryID, MacKeyEntry> macKeyEntryCache
          = new ConcurrentHashMap<KeyEntryID, MacKeyEntry>();
  // The preferred key wrapping transformation
  /** The preferred key wrapping transformation. */
  private String preferredKeyWrappingTransformation;
  // TODO: Move the following configuration to backup or backend configuration.
  // TODO: https://opends.dev.java.net/issues/show_bug.cgi?id=2472
  // The preferred message digest algorithm for the Directory Server.
  /** The preferred message digest algorithm for the Directory Server. */
  private String preferredDigestAlgorithm;
  // The preferred cipher for the Directory Server.
  /** The preferred cipher for the Directory Server. */
  private String preferredCipherTransformation;
  // The preferred key length for the preferred cipher.
  /** The preferred key length for the preferred cipher. */
  private int preferredCipherTransformationKeyLengthBits;
  // The preferred MAC algorithm for the Directory Server.
  /** The preferred MAC algorithm for the Directory Server. */
  private String preferredMACAlgorithm;
  // The preferred key length for the preferred MAC algorithm.
  /** The preferred key length for the preferred MAC algorithm. */
  private int preferredMACAlgorithmKeyLengthBits;
  // TODO: Move the following configuration to replication configuration.
  // TODO: https://opends.dev.java.net/issues/show_bug.cgi?id=2473
  // The name of the local certificate to use for SSL.
  /** The name of the local certificate to use for SSL. */
  private final String sslCertNickname;
  // Whether replication sessions use SSL encryption.
  /** Whether replication sessions use SSL encryption. */
  private final boolean sslEncryption;
  // The set of SSL protocols enabled or null for the default set.
  /** The set of SSL protocols enabled or null for the default set. */
  private final SortedSet<String> sslProtocols;
  // The set of SSL cipher suites enabled or null for the default set.
  /** The set of SSL cipher suites enabled or null for the default set. */
  private final SortedSet<String> sslCipherSuites;
@@ -290,9 +295,8 @@
  }
  /**
   * {@inheritDoc}
   */
  /** {@inheritDoc} */
  @Override
  public boolean isConfigurationChangeAcceptable(
       CryptoManagerCfg cfg,
       List<LocalizableMessage> unacceptableReasons)
@@ -421,9 +425,8 @@
  }
  /**
   * {@inheritDoc}
   */
  /** {@inheritDoc} */
  @Override
  public ConfigChangeResult applyConfigurationChange(
       CryptoManagerCfg cfg)
  {
@@ -492,10 +495,7 @@
    final DN entryDN = localTruststoreDN.child(
            RDN.create(attrKeyID, distinguishedValue));
    // Construct the search filter.
    final String FILTER_OC_INSTANCE_KEY =
            new StringBuilder("(objectclass=")
                    .append(ocInstanceKey.getNameOrOID())
                    .append(")").toString();
    final String FILTER_OC_INSTANCE_KEY = "(objectclass=" + ocInstanceKey.getNameOrOID() + ")";
    // Construct the attribute list.
    final LinkedHashSet<String> requestedAttributes
            = new LinkedHashSet<String>();
@@ -636,10 +636,7 @@
    final DN entryDN = instanceKeysDN.child(
         RDN.create(attrKeyID, distinguishedValue));
    // Construct the search filter.
    final String FILTER_OC_INSTANCE_KEY =
            new StringBuilder("(objectclass=")
                    .append(ocInstanceKey.getNameOrOID())
                    .append(")").toString();
    final String FILTER_OC_INSTANCE_KEY = "(objectclass=" + ocInstanceKey.getNameOrOID() + ")";
    // Construct the attribute list.
    final LinkedHashSet<String> requestedAttributes
            = new LinkedHashSet<String>();
@@ -714,17 +711,9 @@
            = new HashMap<String, byte[]>();
    try {
      // Construct the search filter.
      final String FILTER_OC_INSTANCE_KEY
              = new StringBuilder("(objectclass=")
              .append(ocInstanceKey.getNameOrOID())
              .append(")").toString();
      final String FILTER_NOT_COMPROMISED = new StringBuilder("(!(")
              .append(attrCompromisedTime.getNameOrOID())
              .append("=*))").toString();
      final String searchFilter = new StringBuilder("(&")
              .append(FILTER_OC_INSTANCE_KEY)
              .append(FILTER_NOT_COMPROMISED)
              .append(")").toString();
      final String FILTER_OC_INSTANCE_KEY = "(objectclass=" + ocInstanceKey.getNameOrOID() + ")";
      final String FILTER_NOT_COMPROMISED = "(!(" + attrCompromisedTime.getNameOrOID() + "=*))";
      final String searchFilter = "(&" + FILTER_OC_INSTANCE_KEY + FILTER_NOT_COMPROMISED + ")";
      // Construct the attribute list.
      final LinkedHashSet<String> requestedAttributes
              = new LinkedHashSet<String>();
@@ -759,7 +748,7 @@
            ERR_CRYPTOMGR_FAILED_TO_RETRIEVE_ADS_TRUSTSTORE_CERTS.get(
                    instanceKeysDN, getExceptionMessage(ex)), ex);
    }
    return(certificateMap);
    return certificateMap;
  }
@@ -860,16 +849,8 @@
    }
    // Compose ds-cfg-symmetric-key value.
    StringBuilder symmetricKeyAttribute = new StringBuilder();
    symmetricKeyAttribute.append(wrappingKeyID);
    symmetricKeyAttribute.append(":");
    symmetricKeyAttribute.append(wrappingTransformationName);
    symmetricKeyAttribute.append(":");
    symmetricKeyAttribute.append(secretKey.getAlgorithm());
    symmetricKeyAttribute.append(":");
    symmetricKeyAttribute.append(wrappedKeyElement);
    return symmetricKeyAttribute.toString();
    return wrappingKeyID + ":" + wrappingTransformationName + ":"
        + secretKey.getAlgorithm() + ":" + wrappedKeyElement;
  }
@@ -1432,6 +1413,7 @@
     * @return {@code true} if the objects are the same, {@code false}
     * otherwise.
     */
    @Override
    public boolean equals(final Object obj){
      return obj instanceof KeyEntryID
              && fValue.equals(((KeyEntryID) obj).fValue);
@@ -1442,6 +1424,7 @@
     *
     * @return a hash code value for this {@code KeyEntryID}.
     */
    @Override
    public int hashCode() {
      return fValue.hashCode();
    }
@@ -2566,6 +2549,7 @@
  /** {@inheritDoc} */
  @Override
  public String getPreferredMessageDigestAlgorithm()
  {
    return preferredDigestAlgorithm;
@@ -2573,6 +2557,7 @@
  /** {@inheritDoc} */
  @Override
  public MessageDigest getPreferredMessageDigest()
         throws NoSuchAlgorithmException
  {
@@ -2581,6 +2566,7 @@
  /** {@inheritDoc} */
  @Override
  public MessageDigest getMessageDigest(String digestAlgorithm)
         throws NoSuchAlgorithmException
  {
@@ -2589,6 +2575,7 @@
  /** {@inheritDoc} */
  @Override
  public byte[] digest(byte[] data)
         throws NoSuchAlgorithmException
  {
@@ -2598,6 +2585,7 @@
  /** {@inheritDoc} */
  @Override
  public byte[] digest(String digestAlgorithm, byte[] data)
         throws NoSuchAlgorithmException
  {
@@ -2606,6 +2594,7 @@
  /** {@inheritDoc} */
  @Override
  public byte[] digest(InputStream inputStream)
         throws IOException, NoSuchAlgorithmException
  {
@@ -2629,6 +2618,7 @@
  /** {@inheritDoc} */
  @Override
  public byte[] digest(String digestAlgorithm,
                       InputStream inputStream)
         throws IOException, NoSuchAlgorithmException
@@ -2652,6 +2642,7 @@
  /** {@inheritDoc} */
  @Override
  public String getMacEngineKeyEntryID()
          throws CryptoManagerException
  {
@@ -2661,6 +2652,7 @@
  /** {@inheritDoc} */
  @Override
  public String getMacEngineKeyEntryID(final String macAlgorithm,
                                       final int keyLengthBits)
         throws CryptoManagerException {
@@ -2678,6 +2670,7 @@
  /** {@inheritDoc} */
  @Override
  public Mac getMacEngine(String keyEntryID)
          throws CryptoManagerException
  {
@@ -2688,6 +2681,7 @@
  /** {@inheritDoc} */
  @Override
  public byte[] encrypt(byte[] data)
         throws GeneralSecurityException, CryptoManagerException
  {
@@ -2697,6 +2691,7 @@
  /** {@inheritDoc} */
  @Override
  public byte[] encrypt(String cipherTransformation,
                        int keyLengthBits,
                        byte[] data)
@@ -2734,6 +2729,7 @@
  /** {@inheritDoc} */
  @Override
  public CipherOutputStream getCipherOutputStream(
          OutputStream outputStream) throws CryptoManagerException
  {
@@ -2743,6 +2739,7 @@
  /** {@inheritDoc} */
  @Override
  public CipherOutputStream getCipherOutputStream(
          String cipherTransformation, int keyLengthBits,
          OutputStream outputStream)
@@ -2778,6 +2775,7 @@
  /** {@inheritDoc} */
  @Override
  public byte[] decrypt(byte[] data)
         throws GeneralSecurityException,
                CryptoManagerException
@@ -2854,6 +2852,7 @@
 /** {@inheritDoc} */
  @Override
  public CipherInputStream getCipherInputStream(
          InputStream inputStream) throws CryptoManagerException
  {
@@ -2911,6 +2910,7 @@
  /** {@inheritDoc} */
  @Override
  public int compress(byte[] src, int srcOff, int srcLen,
                      byte[] dst, int dstOff, int dstLen)
  {
@@ -2938,6 +2938,7 @@
  /** {@inheritDoc} */
  @Override
  public int uncompress(byte[] src, int srcOff, int srcLen,
                        byte[] dst, int dstOff, int dstLen)
         throws DataFormatException
@@ -2972,6 +2973,7 @@
  /** {@inheritDoc} */
  @Override
  public SSLContext getSslContext(String sslCertNickname)
       throws ConfigException
  {
@@ -3013,24 +3015,28 @@
  /** {@inheritDoc} */
  @Override
  public String getSslCertNickname()
  {
    return sslCertNickname;
  }
  /** {@inheritDoc} */
  @Override
  public boolean isSslEncryption()
  {
    return sslEncryption;
  }
  /** {@inheritDoc} */
  @Override
  public SortedSet<String> getSslProtocols()
  {
    return sslProtocols;
  }
  /** {@inheritDoc} */
  @Override
  public SortedSet<String> getSslCipherSuites()
  {
    return sslCipherSuites;