| | |
| | | |
| | | package org.opends.quicksetup; |
| | | |
| | | |
| | | import org.opends.admin.ads.util.ApplicationTrustManager; |
| | | import org.opends.quicksetup.ui.CertificateDialog; |
| | | import org.opends.messages.Message; |
| | | import org.opends.messages.MessageBuilder; |
| | | import static org.opends.messages.AdminToolMessages.*; |
| | | import static org.opends.messages.QuickSetupMessages.*; |
| | | |
| | | import org.opends.quicksetup.util.Utils; |
| | | import org.opends.server.util.args.ArgumentParser; |
| | | import org.opends.server.util.args.ArgumentException; |
| | | import org.opends.server.util.args.BooleanArgument; |
| | | import org.opends.server.util.PasswordReader; |
| | | import org.opends.server.util.StaticUtils; |
| | | |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.InputStream; |
| | | import java.io.PrintStream; |
| | | import java.net.URI; |
| | | import java.security.cert.X509Certificate; |
| | | import java.util.Set; |
| | | import java.util.ArrayList; |
| | | import java.util.logging.Logger; |
| | |
| | | Message defaultValue, |
| | | Message[] validValues) { |
| | | |
| | | System.out.println(); |
| | | printLineBreak(); |
| | | |
| | | boolean isValid = false; |
| | | Message response = null; |
| | |
| | | System.out.flush(); |
| | | |
| | | response = Message.raw(readLine()); |
| | | if (response.equals("")) |
| | | if (response.toString().equals("")) |
| | | { |
| | | response = defaultValue; |
| | | } |
| | |
| | | * @return The string value read from the user. |
| | | */ |
| | | protected String promptForString(Message prompt, String defaultValue) { |
| | | System.out.println(); |
| | | printLineBreak(); |
| | | String wrappedPrompt = StaticUtils.wrapText(prompt, |
| | | Utils.getCommandLineMaxLineWidth()); |
| | | |
| | | while (true) { |
| | | System.out.println(wrappedPrompt); |
| | | System.out.print(wrappedPrompt); |
| | | |
| | | if (defaultValue == null) { |
| | | System.out.print(": "); |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Interactively prompts (on standard output) the user to provide a password |
| | | * value. |
| | | * |
| | | * @param msg The prompt to present to the user. |
| | | * |
| | | * @return The string value read from the user. |
| | | */ |
| | | protected String promptForPassword(Message msg) |
| | | { |
| | | String pwd; |
| | | printLineBreak(); |
| | | String wrappedPrompt = StaticUtils.wrapText(msg, |
| | | Utils.getCommandLineMaxLineWidth()); |
| | | System.out.print(wrappedPrompt+" "); |
| | | System.out.flush(); |
| | | try |
| | | { |
| | | char[] pwChars = PasswordReader.readPassword(); |
| | | if ((pwChars == null) || pwChars.length == 0) |
| | | { |
| | | pwd = null; |
| | | } |
| | | else |
| | | { |
| | | pwd = new String(pwChars); |
| | | } |
| | | } |
| | | catch (Throwable t) |
| | | { |
| | | LOG.log(Level.WARNING, "Error reading password: "+t, t); |
| | | pwd = null; |
| | | } |
| | | return pwd; |
| | | } |
| | | |
| | | /** |
| | | * Reads a line of text from standard input. |
| | |
| | | } |
| | | catch (Exception e) |
| | | { |
| | | err.println(INFO_CLI_ERROR_READING_STDIN.get()); |
| | | err.println(INFO_CLI_ERROR_READING_STDIN.get().toString()); |
| | | return null; |
| | | } |
| | | } |
| | |
| | | return argParser; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Displays an error message in the error output (wrapping it if necessary). |
| | | * @param msg the error message to be displayed. |
| | | */ |
| | | protected void printErrorMessage(Message msg) |
| | | { |
| | | System.err.println(org.opends.server.util.StaticUtils.wrapText(msg, |
| | | Utils.getCommandLineMaxLineWidth())); |
| | | } |
| | | |
| | | /** |
| | | * Displays an error message in the error output (wrapping it if necessary). |
| | | * @param msg the error message to be displayed. |
| | | */ |
| | | protected void printErrorMessage(String msg) |
| | | { |
| | | System.err.println(org.opends.server.util.StaticUtils.wrapText(msg, |
| | | Utils.getCommandLineMaxLineWidth())); |
| | | } |
| | | |
| | | /** |
| | | * Prints a line break in the standard output. |
| | | */ |
| | | protected void printLineBreak() |
| | | { |
| | | System.out.println(); |
| | | } |
| | | |
| | | /** |
| | | * Prompts the user to accept the certificate. |
| | | * @param t the throwable that was generated because the certificate was |
| | | * not trusted. |
| | | * @param trustManager the global trustManager that contains the certificates |
| | | * accepted by the user. |
| | | * @param usedUrl the LDAP URL used to connect to the server. |
| | | * @return <CODE>true</CODE> if the user accepted the certificate and |
| | | * <CODE>false</CODE> otherwise. |
| | | */ |
| | | protected boolean promptForCertificateConfirmation(Throwable t, |
| | | ApplicationTrustManager trustManager, String usedUrl) |
| | | { |
| | | boolean returnValue = false; |
| | | ApplicationTrustManager.Cause cause = trustManager.getLastRefusedCause(); |
| | | |
| | | LOG.log(Level.INFO, "Certificate exception cause: "+cause); |
| | | UserDataCertificateException.Type excType = null; |
| | | if (cause == ApplicationTrustManager.Cause.NOT_TRUSTED) |
| | | { |
| | | excType = UserDataCertificateException.Type.NOT_TRUSTED; |
| | | } |
| | | else if (cause == |
| | | ApplicationTrustManager.Cause.HOST_NAME_MISMATCH) |
| | | { |
| | | excType = UserDataCertificateException.Type.HOST_NAME_MISMATCH; |
| | | } |
| | | else |
| | | { |
| | | System.err.println(); |
| | | Message msg = Utils.getThrowableMsg(INFO_ERROR_CONNECTING_TO_LOCAL.get(), |
| | | t); |
| | | printErrorMessage(msg); |
| | | } |
| | | |
| | | if (excType != null) |
| | | { |
| | | String h; |
| | | int p; |
| | | try |
| | | { |
| | | URI uri = new URI(usedUrl); |
| | | h = uri.getHost(); |
| | | p = uri.getPort(); |
| | | } |
| | | catch (Throwable t1) |
| | | { |
| | | LOG.log(Level.WARNING, "Error parsing ldap url of ldap url.", t1); |
| | | h = INFO_NOT_AVAILABLE_LABEL.get().toString(); |
| | | p = -1; |
| | | } |
| | | UserDataCertificateException udce = |
| | | new UserDataCertificateException(Step.REPLICATION_OPTIONS, |
| | | INFO_CERTIFICATE_EXCEPTION.get(h, String.valueOf(p)), t, h, p, |
| | | trustManager.getLastRefusedChain(), |
| | | trustManager.getLastRefusedAuthType(), excType); |
| | | |
| | | returnValue = handleCertificateException(udce, trustManager, true); |
| | | } |
| | | return returnValue; |
| | | } |
| | | |
| | | /** |
| | | * Prompts the user to accept the certificate that generated the provided |
| | | * UserDataCertificateException. |
| | | * @param trustManager the global trustManager that contains the certificates |
| | | * accepted by the user. |
| | | * @param udce the UserDataCertificateException that was generated. |
| | | * @param trustManager the global trustManager that contains the certificates |
| | | * accepted by the user. |
| | | * @param displayErrorMessage whether to display the message describing |
| | | * the error encountered (certificate not trusted) or only prompt to accept |
| | | * the certificate. |
| | | * @return <CODE>true</CODE> if the user accepted the certificate and |
| | | * <CODE>false</CODE> otherwise. |
| | | */ |
| | | private boolean handleCertificateException( |
| | | UserDataCertificateException udce, ApplicationTrustManager trustManager, |
| | | boolean displayErrorMessage) |
| | | { |
| | | boolean accepted = false; |
| | | Message msg; |
| | | if (udce.getType() == UserDataCertificateException.Type.NOT_TRUSTED) |
| | | { |
| | | msg = INFO_CERTIFICATE_NOT_TRUSTED_TEXT_CLI.get( |
| | | udce.getHost(), String.valueOf(udce.getPort()), |
| | | udce.getHost(), String.valueOf(udce.getPort())); |
| | | } |
| | | else |
| | | { |
| | | msg = INFO_CERTIFICATE_NAME_MISMATCH_TEXT_CLI.get( |
| | | udce.getHost(), String.valueOf(udce.getPort()), |
| | | udce.getHost(), |
| | | udce.getHost(), String.valueOf(udce.getPort()), |
| | | udce.getHost(), String.valueOf(udce.getPort())); |
| | | } |
| | | if (displayErrorMessage) |
| | | { |
| | | printLineBreak(); |
| | | printErrorMessage(msg); |
| | | } |
| | | Message[] validValues = { |
| | | INFO_CLI_ACCEPT_CERTIFICATE_LONG.get(), |
| | | INFO_CLI_REJECT_CERTIFICATE_LONG.get(), |
| | | INFO_CLI_VIEW_CERTIFICATE_LONG.get(), |
| | | INFO_CLI_ACCEPT_CERTIFICATE_SHORT.get(), |
| | | INFO_CLI_REJECT_CERTIFICATE_SHORT.get(), |
| | | INFO_CLI_VIEW_CERTIFICATE_SHORT.get() |
| | | }; |
| | | Message answer = promptConfirm(INFO_CLI_ACCEPT_CERTIFICATE_PROMPT.get(), |
| | | validValues[0], validValues); |
| | | |
| | | if (INFO_CLI_REJECT_CERTIFICATE_LONG.get().toString().equalsIgnoreCase( |
| | | answer.toString()) || |
| | | INFO_CLI_REJECT_CERTIFICATE_SHORT.get().toString().equalsIgnoreCase( |
| | | answer.toString())) |
| | | { |
| | | accepted = false; |
| | | } |
| | | else if (INFO_CLI_VIEW_CERTIFICATE_LONG.get().toString().equalsIgnoreCase( |
| | | answer.toString()) || |
| | | INFO_CLI_VIEW_CERTIFICATE_SHORT.get().toString().equalsIgnoreCase( |
| | | answer.toString())) |
| | | { |
| | | printLineBreak(); |
| | | displayCertificate(udce); |
| | | accepted = handleCertificateException(udce, trustManager, false); |
| | | } |
| | | else |
| | | { |
| | | X509Certificate[] chain = udce.getChain(); |
| | | String authType = udce.getAuthType(); |
| | | String host = udce.getHost(); |
| | | |
| | | if ((chain != null) && (authType != null) && (host != null)) |
| | | { |
| | | LOG.log(Level.INFO, "Accepting certificate presented by host "+host); |
| | | trustManager.acceptCertificate(chain, authType, host); |
| | | accepted = true; |
| | | } |
| | | else |
| | | { |
| | | if (chain == null) |
| | | { |
| | | LOG.log(Level.WARNING, |
| | | "The chain is null for the UserDataCertificateException"); |
| | | } |
| | | if (authType == null) |
| | | { |
| | | LOG.log(Level.WARNING, |
| | | "The auth type is null for the UserDataCertificateException"); |
| | | } |
| | | if (host == null) |
| | | { |
| | | LOG.log(Level.WARNING, |
| | | "The host is null for the UserDataCertificateException"); |
| | | } |
| | | } |
| | | } |
| | | return accepted; |
| | | } |
| | | |
| | | private void displayCertificate(UserDataCertificateException udce) |
| | | { |
| | | Message[] labels = |
| | | { |
| | | INFO_CERTIFICATE_SUBJECT_LABEL.get(), |
| | | INFO_CERTIFICATE_ISSUED_BY_LABEL.get(), |
| | | INFO_CERTIFICATE_VALID_FROM_LABEL.get(), |
| | | INFO_CERTIFICATE_EXPIRES_ON_LABEL.get(), |
| | | INFO_CERTIFICATE_TYPE_LABEL.get(), |
| | | INFO_CERTIFICATE_SERIAL_NUMBER_LABEL.get(), |
| | | INFO_CERTIFICATE_SIGNATURE_LABEL.get(), |
| | | INFO_CERTIFICATE_SIGNATURE_ALGORITHM_LABEL.get(), |
| | | INFO_CERTIFICATE_VERSION_LABEL.get(), |
| | | INFO_CERTIFICATE_PUBLIC_KEY_LABEL.get() |
| | | }; |
| | | for (int i=0; i<udce.getChain().length; i++) |
| | | { |
| | | X509Certificate cert = udce.getChain()[i]; |
| | | String[] values = |
| | | { |
| | | cert.getSubjectX500Principal().getName().toString(), |
| | | cert.getIssuerX500Principal().getName().toString(), |
| | | CertificateDialog.getValidFrom(cert), |
| | | CertificateDialog.getExpiresOn(cert), |
| | | cert.getType(), |
| | | String.valueOf(cert.getSerialNumber()), |
| | | CertificateDialog.getSignature(cert).toString(), |
| | | String.valueOf(cert.getSigAlgName()), |
| | | String.valueOf(cert.getVersion()), |
| | | cert.getPublicKey().toString() |
| | | }; |
| | | for (int j=0; j<labels.length; j++) |
| | | { |
| | | System.out.println(StaticUtils.wrapText(labels[j]+" "+values[j], |
| | | Utils.getCommandLineMaxLineWidth())); |
| | | } |
| | | } |
| | | System.out.flush(); |
| | | } |
| | | } |