/* Main.java -- JAR signing and verification tool not unlike jarsigner
   Copyright (C) 2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath 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 Classpath 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 GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.classpath.tools.jarsigner;

import gnu.classpath.Configuration;
import gnu.classpath.SystemProperties;
import gnu.classpath.tools.common.CallbackUtil;
import gnu.classpath.tools.common.ProviderUtil;
import gnu.classpath.tools.getopt.ClasspathToolParser;
import gnu.classpath.tools.getopt.FileArgumentCallback;
import gnu.classpath.tools.getopt.Option;
import gnu.classpath.tools.getopt.OptionException;
import gnu.classpath.tools.getopt.OptionGroup;
import gnu.java.security.OID;
import gnu.java.security.Registry;
import gnu.javax.security.auth.callback.ConsoleCallbackHandler;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Locale;
import java.util.jar.Attributes.Name;
import java.util.logging.Logger;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;

/**
 * The GNU Classpath implementation of the <i>jarsigner</i> tool.
 * <p>
 * The <i>jarsigner</i> tool is used to sign and verify JAR (Java ARchive)
 * files.
 * <p>
 * This implementation is intended to be compatible with the behaviour
 * described in the public documentation of the same tool included in JDK 1.4.
 */
public class Main
{
  protected static final Logger log = Logger.getLogger(Main.class.getName());
  static final String KEYTOOL_TOOL = "jarsigner"; //$NON-NLS-1$
  private static final Locale EN_US_LOCALE = new Locale("en", "US"); //$NON-NLS-1$ //$NON-NLS-2$
  static final String DIGEST = "SHA1-Digest"; //$NON-NLS-1$
  static final String DIGEST_MANIFEST = "SHA1-Digest-Manifest"; //$NON-NLS-1$
  static final Name DIGEST_ATTR = new Name(DIGEST);
  static final Name DIGEST_MANIFEST_ATTR = new Name(DIGEST_MANIFEST);
  static final OID DSA_SIGNATURE_OID = new OID(Registry.DSA_OID_STRING);
  static final OID RSA_SIGNATURE_OID = new OID(Registry.RSA_OID_STRING);

  protected boolean verify;
  protected String ksURL;
  protected String ksType;
  protected String password;
  protected String ksPassword;
  protected String sigFileName;
  protected String signedJarFileName;
  protected boolean verbose;
  protected boolean certs;
  protected boolean internalSF;
  protected boolean sectionsOnly;
  protected String providerClassName;
  protected String jarFileName;
  protected String alias;

  protected Provider provider;
  private boolean providerInstalled;
  private char[] ksPasswordChars;
  private KeyStore store;
  private char[] passwordChars;
  private PrivateKey signerPrivateKey;
  private Certificate[] signerCertificateChain;
  /** The callback handler to use when needing to interact with user. */
  private CallbackHandler handler;
  /** The command line parser. */
  private ToolParser cmdLineParser;
  protected ArrayList fileAndAlias = new ArrayList();;

  private Main()
  {
    super();
  }

  public static final void main(String[] args)
  {
    if (Configuration.DEBUG)
      log.entering(Main.class.getName(), "main", args); //$NON-NLS-1$
    Main tool = new Main();
    int result = 1;
    try
      {
        tool.processArgs(args);
        tool.start();
        result = 0;
      }
    catch (SecurityException x)
      {
        if (Configuration.DEBUG)
          log.throwing(Main.class.getName(), "main", x); //$NON-NLS-1$
        System.err.println(Messages.getString("Main.7") + x.getMessage()); //$NON-NLS-1$
      }
    catch (Exception x)
      {
        if (Configuration.DEBUG)
          log.throwing(Main.class.getName(), "main", x); //$NON-NLS-1$
        System.err.println(Messages.getString("Main.9") + x); //$NON-NLS-1$
      }
    finally
      {
        tool.teardown();
      }
    if (Configuration.DEBUG)
      log.exiting(Main.class.getName(), "main", Integer.valueOf(result)); //$NON-NLS-1$
    System.exit(result);
  }

  // helper methods -----------------------------------------------------------

