Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / tools / gnu / classpath / tools / keytool / ListCmd.java
blob655242785342753134b3c5644b3c7884ad372b6d
1 /* ListCmd.java -- The list command handler of the keytool
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.classpath.tools.keytool;
41 import gnu.java.security.util.Base64;
43 import java.io.IOException;
44 import java.io.PrintWriter;
45 import java.security.KeyStoreException;
46 import java.security.cert.Certificate;
47 import java.security.cert.CertificateEncodingException;
48 import java.util.Enumeration;
49 import java.util.logging.Logger;
51 /**
52 * The <b>-list</b> keytool command handler is used to output one or all key
53 * store entries.
54 * <p>
55 * Possible options for this command are:
56 * <p>
57 * <dl>
58 * <dt>-alias ALIAS</dt>
59 * <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
60 * Certificate</i>, in a key store is uniquely identified by a user-defined
61 * <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
62 * when referring to an entry in the key store. Unless specified otherwise,
63 * a default value of <code>mykey</code> shall be used when this option is
64 * omitted from the command line.
65 * <p></dd>
67 * <dt>-storetype STORE_TYP}</dt>
68 * <dd>Use this option to specify the type of the key store to use. The
69 * default value, if this option is omitted, is that of the property
70 * <code>keystore.type</code> in the security properties file, which is
71 * obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
72 * static method.
73 * <p></dd>
75 * <dt>-keystore URL</dt>
76 * <dd>Use this option to specify the location of the key store to use.
77 * The default value is a file {@link java.net.URL} referencing the file
78 * named <code>.keystore</code> located in the path returned by the call to
79 * {@link java.lang.System#getProperty(String)} using <code>user.home</code>
80 * as argument.
81 * <p>
82 * If a URL was specified, but was found to be malformed --e.g. missing
83 * protocol element-- the tool will attempt to use the URL value as a file-
84 * name (with absolute or relative path-name) of a key store --as if the
85 * protocol was <code>file:</code>.
86 * <p></dd>
88 * <dt>-storepass PASSWORD</dt>
89 * <dd>Use this option to specify the password protecting the key store. If
90 * this option is omitted from the command line, you will be prompted to
91 * provide a password.
92 * <p></dd>
94 * <dt>-provider PROVIDER_CLASS_NAME</dt>
95 * <dd>A fully qualified class name of a Security Provider to add to the
96 * current list of Security Providers already installed in the JVM in-use.
97 * If a provider class is specified with this option, and was successfully
98 * added to the runtime --i.e. it was not already installed-- then the tool
99 * will attempt to removed this Security Provider before exiting.
100 * <p></dd>
102 * <dt>-rfc</dt>
103 * <dd>Use RFC-1421 specifications when encoding the output.
104 * <p></dd>
106 * <dt>-v</dt>
107 * <dd>Output the certificate in human-readable format. If both this option
108 * and the <code>-rfc</code> option are detected on the command line, the
109 * tool will opt for the human-readable form and will not abort the
110 * command.</dd>
111 * </dl>
113 class ListCmd extends Command
115 private static final Logger log = Logger.getLogger(ListCmd.class.getName());
116 private String _alias;
117 private String _ksType;
118 private String _ksURL;
119 private String _ksPassword;
120 private String _providerClassName;
121 private boolean rfc;
122 private boolean all;
124 // default 0-arguments constructor
126 // public setters -----------------------------------------------------------
128 /** @param alias the alias to use. */
129 public void setAlias(String alias)
131 this._alias = alias;
134 /** @param type the key-store type to use. */
135 public void setStoretype(String type)
137 this._ksType = type;
140 /** @param url the key-store URL to use. */
141 public void setKeystore(String url)
143 this._ksURL = url;
146 /** @param password the key-store password to use. */
147 public void setStorepass(String password)
149 this._ksPassword = password;
152 /** @param className a security provider fully qualified class name to use. */
153 public void setProvider(String className)
155 this._providerClassName = className;
159 * @param flag whether to use, or not, RFC-1421 format when listing the
160 * certificate(s).
162 public void setRfc(String flag)
164 this.rfc = Boolean.valueOf(flag).booleanValue();
167 // life-cycle methods -------------------------------------------------------
169 int processArgs(String[] args, int i)
171 int limit = args.length;
172 String opt;
173 while (++i < limit)
175 opt = args[i];
176 log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
177 if (opt == null || opt.length() == 0)
178 continue;
180 if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
181 _alias = args[++i];
182 else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
183 _ksType = args[++i];
184 else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
185 _ksURL = args[++i];
186 else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
187 _ksPassword = args[++i];
188 else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
189 _providerClassName = args[++i];
190 else if ("-v".equals(opt)) //$NON-NLS-1$
191 verbose = true;
192 else if ("-rfc".equals(opt)) //$NON-NLS-1$
193 rfc = true;
194 else
195 break;
198 all = _alias == null;
200 return i;
203 void setup() throws Exception
205 setOutputStreamParam(null); // use stdout
206 setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
207 if (! all)
208 setAliasParam(_alias);
210 if (verbose & rfc)
212 log.warning("Both -v and -rfc options were found on the command line. " //$NON-NLS-1$
213 + "Only the former will be considered"); //$NON-NLS-1$
214 rfc = false;
217 log.finer("-list handler will use the following options:"); //$NON-NLS-1$
218 log.finer(" -alias=" + alias); //$NON-NLS-1$
219 log.finer(" -storetype=" + storeType); //$NON-NLS-1$
220 log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
221 log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
222 log.finer(" -provider=" + provider); //$NON-NLS-1$
223 log.finer(" -v=" + verbose); //$NON-NLS-1$
224 log.finer(" -rfc=" + rfc); //$NON-NLS-1$
227 void start() throws KeyStoreException, CertificateEncodingException,
228 IOException
230 log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
232 PrintWriter writer = new PrintWriter(outStream, true);
233 writer.println(Messages.getFormattedString("ListCmd.21", store.getType())); //$NON-NLS-1$
234 writer.println(Messages.getFormattedString("ListCmd.22", //$NON-NLS-1$
235 store.getProvider().getName()));
236 if (all)
238 log.finest("About to list all aliases in key store..."); //$NON-NLS-1$
239 writer.println();
240 writer.println(Messages.getFormattedString("ListCmd.24", //$NON-NLS-1$
241 Integer.valueOf(store.size())));
242 for (Enumeration e = store.aliases(); e.hasMoreElements(); )
244 String anAlias = (String) e.nextElement();
245 if (anAlias != null)
246 list1Alias(anAlias, writer);
249 else
250 list1Alias(alias, writer);
252 log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
255 // own methods --------------------------------------------------------------
258 * Prints the certificate(s) associated with the designated alias.
260 * @param anAlias a non-null string denoting an alias in the key-store.
261 * @param writer where to print.
262 * @throws KeyStoreException if an exception occurs while obtaining the
263 * certificate associated to the designated alias.
264 * @throws CertificateEncodingException if an exception occurs while obtaining
265 * the DER encoded form of the certificate.
266 * @throws IOException if an I/O related exception occurs during the process.
268 private void list1Alias(String anAlias, PrintWriter writer)
269 throws KeyStoreException, CertificateEncodingException, IOException
271 log.entering(this.getClass().getName(), "list1Alias", anAlias); //$NON-NLS-1$
273 writer.println();
274 writer.println(Messages.getFormattedString("ListCmd.30", anAlias)); //$NON-NLS-1$
275 writer.println(Messages.getFormattedString("ListCmd.31", store.getCreationDate(anAlias))); //$NON-NLS-1$
277 if (store.isCertificateEntry(anAlias))
279 writer.println(Messages.getString("ListCmd.32")); //$NON-NLS-1$
280 Certificate certificate = store.getCertificate(anAlias);
281 print1Certificate(certificate, writer);
283 else if (store.isKeyEntry(anAlias))
285 writer.println(Messages.getString("ListCmd.33")); //$NON-NLS-1$
286 Certificate[] chain = store.getCertificateChain(anAlias);
287 print1Chain(chain, writer);
289 else
290 throw new IllegalArgumentException(Messages.getFormattedString("ListCmd.34", //$NON-NLS-1$
291 anAlias));
292 log.exiting(this.getClass().getName(), "list1Alias"); //$NON-NLS-1$
296 * Prints the designated certificate chain, or a fingerprint of the first
297 * certificate (bottom) in the chain, depending on the values of the flags
298 * <code>v</code> (for verbose) and <code>rfc</code>.
299 * <p>
300 * If both flags are <code>false</code>, only the fingerprint is generated,
301 * otherwise, if the <code>v</code> flag is set, then a human readable output
302 * is generated. If <code>rfc</code> is set, then an RFC-1421 like output
303 * is generated.
304 * <p>Note that both <code>v</code> and <code>rfc</code> cannot both be
305 * <code>true</code> at the same time.
307 * @param chain the certificate chain to process.
308 * @param writer where to print.
309 * @throws CertificateEncodingException if an exception occurs while obtaining
310 * the DER encoded form of the certificate.
312 private void print1Chain(Certificate[] chain, PrintWriter writer)
313 throws CertificateEncodingException
315 if (!verbose && !rfc)
316 fingerprint(chain[0], writer);
317 else
319 int limit = chain.length;
320 writer.println(Messages.getFormattedString("ListCmd.38", //$NON-NLS-1$
321 Integer.valueOf(limit)));
322 writer.println(Messages.getString("ListCmd.39")); //$NON-NLS-1$
323 print1Certificate(chain[0], writer);
324 for (int i = 1; i < limit; i++)
326 writer.println();
327 writer.println(Messages.getFormattedString("ListCmd.40", //$NON-NLS-1$
328 Integer.valueOf(i + 1)));
329 print1Certificate(chain[i], writer);
331 writer.println();
332 writer.println(Messages.getString("ListCmd.42")); //$NON-NLS-1$
337 * Prints the designated certificate, or its fingerprint, depending on the
338 * values of the flags <code>v</code> (for verbose) and <code>rfc</code>.
339 * <p>
340 * If both flags are <code>false</code>, only a fingerprint is generated,
341 * otherwise, if the <code>v</code> flag is set, then a human readable output
342 * is generated. If <code>rfc</code> is set, then an RFC-1421 like output
343 * is generated.
344 * <p>Note that both <code>v</code> and <code>rfc</code> cannot both be
345 * <code>true</code> at the same time.
347 * @param certificate the certificate to process.
348 * @param writer where to print.
349 * @throws CertificateEncodingException if an exception occurs while obtaining
350 * the DER encoded form of the certificate.
352 private void print1Certificate(Certificate certificate, PrintWriter writer)
353 throws CertificateEncodingException
355 if (verbose)
356 printVerbose(certificate, writer);
357 else if (rfc)
358 printRFC1421(certificate, writer);
359 else
360 fingerprint(certificate, writer);
363 private void printRFC1421(Certificate certificate, PrintWriter writer)
364 throws CertificateEncodingException
366 byte[] derBytes = certificate.getEncoded();
367 String encoded = Base64.encode(derBytes, 0, derBytes.length, true);
368 writer.println(Messages.getString("ListCmd.43")); //$NON-NLS-1$
369 writer.println(encoded);
370 writer.println(Messages.getString("ListCmd.44")); //$NON-NLS-1$
373 private void fingerprint(Certificate certificate, PrintWriter writer)
374 throws CertificateEncodingException
376 byte[] derBytes = certificate.getEncoded();
377 String fingerPrint = digestWithMD5(derBytes);
378 writer.println(Messages.getFormattedString("ListCmd.45", fingerPrint)); //$NON-NLS-1$