From 0e2118631c0ae4dc02e0904cec9bda8f399d412b Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Thu, 08 Mar 2007 17:28:22 +0000
Subject: [PATCH] Add a new CertificateManager class that can be used to simplify interacting with different types of key stores, including generating self-signed certificates and certificate signing requests.
---
opendj-sdk/opends/src/server/org/opends/server/util/CertificateManager.java | 860 ++++++++++++++++++++++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/util/CertificateManagerTestCase.java | 1416 +++++++++++++++++++++++++++++++++++++
2 files changed, 2,276 insertions(+), 0 deletions(-)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/CertificateManager.java b/opendj-sdk/opends/src/server/org/opends/server/util/CertificateManager.java
new file mode 100644
index 0000000..82961ca
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/CertificateManager.java
@@ -0,0 +1,860 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.util;
+
+
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.File;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+
+
+/**
+ * This class provides an interface for generating self-signed certificates and
+ * certificate signing requests, and for importing, exporting, and deleting
+ * certificates from a key store. It supports JKS, PKCS11, and PKCS12 key store
+ * types.
+ * <BR><BR>
+ * Note that for some operations, particularly those that require updating the
+ * contents of a key store (including generating certificates and/or certificate
+ * signing requests, importing certificates, or removing certificates), this
+ * class relies on the keytool utility provided with Sun's implementation of the
+ * Java runtime environment. It will perform the associated operations by
+ * invoking the appropriate command. It is possible that the keytool command
+ * will not exist in all Java runtime environments, especially those not created
+ * by Sun. In those cases, it will not be possible to invoke operations that
+ * require altering the contents of the key store. Therefore, it is strongly
+ * recommended that any code that may want to make use of this facility should
+ * first call {@code mayUseCertificateManager} and if it returns {@code false}
+ * the caller should gracefully degrade and suggest that the user perform the
+ * operation manually.
+ */
+public class CertificateManager
+{
+ /**
+ * The path to the keytool command, which will be required to perform
+ * operations that modify the contents of a key store.
+ */
+ public static final String KEYTOOL_COMMAND;
+
+
+
+ /**
+ * The key store type value that should be used for the "JKS" key store.
+ */
+ public static final String KEY_STORE_TYPE_JKS = "JKS";
+
+
+
+ /**
+ * The key store type value that should be used for the "PKCS11" key store.
+ */
+ public static final String KEY_STORE_TYPE_PKCS11 = "PKCS11";
+
+
+
+ /**
+ * The key store type value that should be used for the "PKCS12" key store.
+ */
+ public static final String KEY_STORE_TYPE_PKCS12 = "PKCS12";
+
+
+
+ /**
+ * The key store path value that must be used in conjunction with the PKCS11
+ * key store type.
+ */
+ public static final String KEY_STORE_PATH_PKCS11 = "NONE";
+
+
+
+ // The parsed key store backing this certificate manager.
+ private KeyStore keyStore;
+
+ // The password that should be used to interact with the key store.
+ private String keyStorePIN;
+
+ // The path to the key store that we should be using.
+ private String keyStorePath;
+
+ // The name of the key store type we are using.
+ private String keyStoreType;
+
+
+
+ static
+ {
+ String keytoolCommand = null;
+
+ try
+ {
+ String cmd = System.getProperty("java.home") + File.separator + "bin" +
+ File.separator + "keytool";
+ File cmdFile = new File(cmd);
+ if (cmdFile.exists())
+ {
+ keytoolCommand = cmdFile.getAbsolutePath();
+ }
+ else
+ {
+ cmd = cmd + ".exe";
+ cmdFile = new File(cmd);
+ if (cmdFile.exists())
+ {
+ keytoolCommand = cmdFile.getAbsolutePath();
+ }
+ else
+ {
+ keytoolCommand = null;
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ keytoolCommand = null;
+ }
+
+ KEYTOOL_COMMAND = keytoolCommand;
+ }
+
+
+
+ /**
+ * Indicates whether it is possible to use this certificate manager code to
+ * perform operations which may alter the contents of a key store.
+ *
+ * @return {@code true} if it appears that the keytool utility is available
+ * and may be used to execute commands that may alter the contents of
+ * a key store, or {@code false} if not.
+ */
+ public static boolean mayUseCertificateManager()
+ {
+ return (KEYTOOL_COMMAND != null);
+ }
+
+
+
+ /**
+ * Creates a new certificate manager instance with the provided information.
+ *
+ * @param keyStorePath The path to the key store file, or "NONE" if the key
+ * store type is "PKCS11". For the other key store
+ * types, the file does not need to exist if a new
+ * self-signed certificate or certificate signing
+ * request is to be generated, although the directory
+ * containing the file must exist. The key store file
+ * must exist if import or export operations are to be
+ * performed.
+ * @param keyStoreType The key store type to use. It should be one of
+ * {@code KEY_STORE_TYPE_JKS},
+ * {@code KEY_STORE_TYPE_PKCS11}, or
+ * {@code KEY_STORE_TYPE_PKCS12}.
+ * @param keyStorePIN The PIN required to access the key store. It must
+ * not be {@code null}.
+ *
+ * @throws IllegalArgumentException If any of the provided arguments is
+ * invalid.
+ *
+ * @throws NullPointerException If any of the provided arguments is
+ * {@code null}.
+ *
+ * @throws UnsupportedOperationException If it is not possible to use the
+ * certificate manager on the
+ * underlying platform.
+ */
+ public CertificateManager(String keyStorePath, String keyStoreType,
+ String keyStorePIN)
+ throws IllegalArgumentException, NullPointerException,
+ UnsupportedOperationException
+ {
+ if ((keyStorePath == null) || (keyStorePath.length() == 0))
+ {
+ throw new NullPointerException("keyStorePath");
+ }
+ else if ((keyStoreType == null) || (keyStoreType.length() == 0))
+ {
+ throw new NullPointerException("keyStoreType");
+ }
+ else if ((keyStorePIN == null) || (keyStorePIN.length() == 0))
+ {
+ throw new NullPointerException("keyStorePIN");
+ }
+
+
+ if (keyStoreType.equals(KEY_STORE_TYPE_PKCS11))
+ {
+ if (! keyStorePath.equals(KEY_STORE_PATH_PKCS11))
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new IllegalArgumentException("Invalid key store path for " +
+ "PKCS11 keystore -- it must be " +
+ KEY_STORE_PATH_PKCS11);
+ }
+ }
+ else if (keyStoreType.equals(KEY_STORE_TYPE_JKS) ||
+ keyStoreType.equals(KEY_STORE_TYPE_PKCS12))
+ {
+ File keyStoreFile = new File(keyStorePath);
+ if (keyStoreFile.exists())
+ {
+ if (! keyStoreFile.isFile())
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new IllegalArgumentException("Key store path " + keyStorePath +
+ " exists but is not a file.");
+ }
+ }
+ else
+ {
+ File keyStoreDirectory = keyStoreFile.getParentFile();
+ if ((keyStoreDirectory == null) || (! keyStoreDirectory.exists()) ||
+ (! keyStoreDirectory.isDirectory()))
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new IllegalArgumentException("Parent directory for key " +
+ "store path " + keyStorePath + " does not exist or " +
+ "is not a directory.");
+ }
+ }
+ }
+ else
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new IllegalArgumentException("Invalid key store type -- it must " +
+ "be one of " + KEY_STORE_TYPE_JKS + ", " +
+ KEY_STORE_TYPE_PKCS11 + ", or " + KEY_STORE_TYPE_PKCS12);
+ }
+
+
+ this.keyStorePath = keyStorePath;
+ this.keyStoreType = keyStoreType;
+ this.keyStorePIN = keyStorePIN;
+
+ keyStore = null;
+ }
+
+
+
+ /**
+ * Indicates whether the provided alias is in use in the key store.
+ *
+ * @param alias The alias for which to make the determination. It must not
+ * be {@code null} or empty.
+ *
+ * @return {@code true} if the key store exist and already contains a
+ * certificate with the given alias, or {@code false} if not.
+ *
+ * @throws KeyStoreException If a problem occurs while attempting to
+ * interact with the key store.
+ *
+ * @throws NullPointerException If the provided alias is {@code null} or a
+ * zero-length string.
+ */
+ public boolean aliasInUse(String alias)
+ throws KeyStoreException, NullPointerException
+ {
+ if ((alias == null) || (alias.length() == 0))
+ {
+ throw new NullPointerException("alias");
+ }
+
+
+ KeyStore keyStore = getKeyStore();
+ if (keyStore == null)
+ {
+ return false;
+ }
+
+ return keyStore.containsAlias(alias);
+ }
+
+
+
+ /**
+ * Retrieves the aliases of the certificates in the specified key store.
+ *
+ * @return The aliases of the certificates in the specified key store, or
+ * {@code null} if the key store does not exist.
+ *
+ * @throws KeyStoreException If a problem occurs while attempting to
+ * interact with the key store.
+ */
+ public String[] getCertificateAliases()
+ throws KeyStoreException
+ {
+ KeyStore keyStore = getKeyStore();
+ if (keyStore == null)
+ {
+ return null;
+ }
+
+ Enumeration<String> aliasEnumeration = keyStore.aliases();
+ if (aliasEnumeration == null)
+ {
+ return new String[0];
+ }
+
+ ArrayList<String> aliasList = new ArrayList<String>();
+ while (aliasEnumeration.hasMoreElements())
+ {
+ aliasList.add(aliasEnumeration.nextElement());
+ }
+
+ String[] aliases = new String[aliasList.size()];
+ return aliasList.toArray(aliases);
+ }
+
+
+
+ /**
+ * Retrieves the certificate with the specified alias from the key store.
+ *
+ * @param alias The alias of the certificate to retrieve. It must not be
+ * {@code null} or empty.
+ *
+ * @return The requested certificate, or {@code null} if the specified
+ * certificate does not exist.
+ *
+ * @throws KeyStoreException If a problem occurs while interacting with the
+ * key store, or the key store does not exist.
+ *
+ * @throws NullPointerException If the provided alias is {@code null} or a
+ * zero-length string.
+ */
+ public Certificate getCertificate(String alias)
+ throws KeyStoreException, NullPointerException
+ {
+ if ((alias == null) || (alias.length() == 0))
+ {
+ throw new NullPointerException("alias");
+ }
+
+ KeyStore keyStore = getKeyStore();
+ if (keyStore == null)
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new KeyStoreException("The key store does not exist.");
+ }
+
+ return keyStore.getCertificate(alias);
+ }
+
+
+
+ /**
+ * Generates a self-signed certificate using the provided information.
+ *
+ * @param alias The nickname to use for the certificate in the key
+ * store. For the server certificate, it should generally
+ * be "server-cert". It must not be {@code null} or empty.
+ * @param subjectDN The subject DN to use for the certificate. It must not
+ * be {@code null} or empty.
+ * @param validity The length of time in days that the certificate should
+ * be valid, starting from the time the certificate is
+ * generated. It must be a positive integer value.
+ *
+ * @throws IllegalArgumentException If the validity is not positive.
+ *
+ * @throws KeyStoreException If a problem occurs while actually attempting
+ * to generate the certificate in the key store.
+ *
+ * @throws NullPointerException If either the alias or subject DN is null or
+ * a zero-length string.
+ *
+ * @throws UnsupportedOperationException If it is not possible to use the
+ * keytool utility to alter the
+ * contents of the key store.
+ */
+ public void generateSelfSignedCertificate(String alias, String subjectDN,
+ int validity)
+ throws KeyStoreException, IllegalArgumentException,
+ NullPointerException, UnsupportedOperationException
+ {
+ if ((alias == null) || (alias.length() == 0))
+ {
+ throw new NullPointerException("alias");
+ }
+ else if ((subjectDN == null) || (subjectDN.length() == 0))
+ {
+ throw new NullPointerException("subjectDN");
+ }
+ else if (validity <= 0)
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new IllegalArgumentException("The validity must be positive.");
+ }
+
+ if (KEYTOOL_COMMAND == null)
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new UnsupportedOperationException("The certificate manager may " +
+ "not be used to alter the contents of key stores on " +
+ "this system.");
+ }
+
+ if (aliasInUse(alias))
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new IllegalArgumentException("A certificate with alias " + alias +
+ " already exists in the key store.");
+ }
+
+
+ // Clear the reference to the key store, since it will be altered by
+ // invoking the KeyTool command.
+ keyStore = null;
+
+
+ // First, we need to run with the "-genkey" command to create the private
+ // key.
+ String[] commandElements =
+ {
+ KEYTOOL_COMMAND,
+ "-genkey",
+ "-alias", alias,
+ "-dname", subjectDN.toString(),
+ "-keyalg", "rsa",
+ "-keystore", keyStorePath,
+ "-keypass", keyStorePIN,
+ "-storetype", keyStoreType,
+ "-storepass", keyStorePIN
+ };
+ runKeyTool(commandElements, false);
+
+ // Next, we need to run with the "-selfcert" command to self-sign the
+ // certificate.
+ commandElements = new String[]
+ {
+ KEYTOOL_COMMAND,
+ "-selfcert",
+ "-alias", alias,
+ "-validity", String.valueOf(validity),
+ "-keystore", keyStorePath,
+ "-keypass", keyStorePIN,
+ "-storetype", keyStoreType,
+ "-storepass", keyStorePIN
+ };
+ runKeyTool(commandElements, false);
+ }
+
+
+
+ /**
+ * Generates a certificate signing request (CSR) using the provided
+ * information.
+ *
+ * @param alias The nickname to use for the certificate in the key
+ * store. For the server certificate, it should generally
+ * be "server-cert". It must not be {@code null} or empty.
+ * @param subjectDN The subject DN to use for the certificate. It must not
+ * be {@code null} or empty.
+ *
+ * @return The file containing the generated certificate signing request.
+ *
+ * @throws KeyStoreException If a problem occurs while actually attempting
+ * to generate the private key in the key store or
+ * generate the certificate signing request based
+ * on that key.
+ *
+ * @throws IOException If a problem occurs while attempting to create the
+ * file to which the certificate signing request will be
+ * written.
+ *
+ * @throws NullPointerException If either the alias or subject DN is null or
+ * a zero-length string.
+ *
+ * @throws UnsupportedOperationException If it is not possible to use the
+ * keytool utility to alter the
+ * contents of the key store.
+ */
+ public File generateCertificateSigningRequest(String alias, String subjectDN)
+ throws KeyStoreException, IOException, NullPointerException,
+ UnsupportedOperationException
+ {
+ if ((alias == null) || (alias.length() == 0))
+ {
+ throw new NullPointerException("alias");
+ }
+ else if ((subjectDN == null) || (subjectDN.length() == 0))
+ {
+ throw new NullPointerException("subjectDN");
+ }
+
+ if (KEYTOOL_COMMAND == null)
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new UnsupportedOperationException("The certificate manager may " +
+ "not be used to alter the contents of key stores on " +
+ "this system.");
+ }
+
+ if (aliasInUse(alias))
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new IllegalArgumentException("A certificate with alias " + alias +
+ " already exists in the key store.");
+ }
+
+
+ // Clear the reference to the key store, since it will be altered by
+ // invoking the KeyTool command.
+ keyStore = null;
+
+
+ // First, we need to run with the "-genkey" command to create the private
+ // key.
+ String[] commandElements =
+ {
+ KEYTOOL_COMMAND,
+ "-genkey",
+ "-alias", alias,
+ "-dname", subjectDN.toString(),
+ "-keyalg", "rsa",
+ "-keystore", keyStorePath,
+ "-keypass", keyStorePIN,
+ "-storetype", keyStoreType,
+ "-storepass", keyStorePIN
+ };
+ runKeyTool(commandElements, false);
+
+ // Next, we need to run with the "-certreq" command to generate the
+ // certificate signing request.
+ File csrFile = File.createTempFile("CertificateManager-", ".csr");
+ commandElements = new String[]
+ {
+ KEYTOOL_COMMAND,
+ "-certreq",
+ "-alias", alias,
+ "-file", csrFile.getAbsolutePath(),
+ "-keystore", keyStorePath,
+ "-keypass", keyStorePIN,
+ "-storetype", keyStoreType,
+ "-storepass", keyStorePIN
+ };
+ runKeyTool(commandElements, false);
+
+ return csrFile;
+ }
+
+
+
+ /**
+ * Adds the provided certificate to the key store. This may be used to
+ * associate an externally-signed certificate with an existing private key
+ * with the given alias.
+ *
+ * @param alias The alias to use for the certificate. It must not
+ * be {@code null} or empty.
+ * @param certificateFile The file containing the encoded certificate. It
+ * must not be {@code null}, and the file must exist.
+ *
+ * @throws IllegalArgumentException If the provided certificate file does
+ * not exist.
+ *
+ * @throws KeyStoreException If a problem occurs while interacting with the
+ * key store.
+ *
+ * @throws NullPointerException If the provided alias is {@code null} or a
+ * zero-length string, or the certificate file
+ * is {@code null}.
+ *
+ * @throws UnsupportedOperationException If it is not possible to use the
+ * keytool utility to alter the
+ * contents of the key store.
+ */
+ public void addCertificate(String alias, File certificateFile)
+ throws IllegalArgumentException, KeyStoreException,
+ NullPointerException, UnsupportedOperationException
+ {
+ if ((alias == null) || (alias.length() == 0))
+ {
+ throw new NullPointerException("alias");
+ }
+
+ if (certificateFile == null)
+ {
+ throw new NullPointerException("certificateFile");
+ }
+ else if ((! certificateFile.exists()) ||
+ (! certificateFile.isFile()))
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new IllegalArgumentException("Certificate file " +
+ certificateFile.getAbsolutePath() +
+ " does not exist or is not a file.");
+ }
+
+ if (KEYTOOL_COMMAND == null)
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new UnsupportedOperationException("The certificate manager may " +
+ "not be used to alter the contents of key stores on " +
+ "this system.");
+ }
+
+
+ // Clear the reference to the key store, since it will be altered by
+ // invoking the KeyTool command.
+ keyStore = null;
+
+
+ String[] commandElements =
+ {
+ KEYTOOL_COMMAND,
+ "-import",
+ "-noprompt",
+ "-alias", alias,
+ "-file", certificateFile.getAbsolutePath(),
+ "-keystore", keyStorePath,
+ "-keypass", keyStorePIN,
+ "-storetype", keyStoreType,
+ "-storepass", keyStorePIN
+ };
+ runKeyTool(commandElements, true);
+ }
+
+
+
+ /**
+ * Removes the specified certificate from the key store.
+ *
+ * @param alias The alias to use for the certificate to remove. It must not
+ * be {@code null} or an empty string, and it must exist in
+ * the key store.
+ *
+ * @throws IllegalArgumentException If the specified certificate does not
+ * exist in the key store.
+ *
+ * @throws KeyStoreException If a problem occurs while interacting with the
+ * key store.
+ *
+ * @throws NullPointerException If the provided alias is {@code null} or a
+ * zero-length string, or the certificate file
+ * is {@code null}.
+ *
+ * @throws UnsupportedOperationException If it is not possible to use the
+ * keytool utility to alter the
+ * contents of the key store.
+ */
+ public void removeCertificate(String alias)
+ throws IllegalArgumentException, KeyStoreException,
+ NullPointerException, UnsupportedOperationException
+ {
+ if ((alias == null) || (alias.length() == 0))
+ {
+ throw new NullPointerException("alias");
+ }
+
+ if (KEYTOOL_COMMAND == null)
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new UnsupportedOperationException("The certificate manager may " +
+ "not be used to alter the contents of key stores on " +
+ "this system.");
+ }
+
+ if (! aliasInUse(alias))
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new IllegalArgumentException("There is no certificate with alias " +
+ alias + " in the key store.");
+ }
+
+
+ // Clear the reference to the key store, since it will be altered by
+ // invoking the KeyTool command.
+ keyStore = null;
+
+
+ String[] commandElements =
+ {
+ KEYTOOL_COMMAND,
+ "-delete",
+ "-alias", alias,
+ "-keystore", keyStorePath,
+ "-keypass", keyStorePIN,
+ "-storetype", keyStoreType,
+ "-storepass", keyStorePIN
+ };
+ runKeyTool(commandElements, false);
+ }
+
+
+
+ /**
+ * Attempts to run the keytool utility with the provided arguments.
+ *
+ * @param commandElements The command and arguments to execute. The first
+ * element of the array must be the command, and the
+ * remaining elements must be the arguments.
+ * @param outputAcceptable Indicates whether it is acceptable for the
+ * command to generate output, as long as the exit
+ * code is zero. Some commands (like "keytool
+ * -import") may generate output even on successful
+ * completion. If the command generates output and
+ * this is {@code false}, then an exception will
+ * be thrown.
+ *
+ * @throws KeyStoreException If a problem occurs while attempting to invoke
+ * the keytool utility, if it does not exit with
+ * the expected exit code, or if any unexpected
+ * output is generated while running the tool.
+ */
+ private void runKeyTool(String[] commandElements, boolean outputAcceptable)
+ throws KeyStoreException
+ {
+ try
+ {
+ ProcessBuilder processBuilder = new ProcessBuilder(commandElements);
+ processBuilder.redirectErrorStream(true);
+
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ Process process = processBuilder.start();
+ InputStream inputStream = process.getInputStream();
+ while (true)
+ {
+ int bytesRead = inputStream.read(buffer);
+ if (bytesRead < 0)
+ {
+ break;
+ }
+ else if (bytesRead > 0)
+ {
+ output.write(buffer, 0, bytesRead);
+ }
+ }
+
+ process.waitFor();
+ int exitValue = process.exitValue();
+ byte[] outputBytes = output.toByteArray();
+ if (exitValue != 0)
+ {
+ // FIXME -- Make this an internationalizeable string.
+ StringBuilder message = new StringBuilder();
+ message.append("Unexpected exit code of ");
+ message.append(exitValue);
+ message.append(" returned from the keytool utility.");
+
+ if ((outputBytes != null) && (outputBytes.length > 0))
+ {
+ message.append(" The generated output was: '");
+ message.append(new String(outputBytes));
+ message.append("'.");
+ }
+
+ throw new KeyStoreException(message.toString());
+ }
+ else if ((! outputAcceptable) && (outputBytes != null) &&
+ (outputBytes.length > 0))
+ {
+ // FIXME -- Make this an internationalizeable string.
+ StringBuilder message = new StringBuilder();
+ message.append("Unexpected output generated by the keytool " +
+ "utility: '");
+ message.append(new String(outputBytes));
+ message.append("'.");
+
+ throw new KeyStoreException(message.toString());
+ }
+ }
+ catch (KeyStoreException kse)
+ {
+ throw kse;
+ }
+ catch (Exception e)
+ {
+ // FIXME -- Make this an internationalizeable string.
+ throw new KeyStoreException("Could not invoke the KeyTool.run method: " +
+ e, e);
+ }
+ }
+
+
+
+ /**
+ * Retrieves a handle to the key store.
+ *
+ * @return The handle to the key store, or {@code null} if the key store
+ * doesn't exist.
+ *
+ * @throws KeyStoreException If a problem occurs while trying to open the
+ * key store.
+ */
+ private KeyStore getKeyStore()
+ throws KeyStoreException
+ {
+ if (keyStore != null)
+ {
+ return keyStore;
+ }
+
+ // For JKS and PKCS12 key stores, we should make sure the file exists, and
+ // we'll need an input stream that we can use to read it. For PKCS11 key
+ // stores there won't be a file and the input stream should be null.
+ FileInputStream keyStoreInputStream = null;
+ if (keyStoreType.equals(KEY_STORE_TYPE_JKS) ||
+ keyStoreType.equals(KEY_STORE_TYPE_PKCS12))
+ {
+ File keyStoreFile = new File(keyStorePath);
+ if (! keyStoreFile.exists())
+ {
+ return null;
+ }
+
+ try
+ {
+ keyStoreInputStream = new FileInputStream(keyStoreFile);
+ }
+ catch (Exception e)
+ {
+ throw new KeyStoreException(String.valueOf(e), e);
+ }
+ }
+
+
+ KeyStore keyStore = KeyStore.getInstance(keyStoreType);
+ try
+ {
+ keyStore.load(keyStoreInputStream, keyStorePIN.toCharArray());
+ return this.keyStore = keyStore;
+ }
+ catch (Exception e)
+ {
+ throw new KeyStoreException(String.valueOf(e), e);
+ }
+ }
+}
+
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/util/CertificateManagerTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/util/CertificateManagerTestCase.java
new file mode 100644
index 0000000..b08ba9f
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/util/CertificateManagerTestCase.java
@@ -0,0 +1,1416 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.util;
+
+
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.security.KeyStoreException;
+import java.security.cert.Certificate;
+import java.util.Arrays;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import org.opends.server.TestCaseUtils;
+
+import static org.testng.Assert.*;
+
+
+
+/**
+ * A set of generic test cases for the certificate manager class.
+ */
+public class CertificateManagerTestCase
+ extends UtilTestCase
+{
+ /**
+ * Indicates whether the certificate manager is available on this platform and
+ * should be tested.
+ */
+ public static final boolean CERT_MANAGER_AVAILABLE =
+ CertificateManager.mayUseCertificateManager();
+
+
+
+ /**
+ * The path to a JKS key store file.
+ */
+ public static final String JKS_KEY_STORE_PATH =
+ System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT) + File.separator +
+ "build" + File.separator + "unit-tests" + File.separator + "package" +
+ File.separator + "config" + File.separator + "server.keystore";
+
+
+
+ /**
+ * The path to a PKCS#12 key store file.
+ */
+ public static final String PKCS12_KEY_STORE_PATH =
+ System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT) + File.separator +
+ "build" + File.separator + "unit-tests" + File.separator + "package" +
+ File.separator + "config" + File.separator + "server-cert.p12";
+
+
+
+ /**
+ * The path to the unit test working directory.
+ */
+ public static final String TEST_DIR =
+ System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT) + File.separator +
+ "build" + File.separator + "unit-tests" + File.separator + "package";
+
+
+
+ /**
+ * Make sure the server is running.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @BeforeClass()
+ public void startServer()
+ throws Exception
+ {
+ TestCaseUtils.startServer();
+ }
+
+
+
+ /**
+ * Tests the CertificateManager constructor using a null argument for the key
+ * store path.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test(expectedExceptions = { NullPointerException.class })
+ public void testConstructorNullPath()
+ throws Exception
+ {
+ new CertificateManager(null, "JKS", "password");
+ }
+
+
+
+ /**
+ * Tests the CertificateManager constructor using an empty string for the key
+ * store path.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test(expectedExceptions = { NullPointerException.class })
+ public void testConstructorEmptyPath()
+ throws Exception
+ {
+ new CertificateManager("", "JKS", "password");
+ }
+
+
+
+ /**
+ * Tests the CertificateManager constructor using a key store path that refers
+ * to a file in a nonexistent directory.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test(expectedExceptions = { IllegalArgumentException.class })
+ public void testConstructorNonexistentPath()
+ throws Exception
+ {
+ String path = TEST_DIR + File.separator + "nonexistent" + File.separator +
+ "doesntmatter";
+
+ new CertificateManager(path, "JKS", "password");
+ }
+
+
+
+ /**
+ * Tests the CertificateManager constructor using a key store path that refers
+ * to a file that exists but isn't a file.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test(expectedExceptions = { IllegalArgumentException.class })
+ public void testConstructorPathNotFile()
+ throws Exception
+ {
+ new CertificateManager(TEST_DIR, "JKS", "password");
+ }
+
+
+
+ /**
+ * Tests the CertificateManager constructor using a null argument for the key
+ * store type.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test(expectedExceptions = { NullPointerException.class })
+ public void testConstructorNullType()
+ throws Exception
+ {
+ new CertificateManager(JKS_KEY_STORE_PATH, null, "password");
+ }
+
+
+
+ /**
+ * Tests the CertificateManager constructor using an empty string for the key
+ * store type.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test(expectedExceptions = { NullPointerException.class })
+ public void testConstructorEmptyType()
+ throws Exception
+ {
+ new CertificateManager(JKS_KEY_STORE_PATH, "", "password");
+ }
+
+
+
+ /**
+ * Tests the CertificateManager constructor using an invalid key store type.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test(expectedExceptions = { IllegalArgumentException.class })
+ public void testConstructorInvalidType()
+ throws Exception
+ {
+ new CertificateManager(JKS_KEY_STORE_PATH, "invalid", "password");
+ }
+
+
+
+ /**
+ * Tests the CertificateManager constructor using an invalid key store path
+ * in conjunction with the PKCS11 key store type..
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test(expectedExceptions = { IllegalArgumentException.class })
+ public void testConstructorInvalidPKCS11Path()
+ throws Exception
+ {
+ new CertificateManager(JKS_KEY_STORE_PATH, "PKCS11", "password");
+ }
+
+
+
+ /**
+ * Tests the CertificateManager constructor using a null argument for the key
+ * store PIN.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test(expectedExceptions = { NullPointerException.class })
+ public void testConstructorNullPIN()
+ throws Exception
+ {
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", null);
+ }
+
+
+
+ /**
+ * Tests the CertificateManager constructor using an empty string for the key
+ * store PIN.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test(expectedExceptions = { NullPointerException.class })
+ public void testConstructorEmptyPIN()
+ throws Exception
+ {
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "");
+ }
+
+
+
+ /**
+ * Tests the certificate manager with a valid constructor using the JKS key
+ * store type.
+ */
+ @Test()
+ public void testValidConstructorJKS()
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+ }
+
+
+
+ /**
+ * Tests the certificate manager with a valid constructor using the PKCS12 key
+ * store type.
+ */
+ @Test()
+ public void testValidConstructorPKCS12()
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ new CertificateManager(PKCS12_KEY_STORE_PATH, "PKCS12", "password");
+ }
+
+
+
+ /**
+ * Tests the {@code aliasInUse} method with a null alias.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testAliasInUseNull()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.aliasInUse(null);
+ fail("Expected an NPE due to null alias");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code aliasInUse} method with an empty alias.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testAliasInUseEmpty()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.aliasInUse("");
+ fail("Expected an NPE due to empty alias");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code aliasInUse} method with an invalid key store.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testAliasInUseInvalidKeyStore()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ File path = File.createTempFile("testAliasInUseInvalidKeyStore",
+ ".notakeystore");
+ path.deleteOnExit();
+ FileOutputStream outputStream = new FileOutputStream(path, false);
+ outputStream.write("This is not a valid key store.".getBytes());
+ outputStream.close();
+
+ CertificateManager certManager =
+ new CertificateManager(path.getAbsolutePath(), "JKS", "password");
+
+ try
+ {
+ certManager.aliasInUse("doesntmatter");
+ fail("Expected a key store exception due to an invalid key store");
+ } catch (KeyStoreException kse) {}
+
+ path.delete();
+ }
+
+
+
+ /**
+ * Tests the {@code aliasInUse} method for a key store using the JKS type.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testAliasInUseJKS()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+ assertTrue(certManager.aliasInUse("server-cert"));
+ assertFalse(certManager.aliasInUse("nonexistent"));
+
+ String path = TEST_DIR + File.separator + "nonexistent";
+ certManager = new CertificateManager(path, "JKS", "password");
+ assertFalse(certManager.aliasInUse("doesntmatter"));
+ }
+
+
+
+ /**
+ * Tests the {@code aliasInUse} method for a key store using the PKCS12 type.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testAliasInUsePKCS12()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(PKCS12_KEY_STORE_PATH, "PKCS12", "password");
+ assertTrue(certManager.aliasInUse("server-cert"));
+ assertFalse(certManager.aliasInUse("nonexistent"));
+
+ String path = TEST_DIR + File.separator + "nonexistent";
+ certManager = new CertificateManager(path, "PKCS12", "password");
+ assertFalse(certManager.aliasInUse("doesntmatter"));
+ }
+
+
+
+ /**
+ * Tests the {@code getCertificateAliases} method for a key store using the
+ * JKS type.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGetCertificateAliasesJKS()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ String[] aliases = certManager.getCertificateAliases();
+ assertNotNull(aliases);
+ assertTrue(aliases.length > 0);
+ assertTrue(Arrays.asList(aliases).contains("server-cert"));
+
+ String path = TEST_DIR + File.separator + "nonexistent";
+ certManager = new CertificateManager(path, "JKS", "password");
+ assertNull(certManager.getCertificateAliases());
+ }
+
+
+
+ /**
+ * Tests the {@code getCertificateAliases} method for a key store using the
+ * PKCS12 type.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGetCertificateAliasesPKCS12()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(PKCS12_KEY_STORE_PATH, "PKCS12", "password");
+
+ String[] aliases = certManager.getCertificateAliases();
+ assertNotNull(aliases);
+ assertTrue(aliases.length > 0);
+ assertTrue(Arrays.asList(aliases).contains("server-cert"));
+
+ String path = TEST_DIR + File.separator + "nonexistent";
+ certManager = new CertificateManager(path, "PKCS12", "password");
+ assertNull(certManager.getCertificateAliases());
+ }
+
+
+
+ /**
+ * Tests the {@code getCertificate} method using a null alias.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGetCertificateNull()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.getCertificate(null);
+ fail("Expected an NPE due to a null alias");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code getCertificate} method using an empty alias.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGetCertificateEmpty()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.getCertificate("");
+ fail("Expected an NPE due to a null alias");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code getCertificate} method for a key store using the JKS type.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGetCertificateJKS()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+ assertNotNull(certManager.getCertificate("server-cert"));
+ assertNull(certManager.getCertificate("nonexistent"));
+
+ String path = TEST_DIR + File.separator + "nonexistent";
+ certManager = new CertificateManager(path, "JKS", "password");
+ try
+ {
+ certManager.getCertificate("doesntmatter");
+ fail("Expected a key store exception due to a nonexistent key store");
+ } catch (KeyStoreException kse) {}
+ }
+
+
+
+ /**
+ * Tests the {@code getCertificate} method for a key store using the PKCS12
+ * type.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGetCertificatePKCS12()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(PKCS12_KEY_STORE_PATH, "PKCS12", "password");
+ assertNotNull(certManager.getCertificate("server-cert"));
+ assertNull(certManager.getCertificate("nonexistent"));
+
+ String path = TEST_DIR + File.separator + "nonexistent";
+ certManager = new CertificateManager(path, "PKCS12", "password");
+ try
+ {
+ certManager.getCertificate("doesntmatter");
+ fail("Expected a key store exception due to a nonexistent key store");
+ } catch (KeyStoreException kse) {}
+ }
+
+
+
+ /**
+ * Tests the {@code generateSelfSignedCertificate} method using a null alias.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateSelfSignedCertificateNullAlias()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.generateSelfSignedCertificate(null, "CN=Test,O=test", 365);
+ fail("Expected an NPE due to a null alias");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code generateSelfSignedCertificate} method using an empty
+ * alias.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateSelfSignedCertificateEmptyAlias()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.generateSelfSignedCertificate("", "CN=Test,O=test", 365);
+ fail("Expected an NPE due to an empty alias");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code generateSelfSignedCertificate} method using an alias
+ * that's already being used.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateSelfSignedCertificateAliasInUse()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.generateSelfSignedCertificate("server-cert", "CN=Test,O=test",
+ 365);
+ fail("Expected an illegal argument exception to a duplicate alias");
+ } catch (IllegalArgumentException iae) {}
+ }
+
+
+
+ /**
+ * Tests the {@code generateSelfSignedCertificate} method using a null
+ * subject.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateSelfSignedCertificateNullSubject()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.generateSelfSignedCertificate("test-cert", null, 365);
+ fail("Expected an NPE due to a null subject");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code generateSelfSignedCertificate} method using an empty
+ * subject.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateSelfSignedCertificateEmptySubject()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.generateSelfSignedCertificate("test-cert", "", 365);
+ fail("Expected an NPE due to an empty subject");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code generateSelfSignedCertificate} method using an invalid
+ * subject.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateSelfSignedCertificateInvalidSubject()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ File path = File.createTempFile("testGenerateSelfSignedCertificateJKS",
+ ".keystore");
+ path.deleteOnExit();
+ path.delete();
+
+ CertificateManager certManager =
+ new CertificateManager(path.getAbsolutePath(), "JKS", "password");
+ try
+ {
+ certManager.generateSelfSignedCertificate("test-cert", "invalid", 365);
+ fail("Expected a key store exception due to an invalid subject");
+ } catch (KeyStoreException cse) {}
+ path.delete();
+ }
+
+
+
+ /**
+ * Tests the {@code generateSelfSignedCertificate} method using an invalid
+ * validity.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateSelfSignedCertificateInvalidValidity()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.generateSelfSignedCertificate("test-cert", "CN=Test,o=test",
+ 0);
+ fail("Expected an illegal argument exception due to an invalid validity");
+ } catch (IllegalArgumentException iae) {}
+ }
+
+
+
+ /**
+ * Tests the {@code generateSelfSignedCertificate} method for a JKS key store.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateSelfSignedCertificateJKS()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ File path = File.createTempFile("testGenerateSelfSignedCertificateJKS",
+ ".keystore");
+ path.deleteOnExit();
+ path.delete();
+
+ CertificateManager certManager =
+ new CertificateManager(path.getAbsolutePath(), "JKS", "password");
+ certManager.generateSelfSignedCertificate("test-cert", "CN=Test,o=test",
+ 365);
+ assertTrue(certManager.aliasInUse("test-cert"));
+ path.delete();
+ }
+
+
+
+ /**
+ * Tests the {@code generateSelfSignedCertificate} method for a PKCS12 key
+ * store.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateSelfSignedCertificatePKCS12()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ File path = File.createTempFile("testGenerateSelfSignedCertificatePKCS12",
+ ".p12");
+ path.deleteOnExit();
+ path.delete();
+
+ CertificateManager certManager =
+ new CertificateManager(path.getAbsolutePath(), "PKCS12", "password");
+ certManager.generateSelfSignedCertificate("test-cert", "CN=Test,o=test",
+ 365);
+ assertTrue(certManager.aliasInUse("test-cert"));
+ path.delete();
+ }
+
+
+
+ /**
+ * Tests the {@code generateCertificateSigningRequest} method using a null
+ * alias.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateCSRNullAlias()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.generateCertificateSigningRequest(null, "CN=Test,O=test");
+ fail("Expected an NPE due to a null alias");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code generateCertificateSigningRequest} method using an empty
+ * alias.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateCSREmptyAlias()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.generateCertificateSigningRequest("", "CN=Test,O=test");
+ fail("Expected an NPE due to an empty alias");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code generateCertificateSigningRequest} method using an alias
+ * that's already being used.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateCSRAliasInUse()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.generateCertificateSigningRequest("server-cert",
+ "CN=Test,O=test");
+ fail("Expected an illegal argument exception to a duplicate alias");
+ } catch (IllegalArgumentException iae) {}
+ }
+
+
+
+ /**
+ * Tests the {@code generateCertificateSigningRequest} method using a null
+ * subject.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateCSRNullSubject()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.generateCertificateSigningRequest("test-cert", null);
+ fail("Expected an NPE due to a null subject");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code generateCertificateSigningRequest} method using an empty
+ * subject.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateCSREmptySubject()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.generateCertificateSigningRequest("test-cert", "");
+ fail("Expected an NPE due to an empty subject");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code generateCertificateSigningRequest} method using an invalid
+ * subject.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateCSRInvalidSubject()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ File path = File.createTempFile("testGenerateCSRJKS",
+ ".keystore");
+ path.deleteOnExit();
+ path.delete();
+
+ CertificateManager certManager =
+ new CertificateManager(path.getAbsolutePath(), "JKS", "password");
+
+ try
+ {
+ File requestFile =
+ certManager.generateCertificateSigningRequest("test-cert",
+ "invalid");
+ requestFile.delete();
+ fail("Expected a key store exception due to an invalid subject");
+ } catch (KeyStoreException cse) {}
+ }
+
+
+
+ /**
+ * Tests the {@code generateCertificateSigningRequest} method for a JKS key
+ * store.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateCSRJKS()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ File path = File.createTempFile("testGenerateCSRJKS",
+ ".keystore");
+ path.deleteOnExit();
+ path.delete();
+
+ CertificateManager certManager =
+ new CertificateManager(path.getAbsolutePath(), "JKS", "password");
+ File csrFile = certManager.generateCertificateSigningRequest("test-cert",
+ "CN=Test,o=test");
+ assertNotNull(csrFile);
+ assertTrue(csrFile.length() > 0);
+ path.delete();
+ }
+
+
+
+ /**
+ * Tests the {@code generateCertificateSigningRequest} method for a PKCS12 key
+ * store.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testGenerateCSRPKCS12()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ File path = File.createTempFile("testGenerateCSRPKCS12",
+ ".p12");
+ path.deleteOnExit();
+ path.delete();
+
+ CertificateManager certManager =
+ new CertificateManager(path.getAbsolutePath(), "PKCS12", "password");
+ File csrFile = certManager.generateCertificateSigningRequest("test-cert",
+ "CN=Test,o=test");
+ assertNotNull(csrFile);
+ assertTrue(csrFile.length() > 0);
+ path.delete();
+ }
+
+
+
+ /**
+ * Tests the {@code addCertificate} method using a null alias.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testAddCertificateNullAlias()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+ File exportFile = exportCertificate();
+
+ try
+ {
+ certManager.addCertificate(null, exportFile);
+ fail("Expected an NPE due to a null alias");
+ } catch (NullPointerException npe) {}
+
+ exportFile.delete();
+ }
+
+
+
+ /**
+ * Tests the {@code addCertificate} method using an empty alias.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testAddCertificateEmptyAlias()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+ File exportFile = exportCertificate();
+
+ try
+ {
+ certManager.addCertificate("", exportFile);
+ fail("Expected an NPE due to an empty alias");
+ } catch (NullPointerException npe) {}
+
+ exportFile.delete();
+ }
+
+
+
+ /**
+ * Tests the {@code addCertificate} method using a null certificate file.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testAddCertificateNullCertificateFile()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.addCertificate("test-cert", null);
+ fail("Expected an NPE due to a null certificate file");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code addCertificate} method using a certificate file that does
+ * not exist.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testAddCertificateMissingCertificateFile()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ File f = new File(TEST_DIR, "nonexistent");
+
+ try
+ {
+ certManager.addCertificate("test-cert", f);
+ fail("Expected an illegal argument exception due to a missing " +
+ "certificate file");
+ } catch (IllegalArgumentException iae) {}
+ }
+
+
+
+ /**
+ * Tests the {@code addCertificate} method using a certificate file that is
+ * not a file.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testAddCertificateFileNotFile()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ File f = new File(TEST_DIR);
+
+ try
+ {
+ certManager.addCertificate("test-cert", f);
+ fail("Expected an illegal argument exception due to a certificate file " +
+ "actually being a directory");
+ } catch (IllegalArgumentException iae) {}
+ }
+
+
+
+ /**
+ * Tests the {@code addCertificate} method using a certificate file that
+ * contains something other than a certificate.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testAddCertificateFileNotCertificate()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ File path = File.createTempFile("testAddCertificateFileNotCertificate",
+ ".notacertificate");
+ path.deleteOnExit();
+ FileOutputStream outputStream = new FileOutputStream(path, false);
+ outputStream.write("This is not a valid certificate.".getBytes());
+ outputStream.close();
+
+ try
+ {
+ certManager.addCertificate("test-cert", path);
+ fail("Expected a key store exception due to an invalid certificate");
+ } catch (KeyStoreException kse) {}
+
+ path.delete();
+ }
+
+
+
+ /**
+ * Tests the {@code removeCertificate} method using a null alias.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testRemoveCertificateNullAlias()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.removeCertificate(null);
+ fail("Expected an NPE due to a null alias");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code removeCertificate} method using an empty alias.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testRemoveCertificateEmptyAlias()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.removeCertificate("");
+ fail("Expected an NPE due to an empty alias");
+ } catch (NullPointerException npe) {}
+ }
+
+
+
+ /**
+ * Tests the {@code removeCertificate} method using an alias that doesn't
+ * exist.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testRemoveCertificateNonexistentAlias()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ try
+ {
+ certManager.removeCertificate("nonexistent");
+ fail("Expected an illegal argument exception due to a nonexistent alias");
+ } catch (IllegalArgumentException iae) {}
+ }
+
+
+
+ /**
+ * Tests the {@code addCertificate} and {@code removeCertificate} methods
+ * using a newly-created JKS key store.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ @Test()
+ public void testAddAndRemoveCertificateJKS()
+ throws Exception
+ {
+ if (! CERT_MANAGER_AVAILABLE)
+ {
+ return;
+ }
+
+ File path = File.createTempFile("testAddAndRemoveCertificateJKS",
+ ".keystore");
+ path.deleteOnExit();
+ path.delete();
+
+ CertificateManager certManager =
+ new CertificateManager(path.getAbsolutePath(), "JKS", "password");
+
+ File exportFile = exportCertificate();
+ certManager.addCertificate("test-cert", exportFile);
+ assertTrue(certManager.aliasInUse("test-cert"));
+ assertNotNull(certManager.getCertificate("test-cert"));
+
+ certManager.removeCertificate("test-cert");
+ assertFalse(certManager.aliasInUse("test-cert"));
+ assertNull(certManager.getCertificate("test-cert"));
+
+ exportFile.delete();
+ path.delete();
+ }
+
+
+
+ /**
+ * Exports a certificate to a temporary file.
+ *
+ * @throws Exception If a problem occurs.
+ */
+ private File exportCertificate()
+ throws Exception
+ {
+ File path = File.createTempFile("exportCertificate",
+ ".cert");
+ path.deleteOnExit();
+ path.delete();
+
+ CertificateManager certManager =
+ new CertificateManager(JKS_KEY_STORE_PATH, "JKS", "password");
+
+ Certificate certificate = certManager.getCertificate("server-cert");
+ assertNotNull(certificate);
+
+ byte[] certificateBytes = certificate.getEncoded();
+ assertNotNull(certificateBytes);
+ assertTrue(certificateBytes.length > 0);
+
+ FileOutputStream outputStream = new FileOutputStream(path, false);
+ outputStream.write(certificateBytes);
+ outputStream.close();
+
+ return path;
+ }
+}
+
--
Gitblit v1.10.0