opendj-cli/src/main/java/com/forgerock/opendj/cli/ConnectionFactoryProvider.java
@@ -339,6 +339,24 @@ } /** * Indicate if the SSL mode is required. * * @return True if SSL mode is required */ public boolean useSSL() { return useSSLArg.isPresent(); } /** * Indicate if the startTLS mode is required. * * @return True if startTLS mode is required */ public boolean useStartTLS() { return useStartTLSArg.isPresent(); } /** * Checks if any conflicting arguments are present, build the connection with * selected arguments and returns the connection factory. * @@ -351,6 +369,53 @@ if (connFactory == null) { port = portArg.getIntValue(); checkForConflictingArguments(); try { if (useSSLArg.isPresent() || useStartTLSArg.isPresent()) { String clientAlias; if (certNicknameArg.isPresent()) { clientAlias = certNicknameArg.getValue(); } else { clientAlias = null; } if (sslContext == null) { final TrustManager trustManager = getTrustManager(); X509KeyManager keyManager = null; final X509KeyManager akm = getKeyManager(keyStorePathArg.getValue()); if (akm != null && clientAlias != null) { keyManager = KeyManagers.useSingleCertificate(clientAlias, akm); } sslContext = new SSLContextBuilder().setTrustManager(trustManager) .setKeyManager(keyManager).getSSLContext(); } } } catch (final Exception e) { throw new ArgumentException(ERR_LDAP_CONN_CANNOT_INITIALIZE_SSL.get(e.toString()), e); } if (sslContext != null) { options.setSSLContext(sslContext).setUseStartTLS(useStartTLSArg.isPresent()); } connFactory = new LDAPConnectionFactory(hostNameArg.getValue(), port, options); } return connFactory; } /** * Verifies if the arguments are not conflicting together or if they are readable. * * @throws ArgumentException * If arguments are conflicting or if the files cannot be read, * an argument exception is thrown. */ private void checkForConflictingArguments() throws ArgumentException { // Couldn't have at the same time bindPassword and bindPasswordFile if (bindPasswordArg.isPresent() && bindPasswordFileArg.isPresent()) { final LocalizableMessage message = @@ -416,42 +481,6 @@ .getLongIdentifier()); throw new ArgumentException(message); } try { if (useSSLArg.isPresent() || useStartTLSArg.isPresent()) { String clientAlias; if (certNicknameArg.isPresent()) { clientAlias = certNicknameArg.getValue(); } else { clientAlias = null; } if (sslContext == null) { final TrustManager trustManager = getTrustManager(); X509KeyManager keyManager = null; final X509KeyManager akm = getKeyManager(keyStorePathArg.getValue()); if (akm != null && clientAlias != null) { keyManager = KeyManagers.useSingleCertificate(clientAlias, akm); } sslContext = new SSLContextBuilder().setTrustManager(trustManager) .setKeyManager(keyManager).getSSLContext(); } } } catch (final Exception e) { throw new ArgumentException(ERR_LDAP_CONN_CANNOT_INITIALIZE_SSL.get(e.toString()), e); } if (sslContext != null) { options.setSSLContext(sslContext).setUseStartTLS(useStartTLSArg.isPresent()); } connFactory = new LDAPConnectionFactory(hostNameArg.getValue(), port, options); } return connFactory; } /** @@ -739,10 +768,12 @@ * * @return A set of <CODE>TrustManager</CODE> objects that may be used for * interactions requiring access to a trust manager. * @throws IOException * If the trust store file could not be found or could not be read. * @throws GeneralSecurityException * If a problem occurs while interacting with the trust store. */ private TrustManager getTrustManager() throws IOException, GeneralSecurityException { public TrustManager getTrustManager() throws IOException, GeneralSecurityException { if (trustAllArg.isPresent()) { return TrustManagers.trustAll(); } opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java
@@ -51,6 +51,8 @@ import javax.net.ssl.SSLHandshakeException; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.i18n.LocalizableMessageBuilder; import org.forgerock.i18n.LocalizableMessageDescriptor; import org.forgerock.opendj.ldap.DN; import org.forgerock.opendj.ldap.RDN; @@ -492,6 +494,30 @@ } /** * Returns a localized message for a given properties key an throwable. * * @param message * prefix * @param t * the throwable for which we want to get a message. * @return a localized message for a given properties key and throwable. */ public static LocalizableMessage getThrowableMsg(final LocalizableMessage message, final Throwable t) { final LocalizableMessageBuilder mb = new LocalizableMessageBuilder(message); LocalizableMessageDescriptor.Arg1<Object> tag; if (isOutOfMemory(t)) { tag = INFO_EXCEPTION_OUT_OF_MEMORY_DETAILS; } else { tag = INFO_EXCEPTION_DETAILS; } String detail = t.toString(); if (detail != null) { mb.append(" ").append(tag.get(detail)); } return mb.toMessage(); } /** * Returns <CODE>true</CODE> if we can write on the provided path and <CODE>false</CODE> otherwise. * * @param path @@ -517,7 +543,7 @@ * Returns {@code true} if the the provided string is a DN and {@code false} otherwise. * * @param dn * the String we are analyzing. * The String we are analyzing. * @return {@code true} if the the provided string is a DN and {@code false} otherwise. */ public static boolean isDN(String dn) { @@ -536,7 +562,30 @@ * The UID to be used to generate the DN. * @return The DN of the administrator for the given UID. */ private static String getAdministratorDN(String uid) { public static String getAdministratorDN(String uid) { return "cn=" + RDN.valueOf(uid) + ",cn=Administrators, cn=admin data"; } /** * Tells whether this throwable has been generated for an out of memory error or not. * * @param t * The throwable to analyze. * @return {@code true} if the throwable was generated by an out of memory error and false otherwise. */ private static boolean isOutOfMemory(Throwable t) { boolean isOutOfMemory = false; while (!isOutOfMemory && (t != null)) { if (t instanceof OutOfMemoryError) { isOutOfMemory = true; } else if (t instanceof IOException) { final String msg = t.toString(); if (msg != null) { isOutOfMemory = msg.contains("Not enough space"); } } t = t.getCause(); } return isOutOfMemory; } } opendj-cli/src/main/resources/com/forgerock/opendj/cli/cli.properties
@@ -461,6 +461,7 @@ INFO_CATEGORY_PLACEHOLDER={category} INFO_PSEARCH_PLACEHOLDER=ps[:changetype[:changesonly[:entrychgcontrols]]] INFO_ADMINUID_PLACEHOLDER={adminUID} INFO_NOT_AVAILABLE_LABEL=<not available> ERR_CANNOT_READ_TRUSTSTORE=Cannot access trust store '%s'. Verify \ that the provided trust store exists and that you have read access rights to it ERR_CANNOT_READ_KEYSTORE=Cannot access key store '%s'. Verify \ @@ -887,4 +888,66 @@ ERR_FAILED_TO_CONNECT_NOT_TRUSTED=Unable to connect to the \ server at %s on port %s. In non-interactive mode, if the trustStore related parameters are not used, \ you must use the '--trustAll' option for remote connections INFO_EXCEPTION_OUT_OF_MEMORY_DETAILS=Not enough memory to perform the \ operation. Details: %s INFO_EXCEPTION_DETAILS=Details: %s INFO_LDAP_CONN_PROMPT_SECURITY_LDAP=LDAP INFO_LDAP_CONN_PROMPT_SECURITY_USE_SSL=LDAP with SSL INFO_LDAP_CONN_PROMPT_SECURITY_USE_START_TLS=LDAP with StartTLS INFO_LDAP_CONN_PROMPT_SECURITY_USE_TRUST_ALL=Automatically \ trust INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PATH=Truststore path: INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE_PASSWORD=Password for \ truststore '%s': INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PATH=Keystore path: INFO_LDAP_CONN_PROMPT_SECURITY_KEYSTORE_PASSWORD=Password for keystore \ '%s': INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS=>>>> Specify OpenDJ LDAP \ connection parameters ERR_LDAP_CONN_BAD_HOST_NAME=The hostname "%s" could not be \ resolved. Please check you have provided the correct address ERR_LDAP_CONN_BAD_PORT_NUMBER=Invalid port number "%s". Please \ enter a valid port number between 1 and 65535 INFO_LDAP_CONN_PROMPT_HOST_NAME=Directory server hostname or IP address \ [%s]: INFO_LDAP_CONN_PROMPT_SECURITY_USE_SECURE_CTX=How do you want to connect? INFO_LDAP_CONN_PROMPT_SECURITY_PROTOCOL_DEFAULT_CHOICE=%d ERR_LDAP_CONN_PROMPT_SECURITY_INVALID_FILE_PATH=The provided path \ is not valid INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_METHOD=How do you want to trust the server certificate? INFO_LDAP_CONN_PROMPT_SECURITY_TRUSTSTORE=Use a truststore INFO_LDAP_CONN_PROMPT_SECURITY_MANUAL_CHECK=Manually validate INFO_LDAP_CONN_PROMPT_SECURITY_SERVER_CERTIFICATE=Server Certificate: INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE=%s INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION=Do you trust this server certificate? INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_NO=No INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_SESSION=Yes, for this session only INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_ALWAYS=Yes, also add it to a truststore INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_DETAILS=View certificate details INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_USER_DN=User DN : %s INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_VALIDITY=Validity : From '%s'%n To '%s' INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_ISSUER=Issuer : %s INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_ALIASES=Which certificate do you want to use? INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_ALIAS=%s (%s) INFO_LDAP_CONN_PROMPT_ADMINISTRATOR_UID=Global Administrator User ID [%s]: INFO_LDAP_CONN_GLOBAL_ADMINISTRATOR_OR_BINDDN_PROMPT=Global Administrator \ User ID, or bind DN if no Global Administrator is defined [%s]: INFO_LDAP_CONN_PROMPT_PORT_NUMBER=Directory server port number [%d]: INFO_LDAP_CONN_PROMPT_BIND_DN=Administrator user bind DN [%s]: INFO_ADMIN_CONN_PROMPT_PORT_NUMBER=Directory server administration port number [%d]: INFO_ERROR_CONNECTING_TO_LOCAL=An error occurred connecting to the server INFO_CERTIFICATE_NOT_TRUSTED_TEXT_CLI=The Certificate presented by the server \ %s:%s could not be trusted.\nPossible reasons for this error:\n\ -The Certificate Authority that issued the certificate is not recognized (this \ is the case of the self-signed certificates).\n-The server's certificate is \ incomplete due to a misconfiguration.\n-The server's certificate has \ expired.\n-There is a time difference between the server machine clock and \ the local machine clock.\nBefore accepting this certificate, you should \ examine the server's certificate carefully. INFO_CERTIFICATE_NAME_MISMATCH_TEXT_CLI=The Certificate presented by the server \ %s:%s could not be trusted.\nThere is a name mismatch between the name of \ the server (%s) and the subject DN of the certificate. This could be caused \ because you are connected to a server pretending to be %s:%s.\n\ Before accepting this certificate, you should examine the server's \ certificate carefully.