001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.tools;
028 import org.opends.messages.Message;
029
030
031
032 import java.io.BufferedReader;
033 import java.io.InputStreamReader;
034 import java.io.IOException;
035 import java.security.cert.CertificateException;
036 import java.security.cert.X509Certificate;
037 import java.util.Date;
038 import javax.net.ssl.TrustManager;
039 import javax.net.ssl.X509TrustManager;
040
041 import static org.opends.messages.ToolMessages.*;
042 import static org.opends.server.util.StaticUtils.*;
043
044
045
046 /**
047 * This class provides an implementation of an X.509 trust manager which will
048 * interactively prompt the user (via the CLI) whether a given certificate
049 * should be trusted. It should only be used by interactive command-line tools,
050 * since it will block until it gets a response from the user.
051 * <BR><BR>
052 * Note that this class is only intended for client-side use, and therefore may
053 * not be used by a server to determine whether a client certificate is trusted.
054 */
055 public class PromptTrustManager
056 implements X509TrustManager
057 {
058
059
060
061 // The singleton trust manager array for this class.
062 private static TrustManager[] trustManagerArray =
063 new TrustManager[] { new PromptTrustManager() };
064
065
066
067 /**
068 * Creates a new instance of this prompt trust manager.
069 */
070 private PromptTrustManager()
071 {
072 // No implementation is required.
073 }
074
075
076
077 /**
078 * Retrieves the trust manager array that should be used to initialize an SSL
079 * context in cases where the user should be interactively prompted about
080 * whether to trust the server certificate.
081 *
082 * @return The trust manager array that should be used to initialize an SSL
083 * context in cases where the user should be interactively prompted
084 * about whether to trust the server certificate.
085 */
086 public static TrustManager[] getTrustManagers()
087 {
088 return trustManagerArray;
089 }
090
091
092
093 /**
094 * Determines whether an SSL client with the provided certificate chain should
095 * be trusted. This implementation is not intended for server-side use, and
096 * therefore this method will always throw an exception.
097 *
098 * @param chain The certificate chain for the SSL client.
099 * @param authType The authentication type based on the client certificate.
100 *
101 * @throws CertificateException To indicate that the provided client
102 * certificate is not trusted.
103 */
104 public void checkClientTrusted(X509Certificate[] chain, String authType)
105 throws CertificateException
106 {
107 Message message = ERR_PROMPTTM_REJECTING_CLIENT_CERT.get();
108 throw new CertificateException(message.toString());
109 }
110
111
112
113 /**
114 * Determines whether an SSL server with the provided certificate chain should
115 * be trusted. In this case, the user will be interactively prompted as to
116 * whether the certificate should be trusted.
117 *
118 * @param chain The certificate chain for the SSL server.
119 * @param authType The key exchange algorithm used.
120 *
121 * @throws CertificateException If the user rejects the certificate.
122 */
123 public void checkServerTrusted(X509Certificate[] chain, String authType)
124 throws CertificateException
125 {
126 if ((chain == null) || (chain.length == 0))
127 {
128 System.out.println(WARN_PROMPTTM_NO_SERVER_CERT_CHAIN.get());
129 }
130 else
131 {
132 Date currentDate = new Date();
133 Date notAfterDate = chain[0].getNotAfter();
134 Date notBeforeDate = chain[0].getNotBefore();
135
136 if (currentDate.after(notAfterDate))
137 {
138 Message message = WARN_PROMPTTM_CERT_EXPIRED.get(
139 String.valueOf(notAfterDate));
140 System.err.println(message);
141 }
142 else if (currentDate.before(notBeforeDate))
143 {
144 Message message = WARN_PROMPTTM_CERT_NOT_YET_VALID.get(
145 String.valueOf(notBeforeDate));
146 System.err.println(message);
147 }
148
149 System.out.println(INFO_PROMPTTM_SERVER_CERT.get(
150 chain[0].getSubjectDN().getName(),
151 chain[0].getIssuerDN().getName(),
152 String.valueOf(notBeforeDate),
153 String.valueOf(notAfterDate)));
154 }
155
156
157 Message prompt = INFO_PROMPTTM_YESNO_PROMPT.get();
158 BufferedReader reader =
159 new BufferedReader(new InputStreamReader(System.in));
160 while (true)
161 {
162 try
163 {
164 System.out.print(prompt);
165 String line = reader.readLine().toLowerCase();
166 if (line.equals("y") || line.equals("yes"))
167 {
168 // Returning without an exception is sufficient to consider the
169 // certificate trusted.
170 return;
171 }
172 else if (line.equals("n") || line.equals("no"))
173 {
174 Message message = ERR_PROMPTTM_USER_REJECTED.get();
175 throw new CertificateException(message.toString());
176 }
177 } catch (IOException ioe) {}
178
179 System.out.println();
180 }
181 }
182
183
184
185 /**
186 * Retrieves the set of certificate authority certificates which are trusted
187 * for authenticating peers.
188 *
189 * @return An empty array, since we don't care what certificates are
190 * presented because we will always prompt the user.
191 */
192 public X509Certificate[] getAcceptedIssuers()
193 {
194 return new X509Certificate[0];
195 }
196 }
197