Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / tools / gnu / classpath / tools / keytool / KeyCloneCmd.java
blob5936719f7eba9261a9a51c2a20f1e63e497581f6
1 /* KeyCloneCmd.java -- The keyclone 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 java.io.IOException;
42 import java.security.Key;
43 import java.security.KeyStoreException;
44 import java.security.NoSuchAlgorithmException;
45 import java.security.UnrecoverableKeyException;
46 import java.security.cert.Certificate;
47 import java.security.cert.CertificateException;
48 import java.util.logging.Logger;
50 import javax.security.auth.callback.Callback;
51 import javax.security.auth.callback.CallbackHandler;
52 import javax.security.auth.callback.NameCallback;
53 import javax.security.auth.callback.PasswordCallback;
54 import javax.security.auth.callback.TextOutputCallback;
55 import javax.security.auth.callback.UnsupportedCallbackException;
57 /**
58 * The <b>-keyclone</b> keytool command handler is used to clone an existing
59 * key store entry associated with a designated alias, with its private key and
60 * chain of certificates.
61 * <p>
62 * Possible options for this command are:
63 * <p>
64 * <dl>
65 * <dt>-alias ALIAS</dt>
66 * <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
67 * Certificate</i>, in a key store is uniquely identified by a user-defined
68 * <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
69 * when referring to an entry in the key store. Unless specified otherwise,
70 * a default value of <code>mykey</code> shall be used when this option is
71 * omitted from the command line.
72 * <p></dd>
74 * <dt>-dest ALIAS</dt>
75 * <dd>Use this option to specify the new <i>Alias</i> which will be used
76 * to identify the cloned copy of the <i>Key Entry</i>.
77 * <p></dd>
79 * <dt>-keypass PASSWORD</dt>
80 * <dd>Use this option to specify the password which the tool will use to
81 * unlock the <i>Key Entry</i> associated with the designated <i>Alias</i>.
82 * <p>
83 * If this option is omitted, the tool will first attempt to unlock the
84 * <i>Key Entry</i> using the same password protecting the key store. If
85 * this fails, you will then be prompted to provide a password.
86 * <p></dd>
88 * <dt>-new PASSWORD</dt>
89 * <dd>Use this option to specify the password protecting the private key
90 * material of the newly cloned copy of the <i>Key Entry</i>.
91 * <p></dd>
93 * <dt>-storetype STORE_TYP}</dt>
94 * <dd>Use this option to specify the type of the key store to use. The
95 * default value, if this option is omitted, is that of the property
96 * <code>keystore.type</code> in the security properties file, which is
97 * obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
98 * static method.
99 * <p></dd>
101 * <dt>-keystore URL</dt>
102 * <dd>Use this option to specify the location of the key store to use.
103 * The default value is a file {@link java.net.URL} referencing the file
104 * named <code>.keystore</code> located in the path returned by the call to
105 * {@link java.lang.System#getProperty(String)} using <code>user.home</code>
106 * as argument.
107 * <p>
108 * If a URL was specified, but was found to be malformed --e.g. missing
109 * protocol element-- the tool will attempt to use the URL value as a file-
110 * name (with absolute or relative path-name) of a key store --as if the
111 * protocol was <code>file:</code>.
112 * <p></dd>
114 * <dt>-storepass PASSWORD</dt>
115 * <dd>Use this option to specify the password protecting the key store. If
116 * this option is omitted from the command line, you will be prompted to
117 * provide a password.
118 * <p></dd>
120 * <dt>-provider PROVIDER_CLASS_NAME</dt>
121 * <dd>A fully qualified class name of a Security Provider to add to the
122 * current list of Security Providers already installed in the JVM in-use.
123 * If a provider class is specified with this option, and was successfully
124 * added to the runtime --i.e. it was not already installed-- then the tool
125 * will attempt to removed this Security Provider before exiting.
126 * <p></dd>
128 * <dt>-v</dt>
129 * <dd>Use this option to enable more verbose output.</dd>
130 * </dl>
132 class KeyCloneCmd extends Command
134 private static final Logger log = Logger.getLogger(KeyCloneCmd.class.getName());
135 private String _alias;
136 private String _destAlias;
137 private String _password;
138 private String _newPassword;
139 private String _ksType;
140 private String _ksURL;
141 private String _ksPassword;
142 private String _providerClassName;
143 private String destinationAlias;
144 private char[] newKeyPasswordChars;
146 // default 0-arguments constructor
148 // public setters -----------------------------------------------------------
150 /** @param alias the existing alias to use. */
151 public void setAlias(String alias)
153 this._alias = alias;
156 /** @param alias the new alias to use. */
157 public void setDest(String alias)
159 this._destAlias = alias;
162 /** @param password the existing (private) key password to use. */
163 public void setKeypass(String password)
165 this._password = password;
168 /** @param password the new (private) key password to use. */
169 public void setNew(String password)
171 this._newPassword = password;
174 /** @param type the key-store type to use. */
175 public void setStoretype(String type)
177 this._ksType = type;
180 /** @param url the key-store URL to use. */
181 public void setKeystore(String url)
183 this._ksURL = url;
186 /** @param password the key-store password to use. */
187 public void setStorepass(String password)
189 this._ksPassword = password;
192 /** @param className a security provider fully qualified class name to use. */
193 public void setProvider(String className)
195 this._providerClassName = className;
198 // life-cycle methods -------------------------------------------------------
200 int processArgs(String[] args, int i)
202 int limit = args.length;
203 String opt;
204 while (++i < limit)
206 opt = args[i];
207 log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
208 if (opt == null || opt.length() == 0)
209 continue;
211 if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
212 _alias = args[++i];
213 else if ("-dest".equals(opt)) // -dest ALIAS //$NON-NLS-1$
214 _destAlias = args[++i];
215 else if ("-keypass".equals(opt)) // -keypass PASSWORD //$NON-NLS-1$
216 _password = args[++i];
217 else if ("-new".equals(opt)) // -new PASSWORD //$NON-NLS-1$
218 _newPassword = args[++i];
219 else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
220 _ksType = args[++i];
221 else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
222 _ksURL = args[++i];
223 else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
224 _ksPassword = args[++i];
225 else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
226 _providerClassName = args[++i];
227 else if ("-v".equals(opt)) //$NON-NLS-1$
228 verbose = true;
229 else
230 break;
233 return i;
236 void setup() throws Exception
238 setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
239 setAliasParam(_alias);
240 setKeyPasswordNoPrompt(_password);
241 setDestinationAlias(_destAlias);
242 // setNewKeyPassword(_newPassword);
244 log.finer("-keyclone handler will use the following options:"); //$NON-NLS-1$
245 log.finer(" -alias=" + alias); //$NON-NLS-1$
246 log.finer(" -dest=" + destinationAlias); //$NON-NLS-1$
247 log.finer(" -keypass=" + _password); //$NON-NLS-1$
248 log.finer(" -new=" + _newPassword); //$NON-NLS-1$
249 log.finer(" -storetype=" + storeType); //$NON-NLS-1$
250 log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
251 log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
252 log.finer(" -provider=" + provider); //$NON-NLS-1$
253 log.finer(" -v=" + verbose); //$NON-NLS-1$
256 void start() throws KeyStoreException, NoSuchAlgorithmException, IOException,
257 UnsupportedCallbackException, UnrecoverableKeyException,
258 CertificateException
260 log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
262 if (store.containsAlias(destinationAlias))
263 throw new SecurityException(Messages.getString("KeyCloneCmd.23")); //$NON-NLS-1$
265 Key privateKey = getAliasPrivateKey();
267 setNewKeyPassword(_newPassword);
268 Certificate[] chain = store.getCertificateChain(alias);
270 store.setKeyEntry(destinationAlias, privateKey, newKeyPasswordChars, chain);
272 saveKeyStore();
274 log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
277 // own methods --------------------------------------------------------------
279 private void setDestinationAlias(String name) throws IOException,
280 UnsupportedCallbackException
282 if (name == null || name.trim().length() == 0) // ask user to provide one
284 NameCallback ncb = new NameCallback(Messages.getString("KeyCloneCmd.26")); //$NON-NLS-1$
285 getCallbackHandler().handle(new Callback[] { ncb });
286 name = ncb.getName();
287 if (name == null || name.trim().length() == 0)
288 throw new IllegalArgumentException(Messages.getString("KeyCloneCmd.27")); //$NON-NLS-1$
291 destinationAlias = name.trim();
294 private void setNewKeyPassword(String password) throws IOException,
295 UnsupportedCallbackException
297 if (password != null) // ask user to provide one
298 newKeyPasswordChars = password.toCharArray();
299 else
301 boolean ok = false;
302 Callback[] prompts = new Callback[1];
303 Callback[] errors = new Callback[1];
304 for (int i = 0; i < 3; i++)
305 if (prompt4NewPassword(getCallbackHandler(), prompts, errors))
307 ok = true;
308 break;
310 if (! ok)
311 throw new SecurityException(Messages.getString("StorePasswdCmd.19")); //$NON-NLS-1$
315 private boolean prompt4NewPassword(CallbackHandler handler,
316 Callback[] prompts, Callback[] errors)
317 throws IOException, UnsupportedCallbackException
319 String p = Messages.getFormattedString("KeyCloneCmd.28", //$NON-NLS-1$
320 new String[] { destinationAlias,
321 String.valueOf(keyPasswordChars) });
322 PasswordCallback pcb = new PasswordCallback(p, false);
323 prompts[0] = pcb;
324 handler.handle(prompts);
325 char[] pwd1 = pcb.getPassword();
326 pcb.clearPassword();
327 if (pwd1 == null || pwd1.length == 0)
329 newKeyPasswordChars = (char[]) keyPasswordChars.clone();
330 return true;
333 if (pwd1.length < 6)
335 errors[0] = new TextOutputCallback(TextOutputCallback.ERROR,
336 Messages.getString("StorePasswdCmd.21")); //$NON-NLS-1$
337 handler.handle(errors);
338 return false;
341 newKeyPasswordChars = pwd1;
342 return true;