  /**
   * Read the command line arguments setting the tool's parameters in
   * preparation for the user desired action.
   * 
   * @param args an array of options (strings).
   * @throws Exception if an exception occurs during the process.
   */
  private void processArgs(String[] args) throws Exception
  {
    if (Configuration.DEBUG)
      log.entering(this.getClass().getName(), "processArgs", args); //$NON-NLS-1$
    cmdLineParser = new ToolParser();
    cmdLineParser.initializeParser();
    cmdLineParser.parse(args, new ToolParserCallback());

    setupCommonParams();
    if (verify)
      {
        if (Configuration.DEBUG)
          {
            log.fine("Will verify with the following parameters:"); //$NON-NLS-1$
            log.fine("     jar-file = '" + jarFileName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
            log.fine("Options:"); //$NON-NLS-1$
            log.fine("     provider = '" + providerClassName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
            log.fine("      verbose ? " + verbose); //$NON-NLS-1$
            log.fine("        certs ? " + certs); //$NON-NLS-1$
            log.fine("   internalsf ? " + internalSF); //$NON-NLS-1$
            log.fine(" sectionsonly ? " + sectionsOnly); //$NON-NLS-1$
          }
      }
    else // sign
      {
        setupSigningParams();
        if (Configuration.DEBUG)
          {
            log.fine("Will sign with the following parameters:"); //$NON-NLS-1$
            log.fine("     jar-file = '" + jarFileName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
            log.fine("        alias = '" + alias + "'"); //$NON-NLS-1$ //$NON-NLS-2$
            log.fine("Options:"); //$NON-NLS-1$
            log.fine("     keystore = '" + ksURL + "'"); //$NON-NLS-1$ //$NON-NLS-2$
            log.fine("    storetype = '" + ksType + "'"); //$NON-NLS-1$ //$NON-NLS-2$
            log.fine("    storepass = '" + ksPassword + "'"); //$NON-NLS-1$ //$NON-NLS-2$
            log.fine("      keypass = '" + password + "'"); //$NON-NLS-1$ //$NON-NLS-2$
            log.fine("      sigfile = '" + sigFileName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
            log.fine("    signedjar = '" + signedJarFileName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
            log.fine("     provider = '" + providerClassName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
            log.fine("      verbose ? " + verbose); //$NON-NLS-1$
            log.fine("   internalsf ? " + internalSF); //$NON-NLS-1$
            log.fine(" sectionsonly ? " + sectionsOnly); //$NON-NLS-1$
          }
      }
    if (Configuration.DEBUG)
      log.exiting(this.getClass().getName(), "processArgs"); //$NON-NLS-1$
  }

  /**
   * Invokes the <code>start()</code> method of the concrete handler.
   * <p>
   * Depending on the result of processing the command line arguments, this
   * handler may be one for signing the jar, or verifying it.
   * 
   * @throws Exception if an exception occurs during the process.
   */
  private void start() throws Exception
  {
    if (Configuration.DEBUG)
      log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
    if (verify)
      {
        JarVerifier jv = new JarVerifier(this);
        jv.start();
      }
    else
      {
        JarSigner js = new JarSigner(this);
        js.start();
      }
    if (Configuration.DEBUG)
      log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
  }

  /**
   * Ensures that the underlying JVM is left in the same state as we found it
   * when we first launched the tool. Specifically, if we have installed a new
   * security provider then now is the time to remove it.
   * <p>
   * Note (rsn): this may not be necessary if we terminate the JVM; i.e. call
   * {@link System#exit(int)} at the end of the tool's invocation. Nevertheless
   * it's good practive to return the JVM to its initial state.
   */
  private void teardown()
  {
    if (Configuration.DEBUG)
      log.entering(this.getClass().getName(), "teardown"); //$NON-NLS-1$
    if (providerInstalled)
      ProviderUtil.removeProvider(provider.getName());

    if (Configuration.DEBUG)
      log.exiting(this.getClass().getName(), "teardown"); //$NON-NLS-1$
  }

  /**
   * After processing the command line arguments, this method is invoked to
   * process the common parameters which may have been encountered among the
   * actual arguments.
   * <p>
   * Common parameters are those which are allowed in both signing and
   * verification modes.
   * 
   * @throws InstantiationException if a security provider class name is
   *           specified but that class name is that of either an interface or
   *           an abstract class.
   * @throws IllegalAccessException if a security provider class name is
   *           specified but no 0-arguments constructor is defined for that
   *           class.
   * @throws ClassNotFoundException if a security provider class name is
   *           specified but no such class was found in the classpath.
   * @throws IOException if the JAR file name for signing, or verifying, does
   *           not exist, exists but denotes a directory, or is not readable.
   */
  private void setupCommonParams() throws InstantiationException,
      IllegalAccessException, ClassNotFoundException, IOException
  {
    if (Configuration.DEBUG)
      log.entering(this.getClass().getName(), "setupCommonParams"); //$NON-NLS-1$
    File jar = new File(jarFileName);
    if (! jar.exists())
      throw new FileNotFoundException(jarFileName);

    if (jar.isDirectory())
      throw new IOException(Messages.getFormattedString("Main.70", jarFileName)); //$NON-NLS-1$

    if (! jar.canRead())
      throw new IOException(Messages.getFormattedString("Main.72", jarFileName)); //$NON-NLS-1$ //$NON-NLS-2$

    if (providerClassName != null && providerClassName.length() > 0)
      {
        provider = (Provider) Class.forName(providerClassName).newInstance();
        // is it already installed?
        String providerName = provider.getName();
        Provider installedProvider = Security.getProvider(providerName);
        if (installedProvider != null)
          {
            if (Configuration.DEBUG)
              log.finer("Provider " + providerName + " is already installed"); //$NON-NLS-1$ //$NON-NLS-2$
          }
        else // install it
          installNewProvider();
      }

    if (! verbose && certs)
      {
        if (Configuration.DEBUG)
          log.fine("Option <certs> is set but <verbose> is not. Ignored"); //$NON-NLS-1$
        certs = false;
      }

    if (Configuration.DEBUG)
      log.exiting(this.getClass().getName(), "setupCommonParams"); //$NON-NLS-1$
  }

  /**
   * Install the user defined security provider in the underlying JVM.
   * <p>
   * Also record this fact so we can remove it when we exit the tool.
   */
  private void installNewProvider()
  {
    if (Configuration.DEBUG)
      log.entering(this.getClass().getName(), "installNewProvider"); //$NON-NLS-1$
    providerInstalled = ProviderUtil.addProvider(provider) != -1;
    if (Configuration.DEBUG)
      log.exiting(this.getClass().getName(), "installNewProvider"); //$NON-NLS-1$
  }

  /**
   * After processing the command line arguments, this method is invoked to
   * process the parameters which may have been encountered among the actual
   * arguments, and which are specific to the signing action of the tool.
   * 
   * @throws KeyStoreException if no implementation of the designated (or
   *           default type) of a key store is availabe.
   * @throws IOException if an I/O related exception occurs during the process.
   * @throws NoSuchAlgorithmException if an implementation of an algorithm used
   *           by the key store is not available.
   * @throws CertificateException if an exception occurs while reading a
   *           certificate from the key store.
   * @throws UnsupportedCallbackException if no implementation of a password
   *           callback is available.
   * @throws UnrecoverableKeyException if the wrong password was used to unlock
   *           the key store.
   * @throws SecurityException if the designated alias is not known to the key
   *           store or is not an Alias of a Key Entry.
   */
  private void setupSigningParams() throws KeyStoreException, IOException,
      NoSuchAlgorithmException, CertificateException,
      UnsupportedCallbackException, UnrecoverableKeyException
  {
    if (Configuration.DEBUG)
      log.entering(this.getClass().getName(), "setupSigningParams"); //$NON-NLS-1$
    if (ksURL == null || ksURL.trim().length() == 0)
      {
        String userHome = SystemProperties.getProperty("user.home"); //$NON-NLS-1$
        if (userHome == null || userHome.trim().length() == 0)
          throw new SecurityException(Messages.getString("Main.85")); //$NON-NLS-1$

        ksURL = "file:" + userHome.trim() + "/.keystore"; //$NON-NLS-1$ //$NON-NLS-2$
      }
    else
      {
        ksURL = ksURL.trim();
        if (ksURL.indexOf(":") == -1) //$NON-NLS-1$
          ksURL = "file:" + ksURL; //$NON-NLS-1$
      }

    if (ksType == null || ksType.trim().length() == 0)
      ksType = KeyStore.getDefaultType();
    else
      ksType = ksType.trim();

    store = KeyStore.getInstance(ksType);

    if (ksPassword == null)
      {
        // ask the user to provide one
        PasswordCallback pcb = new PasswordCallback(Messages.getString("Main.92"), //$NON-NLS-1$
                                                    false);
        getCallbackHandler().handle(new Callback[] { pcb });
        ksPasswordChars = pcb.getPassword();
      }
    else
      ksPasswordChars = ksPassword.toCharArray();

    URL url = new URL(ksURL);
    InputStream stream = url.openStream();
    store.load(stream, ksPasswordChars);

    if (! store.containsAlias(alias))
      throw new SecurityException(Messages.getFormattedString("Main.6", alias)); //$NON-NLS-1$

    if (! store.isKeyEntry(alias))
      throw new SecurityException(Messages.getFormattedString("Main.95", alias)); //$NON-NLS-1$

    Key key;
    if (password == null)
      {
        passwordChars = ksPasswordChars;
        try
          {
            key = store.getKey(alias, passwordChars);
          }
        catch (UnrecoverableKeyException x)
          {
            // ask the user to provide one
            String prompt = Messages.getFormattedString("Main.97", alias); //$NON-NLS-1$
            PasswordCallback pcb = new PasswordCallback(prompt, false);
            getCallbackHandler().handle(new Callback[] { pcb });
            passwordChars = pcb.getPassword();
            // take 2
            key = store.getKey(alias, passwordChars);
          }
      }
    else
      {
        passwordChars = password.toCharArray();
        key = store.getKey(alias, passwordChars);
      }

    if (! (key instanceof PrivateKey))
      throw new SecurityException(Messages.getFormattedString("Main.99", alias)); //$NON-NLS-1$

    signerPrivateKey = (PrivateKey) key;
    signerCertificateChain = store.getCertificateChain(alias);
    if (Configuration.DEBUG)
      log.fine(String.valueOf(signerCertificateChain));

    if (sigFileName == null)
      sigFileName = alias;

    sigFileName = sigFileName.toUpperCase(EN_US_LOCALE);
    if (sigFileName.length() > 8)
      sigFileName = sigFileName.substring(0, 8);

    char[] chars = sigFileName.toCharArray();
    for (int i = 0; i < chars.length; i++)
      {
        char c = chars[i];
        if (! (Character.isLetter(c)
            || Character.isDigit(c)
            || c == '_'
            || c == '-'))
          chars[i] = '_';
      }

    sigFileName = new String(chars);

    if (signedJarFileName == null)
      signedJarFileName = jarFileName;

    if (Configuration.DEBUG)
      log.exiting(this.getClass().getName(), "setupSigningParams"); //$NON-NLS-1$
  }

  boolean isVerbose()
  {
    return verbose;
  }

  boolean isCerts()
  {
    return certs;
  }

  String getSigFileName()
  {
    return this.sigFileName;
  }

  String getJarFileName()
  {
    return this.jarFileName;
  }

  boolean isSectionsOnly()
  {
    return this.sectionsOnly;
  }

  boolean isInternalSF()
  {
    return this.internalSF;
  }

  PrivateKey getSignerPrivateKey()
  {
    return this.signerPrivateKey;
  }

  Certificate[] getSignerCertificateChain()
  {
    return signerCertificateChain;
  }

  String getSignedJarFileName()
  {
    return this.signedJarFileName;
  }

  /**
   * Return a CallbackHandler which uses the Console (System.in and System.out)
   * for interacting with the user.
   * <p>
   * This method first finds all currently installed security providers capable
   * of providing such service and then in turn attempts to instantiate the
   * handler from those providers. As soon as one provider returns a non-null
   * instance of the callback handler, the search stops and that instance is
   * set to be used from now on.
   * <p>
   * If no installed providers were found, this method falls back on the GNU
   * provider, by-passing the Security search mechanism. The default console
   * callback handler implementation is {@link ConsoleCallbackHandler}.
   * 
   * @return a console-based {@link CallbackHandler}.
   */
  protected CallbackHandler getCallbackHandler()
  {
    if (handler == null)
      handler = CallbackUtil.getConsoleHandler();

    return handler;
  }

  private class ToolParserCallback
      extends FileArgumentCallback
  {
    public void notifyFile(String fileArgument)
    {
      fileAndAlias.add(fileArgument);
    }
  }

  private class ToolParser
      extends ClasspathToolParser
  {
    public ToolParser()
    {
      super(KEYTOOL_TOOL, true);
    }

    protected void validate() throws OptionException
    {
      if (fileAndAlias.size() < 1)
        throw new OptionException(Messages.getString("Main.133")); //$NON-NLS-1$

      jarFileName = (String) fileAndAlias.get(0);
      if (! verify) // must have an ALIAS. use "mykey" if undefined
        if (fileAndAlias.size() < 2)
          {
            if (Configuration.DEBUG)
              log.fine("Missing ALIAS argument. Will use [mykey] instead"); //$NON-NLS-1$
            alias = "mykey"; //$NON-NLS-1$
          }
        else
          alias = (String) fileAndAlias.get(1);
    }

    public void initializeParser()
    {
      setHeader(Messages.getString("Main.2")); //$NON-NLS-1$
      setFooter(Messages.getString("Main.1")); //$NON-NLS-1$
      OptionGroup signGroup = new OptionGroup(Messages.getString("Main.0")); //$NON-NLS-1$
      signGroup.add(new Option("keystore", //$NON-NLS-1$
                               Messages.getString("Main.101"), //$NON-NLS-1$
                               Messages.getString("Main.102")) //$NON-NLS-1$
      {
        public void parsed(String argument) throws OptionException
        {
          ksURL = argument;
        }
      });
      signGroup.add(new Option("storetype", //$NON-NLS-1$
                               Messages.getString("Main.104"), //$NON-NLS-1$
                               Messages.getString("Main.105")) //$NON-NLS-1$
      {
        public void parsed(String argument) throws OptionException
        {
          ksType = argument;
        }
      });
      signGroup.add(new Option("storepass", //$NON-NLS-1$
                               Messages.getString("Main.107"), //$NON-NLS-1$
                               Messages.getString("Main.108")) //$NON-NLS-1$
      {
        public void parsed(String argument) throws OptionException
        {
          ksPassword = argument;
        }
      });
      signGroup.add(new Option("keypass", //$NON-NLS-1$
                               Messages.getString("Main.110"), //$NON-NLS-1$
                               Messages.getString("Main.111")) //$NON-NLS-1$
      {
        public void parsed(String argument) throws OptionException
        {
          password = argument;
        }
      });
      signGroup.add(new Option("sigfile", //$NON-NLS-1$
                               Messages.getString("Main.113"), //$NON-NLS-1$
                               Messages.getString("Main.114")) //$NON-NLS-1$
      {
        public void parsed(String argument) throws OptionException
        {
          sigFileName = argument;
        }
      });
      signGroup.add(new Option("signedjar", //$NON-NLS-1$
                               Messages.getString("Main.116"), //$NON-NLS-1$
                               Messages.getString("Main.117")) //$NON-NLS-1$
      {
        public void parsed(String argument) throws OptionException
        {
          signedJarFileName = argument;
        }
      });
      add(signGroup);

      OptionGroup verifyGroup = new OptionGroup(Messages.getString("Main.118")); //$NON-NLS-1$
      verifyGroup.add(new Option("verify", //$NON-NLS-1$
                                 Messages.getString("Main.120")) //$NON-NLS-1$
      {
        public void parsed(String argument) throws OptionException
        {
          verify = true;
        }
      });
      verifyGroup.add(new Option("certs", //$NON-NLS-1$
                                 Messages.getString("Main.122")) //$NON-NLS-1$
      {
        public void parsed(String argument) throws OptionException
        {
          certs = true;
        }
      });
      add(verifyGroup);

      OptionGroup commonGroup = new OptionGroup(Messages.getString("Main.123")); //$NON-NLS-1$
      commonGroup.add(new Option("verbose", //$NON-NLS-1$
                                 Messages.getString("Main.125")) //$NON-NLS-1$
      {
        public void parsed(String argument) throws OptionException
        {
          verbose = true;
        }
      });
      commonGroup.add(new Option("internalsf", //$NON-NLS-1$
                                 Messages.getString("Main.127")) //$NON-NLS-1$
      {
        public void parsed(String argument) throws OptionException
        {
          internalSF = true;
        }
      });
      commonGroup.add(new Option("sectionsonly", //$NON-NLS-1$
                                 Messages.getString("Main.129")) //$NON-NLS-1$
      {
        public void parsed(String argument) throws OptionException
        {
          sectionsOnly = true;
        }
      });
      commonGroup.add(new Option("provider", //$NON-NLS-1$
                                 Messages.getString("Main.131"), //$NON-NLS-1$
                                 Messages.getString("Main.132")) //$NON-NLS-1$
      {
        public void parsed(String argument) throws OptionException
        {
          providerClassName = argument;
        }
      });
      add(commonGroup);
    }
  }
}
