/* Main.java -- keytool utility. Copyright (C) 2004 Free Software Foundation, Inc. This file is part of GNU Crypto. GNU Crypto is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Crypto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package gnu.crypto.tool.keytool; import gnu.crypto.Properties; import gnu.crypto.Registry; import gnu.crypto.auth.callback.AbstractCallbackHandler; import gnu.crypto.auth.callback.GnuCallbacks; import gnu.getopt.Getopt; import gnu.getopt.LongOpt; import java.io.PrintStream; import java.security.Provider; import java.security.Security; import java.text.DateFormat; import java.text.MessageFormat; import java.util.Iterator; import java.util.LinkedList; import java.util.MissingResourceException; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; import java.util.StringTokenizer; import javax.security.auth.callback.CallbackHandler; public final class Main { // Constants and fields. // ------------------------------------------------------------------------- public static final String PROGNAME = "keytool"; private static final int OPT_ARMOR = 1024; private static final int OPT_CALLBACK = 1025; private static final int OPT_CERT_TYPE = 1026; private static final int OPT_DATE = 1027; private static final int OPT_DEBUG = 1028; private static final int OPT_NO_KEYSTORE = 1029; private static final int OPT_PCLASS = 1030; private static final int OPT_PNAME = 1031; private static final int OPT_STORE_TYPE = 1032; private static final int OPT_VALIDITY = 1033; private static final int OPT_VERSION = 1034; static ResourceBundle messages; // Main. // ------------------------------------------------------------------------- public static void main (final String[] argv) { try { messages = PropertyResourceBundle.getBundle ("gnu/crypto/tool/keytool/MessagesBundle"); } catch (MissingResourceException mre) { System.err.println (PROGNAME + ": can't load messages bundle!"); System.err.println (PROGNAME + ": something is seriously wrong with your installation."); System.exit (1); } final LinkedList commands = new LinkedList(); Command cmd = new Command (); final String optstring = "thegirlsdpa:A:D:f:k:K:no:v"; final LongOpt[] longopts = { // Commands. new LongOpt ("delete", LongOpt.NO_ARGUMENT, null, 'd'), new LongOpt ("export", LongOpt.NO_ARGUMENT, null, 'e'), new LongOpt ("generate", LongOpt.NO_ARGUMENT, null, 'g'), new LongOpt ("help", LongOpt.NO_ARGUMENT, null, 'h'), new LongOpt ("import", LongOpt.NO_ARGUMENT, null, 'i'), new LongOpt ("list", LongOpt.NO_ARGUMENT, null, 'l'), new LongOpt ("path", LongOpt.NO_ARGUMENT, null, 'p'), new LongOpt ("revoke", LongOpt.NO_ARGUMENT, null, 'r'), new LongOpt ("sign", LongOpt.NO_ARGUMENT, null, 's'), new LongOpt ("trust", LongOpt.NO_ARGUMENT, null, 't'), new LongOpt ("version", LongOpt.NO_ARGUMENT, null, OPT_VERSION), // Options. new LongOpt ("alias", LongOpt.REQUIRED_ARGUMENT, null, 'a'), new LongOpt ("armor", LongOpt.NO_ARGUMENT, null, OPT_ARMOR), new LongOpt ("callback", LongOpt.REQUIRED_ARGUMENT, null, OPT_CALLBACK), new LongOpt ("ca-alias", LongOpt.REQUIRED_ARGUMENT, null, 'A'), new LongOpt ("cert-type", LongOpt.REQUIRED_ARGUMENT, null, OPT_CERT_TYPE), new LongOpt ("date", LongOpt.REQUIRED_ARGUMENT, null, OPT_DATE), new LongOpt ("debug", LongOpt.NO_ARGUMENT, null, OPT_DEBUG), new LongOpt ("file", LongOpt.REQUIRED_ARGUMENT, null, 'f'), new LongOpt ("keep-going", LongOpt.NO_ARGUMENT, null, 'n'), new LongOpt ("keystore", LongOpt.REQUIRED_ARGUMENT, null, 'k'), new LongOpt ("no-keystore", LongOpt.NO_ARGUMENT, null, OPT_NO_KEYSTORE), new LongOpt ("outfile", LongOpt.REQUIRED_ARGUMENT, null, 'o'), new LongOpt ("provider", LongOpt.REQUIRED_ARGUMENT, null, OPT_PNAME), new LongOpt ("provider-class", LongOpt.REQUIRED_ARGUMENT, null, OPT_PCLASS), new LongOpt ("secret-keystore",LongOpt.REQUIRED_ARGUMENT, null, 'K'), new LongOpt ("store-type", LongOpt.REQUIRED_ARGUMENT, null, OPT_STORE_TYPE), new LongOpt ("validity", LongOpt.REQUIRED_ARGUMENT, null, OPT_VALIDITY), new LongOpt ("verbose", LongOpt.NO_ARGUMENT, null, 'v') }; Getopt g = new Getopt (PROGNAME, argv, optstring, longopts); int c; boolean keep_going = false; boolean gnuCryptoProperty = false; boolean securityProperty = false; boolean debug = false; while ((c = g.getopt()) != -1) switch (c) { case 'd': commands.add (cmd = new Delete (cmd)); break; case 'e': commands.add (cmd = new Export (cmd)); break; case 'g': commands.add (cmd = new GenKey (cmd)); break; case 'i': commands.add (cmd = new Import (cmd)); break; case 'l': commands.add (cmd = new List (cmd)); break; case 'p': commands.add (cmd = new Path (cmd)); break; case 'r': commands.add (cmd = new Revoke (cmd)); break; case 's': commands.add (cmd = new Sign (cmd)); break; case 't': commands.add (cmd = new Trust (cmd)); break; case 'h': help (System.out); System.exit (0); case OPT_VERSION: version (System.out); if (keep_going) break; System.exit (0); case 'a': cmd.alias = g.getOptarg(); break; case 'A': cmd.caAlias = g.getOptarg(); break; case 'D': { String property = g.getOptarg(); String value = "true"; int i; if ((i = property.indexOf ('=')) >= 0) { value = property.substring (i + 1); property = property.substring (0, i); } try { if (securityProperty) Security.setProperty (property, value); else if (gnuCryptoProperty) Properties.setProperty (property, value); else { if (i < 0 && property.equals ("security")) securityProperty = true; else if (i < 0 && property.equals ("crypto")) gnuCryptoProperty = true; else { securityProperty = false; gnuCryptoProperty = false; System.setProperty (property, value); } } } catch (SecurityException se) { error ("security policy does not allow setting properties"); } } break; case 'f': cmd.file = g.getOptarg(); break; case 'k': cmd.storeFile = g.getOptarg(); break; case 'K': cmd.secretStore = g.getOptarg(); break; case 'n': keep_going = !keep_going; break; case 'o': cmd.outFile = g.getOptarg(); break; case 'v': cmd.verbose++; break; case OPT_ARMOR: cmd.armor = !cmd.armor; break; case OPT_CALLBACK: try { cmd.handler = AbstractCallbackHandler.getInstance (g.getOptarg(), new GnuCallbacks()); } catch (Exception e) { error ("can't load callback handler " + g.getOptarg() + ": " + e.getMessage()); } break; case OPT_DATE: try { cmd.date = DateFormat.getDateInstance().parse (g.getOptarg()); } catch (Exception x) { error ("can't format date: " + x.getMessage()); } break; case OPT_DEBUG: debug = true; break; case OPT_NO_KEYSTORE: cmd.noKeystore = !cmd.noKeystore; break; case OPT_PCLASS: try { cmd.provider = (Provider) Class.forName (g.getOptarg()).newInstance(); } catch (Exception e) { error ("can't load class " + g.getOptarg() + ": " + e.getMessage()); } break; case OPT_PNAME: cmd.provider = Security.getProvider (g.getOptarg().intern()); if (cmd.provider == null) { error ("provider " + g.getOptarg() + " is not available"); } break; case OPT_STORE_TYPE: cmd.storeType = g.getOptarg(); break; case OPT_VALIDITY: try { cmd.validity = Integer.parseInt (g.getOptarg()); if (cmd.validity <= 0) throw new NumberFormatException ("must be positive"); } catch (NumberFormatException nfe) { error ("invalid validity: " + nfe.getMessage()); } case '?': case ':': System.err.println ("Try `" + PROGNAME + " --help' for more info."); System.exit (1); } if (commands.size() == 0) { System.err.println (PROGNAME + ": no command given"); System.err.println ("Try `" + PROGNAME + " --help' for more info."); System.exit (1); } for (Iterator it = commands.iterator(); it.hasNext(); ) { try { cmd = (Command) it.next(); cmd.run(); } catch (Throwable t) { System.err.println (PROGNAME + ": " + cmd + ": " + t.getMessage()); if (debug) t.printStackTrace(); if (!keep_going) System.exit (1); } } } private static void help (final PrintStream out) { String msg = null; try { for (int i = 1; ; i++) { out.println (MessageFormat.format (messages.getString ("usage."+i), new Object[] { PROGNAME })); } } catch (MissingResourceException mre) { } out.println(); fill (messages.getString ("commands"), out); out.println(); int hc = 18; out.print (" -d, --delete "); fill (messages.getString ("command.delete"), out, hc); out.print (" -e, --export "); fill (messages.getString ("command.export"), out, hc); out.print (" -g, --generate "); fill (messages.getString ("command.generate"), out, hc); out.print (" -i, --import "); fill (messages.getString ("command.import"), out, hc); out.print (" -l, --list "); fill (messages.getString ("command.list"), out, hc); out.print (" -p, --path "); fill (messages.getString ("command.path"), out, hc); out.print (" -r, --revoke "); fill (messages.getString ("command.revoke"), out, hc); out.print (" -s, --sign "); fill (messages.getString ("command.sign"), out, hc); out.print (" -t, --trust "); fill (messages.getString ("command.trust"), out, hc); out.print (" -h, --help "); fill (messages.getString ("command.help"), out, hc); out.print (" --version "); fill (messages.getString ("command.version"), out, hc); out.println(); fill (messages.getString ("options"), out); out.println(); hc = 30; out.print (" -a, --alias=NAME "); fill (messages.getString ("opt.alias"), out, hc); out.print (" -A, --ca-alias=NAME "); fill (messages.getString ("opt.ca-alias"), out, hc); out.print (" --armor "); fill (messages.getString ("opt.armor"), out, hc); out.print (" --callback=TYPE "); fill (messages.getString ("opt.callback"), out, hc); out.print (" --cert-type=TYPE "); fill (messages.getString ("opt.cert-type"), out, hc); out.print (" --date=DATE "); fill (messages.getString ("opt.date"), out, hc); out.print (" -f, --file=FILE "); fill (messages.getString ("opt.file"), out, hc); out.print (" -k, --keystore=FILE "); fill (messages.getString ("opt.keystore"), out, hc); out.print (" -K, --secret-keystore=FILE "); fill (messages.getString ("opt.secret-keystore"), out, hc); out.print (" --truststore=FILE "); fill (messages.getString ("opt.truststore"), out, hc); out.print (" -n, --keep-going "); fill (messages.getString ("opt.keep-going"), out, hc); out.print (" --no-keystore "); fill (messages.getString ("opt.no-keystore"), out, hc); out.print (" -o, --outfile=FILE "); fill (messages.getString ("opt.outfile"), out, hc); out.print (" --provider=NAME "); fill (messages.getString ("opt.provider"), out, hc); out.print (" --provider-class=CLASS "); fill (messages.getString ("opt.provider-class"), out, hc); out.print (" --store-type=TYPE "); fill (messages.getString ("opt.store-type"), out, hc); out.print (" --validity=DAYS "); fill (messages.getString ("opt.validity"), out, hc); out.print (" -v, --verbose "); fill (messages.getString ("opt.verbose"), out, hc); out.print (" -Dname=value "); fill (messages.getString ("opt.D"), out, hc); } private static int FILL_COLUMN = 78; private static void fill (String message, final PrintStream out) { fill (message, out, 0); } private static void fill (String message, final PrintStream out, final int hangColumn) { int col = hangColumn; StringTokenizer tok = new StringTokenizer (message); String token = null; while (tok.hasMoreTokens() || token != null) { while (col < hangColumn) { out.print (' '); col++; } if (token == null) token = tok.nextToken(); if (col + token.length() + (col > hangColumn ? 1 : 0) > FILL_COLUMN && col != hangColumn) { out.println(); col = 0; continue; } if (col > hangColumn) { col++; out.print (' '); } out.print (token); col += token.length(); token = null; } out.println(); } private static void version (final PrintStream out) { out.print (PROGNAME); out.print (" (GNU Crypto version "); out.print (Registry.VERSION_STRING); out.println (")"); out.println ("Copyright (C) 2004 Free Software Foundation, Inc."); out.println(); fill (messages.getString ("boilerplate"), out); } private static void error (final String message) { System.err.print (PROGNAME); System.err.print (": "); System.err.println (message); System.exit (1); } }