1 /* StorePasswdCmd.java -- The storepasswd 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)
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
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
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.classpath.SystemProperties;
42 import gnu.classpath.tools.getopt.ClasspathToolParser;
43 import gnu.classpath.tools.getopt.Option;
44 import gnu.classpath.tools.getopt.OptionException;
45 import gnu.classpath.tools.getopt.OptionGroup;
46 import gnu.classpath.tools.getopt.Parser;
48 import java.io.IOException;
49 import java.security.KeyStoreException;
50 import java.security.NoSuchAlgorithmException;
51 import java.security.cert.CertificateException;
52 import java.util.Arrays;
53 import java.util.logging.Logger;
55 import javax.security.auth.callback.Callback;
56 import javax.security.auth.callback.CallbackHandler;
57 import javax.security.auth.callback.PasswordCallback;
58 import javax.security.auth.callback.TextOutputCallback;
59 import javax.security.auth.callback.UnsupportedCallbackException;
62 * The <b>-storepasswd</b> keytool command handler is used to change the
63 * password which protects the integrity of the key store.
65 * Possible options for this command are:
68 * <dt>-new PASSWORD</dt>
69 * <dd>The new, and different, password which will be used to protect the
70 * designated key store.
73 * <dt>-storetype STORE_TYPE</dt>
74 * <dd>Use this option to specify the type of the key store to use. The
75 * default value, if this option is omitted, is that of the property
76 * <code>keystore.type</code> in the security properties file, which is
77 * obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
81 * <dt>-keystore URL</dt>
82 * <dd>Use this option to specify the location of the key store to use.
83 * The default value is a file {@link java.net.URL} referencing the file
84 * named <code>.keystore</code> located in the path returned by the call to
85 * {@link java.lang.System#getProperty(String)} using <code>user.home</code>
88 * If a URL was specified, but was found to be malformed --e.g. missing
89 * protocol element-- the tool will attempt to use the URL value as a file-
90 * name (with absolute or relative path-name) of a key store --as if the
91 * protocol was <code>file:</code>.
94 * <dt>-storepass PASSWORD</dt>
95 * <dd>Use this option to specify the password protecting the key store. If
96 * this option is omitted from the command line, you will be prompted to
100 * <dt>-provider PROVIDER_CLASS_NAME</dt>
101 * <dd>A fully qualified class name of a Security Provider to add to the
102 * current list of Security Providers already installed in the JVM in-use.
103 * If a provider class is specified with this option, and was successfully
104 * added to the runtime --i.e. it was not already installed-- then the tool
105 * will attempt to removed this Security Provider before exiting.
109 * <dd>Use this option to enable more verbose output.</dd>
112 class StorePasswdCmd extends Command
114 private static final Logger log = Logger.getLogger(StorePasswdCmd.class.getName());
115 protected String _newPassword;
116 protected String _ksType;
117 protected String _ksURL;
118 protected String _ksPassword;
119 protected String _providerClassName;
120 private char[] newStorePasswordChars;
122 // default 0-arguments constructor
124 // public setters -----------------------------------------------------------
126 /** @param password the new key-store password to use. */
127 public void setNew(String password)
129 this._newPassword = password;
132 /** @param type the key-store type to use. */
133 public void setStoretype(String type)
138 /** @param url the key-store URL to use. */
139 public void setKeystore(String url)
144 /** @param password the key-store password to use. */
145 public void setStorepass(String password)
147 this._ksPassword = password;
150 /** @param className a security provider fully qualified class name to use. */
151 public void setProvider(String className)
153 this._providerClassName = className;
156 // life-cycle methods -------------------------------------------------------
158 void setup() throws Exception
160 setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
161 setNewKeystorePassword(_newPassword);
163 log.finer("-storepasswd handler will use the following options:"); //$NON-NLS-1$
164 log.finer(" -storetype=" + storeType); //$NON-NLS-1$
165 log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
166 log.finer(" -provider=" + provider); //$NON-NLS-1$
167 log.finer(" -v=" + verbose); //$NON-NLS-1$
170 void start() throws KeyStoreException, NoSuchAlgorithmException,
171 CertificateException, IOException
173 log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
175 saveKeyStore(newStorePasswordChars);
177 log.exiting(getClass().getName(), "start"); //$NON-NLS-1$
180 // own methods --------------------------------------------------------------
184 log.entering(this.getClass().getName(), "getParser"); //$NON-NLS-1$
186 Parser result = new ClasspathToolParser(Main.STOREPASSWD_CMD, true);
187 result.setHeader(Messages.getString("StorePasswdCmd.18")); //$NON-NLS-1$
188 result.setFooter(Messages.getString("StorePasswdCmd.17")); //$NON-NLS-1$
189 OptionGroup options = new OptionGroup(Messages.getString("StorePasswdCmd.16")); //$NON-NLS-1$
190 options.add(new Option(Main.NEW_OPT,
191 Messages.getString("StorePasswdCmd.15"), //$NON-NLS-1$
192 Messages.getString("StorePasswdCmd.8")) //$NON-NLS-1$
194 public void parsed(String argument) throws OptionException
196 _newPassword = argument;
199 options.add(new Option(Main.STORETYPE_OPT,
200 Messages.getString("StorePasswdCmd.13"), //$NON-NLS-1$
201 Messages.getString("StorePasswdCmd.12")) //$NON-NLS-1$
203 public void parsed(String argument) throws OptionException
208 options.add(new Option(Main.KEYSTORE_OPT,
209 Messages.getString("StorePasswdCmd.11"), //$NON-NLS-1$
210 Messages.getString("StorePasswdCmd.10")) //$NON-NLS-1$
212 public void parsed(String argument) throws OptionException
217 options.add(new Option(Main.STOREPASS_OPT,
218 Messages.getString("StorePasswdCmd.9"), //$NON-NLS-1$
219 Messages.getString("StorePasswdCmd.8")) //$NON-NLS-1$
221 public void parsed(String argument) throws OptionException
223 _ksPassword = argument;
226 options.add(new Option(Main.PROVIDER_OPT,
227 Messages.getString("StorePasswdCmd.7"), //$NON-NLS-1$
228 Messages.getString("StorePasswdCmd.6")) //$NON-NLS-1$
230 public void parsed(String argument) throws OptionException
232 _providerClassName = argument;
235 options.add(new Option(Main.VERBOSE_OPT,
236 Messages.getString("StorePasswdCmd.5")) //$NON-NLS-1$
238 public void parsed(String argument) throws OptionException
245 log.exiting(this.getClass().getName(), "getParser", result); //$NON-NLS-1$
249 protected void setNewKeystorePassword(String password) throws IOException,
250 UnsupportedCallbackException
252 if (password != null)
253 newStorePasswordChars = password.toCharArray();
257 Callback[] prompts = new Callback[1];
258 Callback[] errors = new Callback[1];
259 for (int i = 0; i < 3; i++)
260 if (prompt4NewPassword(getCallbackHandler(), prompts, errors))
266 throw new SecurityException(Messages.getString("StorePasswdCmd.19")); //$NON-NLS-1$
270 private boolean prompt4NewPassword(CallbackHandler handler,
271 Callback[] prompts, Callback[] errors)
272 throws IOException, UnsupportedCallbackException
274 // prompt user (1st time) to provide one
275 String p = Messages.getString("StorePasswdCmd.20"); //$NON-NLS-1$
276 PasswordCallback pcb = new PasswordCallback(p, false);
278 handler.handle(prompts);
279 char[] pwd1 = pcb.getPassword();
281 String ls = SystemProperties.getProperty("line.separator"); //$NON-NLS-1$
282 if (pwd1 == null || pwd1.length < 6)
284 String m = Messages.getString("StorePasswdCmd.21") + ls; //$NON-NLS-1$
285 errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
286 handler.handle(errors);
290 if (Arrays.equals(storePasswordChars, pwd1))
292 String m = Messages.getString("StorePasswdCmd.22") + ls; //$NON-NLS-1$
293 errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
294 handler.handle(errors);
298 // prompt user (2nd time) for confirmation
299 pcb = new PasswordCallback(Messages.getString("StorePasswdCmd.23"), false); //$NON-NLS-1$
301 handler.handle(prompts);
302 char[] pwd2 = pcb.getPassword();
304 if (! Arrays.equals(pwd1, pwd2))
306 String m = Messages.getString("StorePasswdCmd.24") + ls; //$NON-NLS-1$
307 errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
308 handler.handle(errors);
312 newStorePasswordChars = pwd2;