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