Imported GNU Classpath 0.90

Imported GNU Classpath 0.90
       * scripts/makemake.tcl: LocaleData.java moved to gnu/java/locale.

       * sources.am: Regenerated.
       * gcj/javaprims.h: Regenerated.
       * Makefile.in: Regenerated.
       * gcj/Makefile.in: Regenerated.
       * include/Makefile.in: Regenerated.
       * testsuite/Makefile.in: Regenerated.

       * gnu/java/lang/VMInstrumentationImpl.java: New override.
       * gnu/java/net/local/LocalSocketImpl.java: Likewise.
       * gnu/classpath/jdwp/VMMethod.java: Likewise.
       * gnu/classpath/jdwp/VMVirtualMachine.java: Update to latest
       interface.
       * java/lang/Thread.java: Add UncaughtExceptionHandler.
       * java/lang/reflect/Method.java: Implements GenericDeclaration and
       isSynthetic(),
       * java/lang/reflect/Field.java: Likewise.
       * java/lang/reflect/Constructor.java
       * java/lang/Class.java: Implements Type, GenericDeclaration,
       getSimpleName() and getEnclosing*() methods.
       * java/lang/Class.h: Add new public methods.
       * java/lang/Math.java: Add signum(), ulp() and log10().
       * java/lang/natMath.cc (log10): New function.
       * java/security/VMSecureRandom.java: New override.
       * java/util/logging/Logger.java: Updated to latest classpath
       version.
       * java/util/logging/LogManager.java: New override.

From-SVN: r113887
This commit is contained in:
Mark Wielaard
2006-05-18 17:29:21 +00:00
parent eaec4980e1
commit 4f9533c772
1640 changed files with 126485 additions and 104808 deletions
-3
View File
@@ -1,3 +0,0 @@
Makefile.in
Makefile
tools.zip
+12 -33
View File
@@ -1,17 +1,19 @@
## Input file for automake to generate the Makefile.in used by configure
GLIBJ_CLASSPATH='$(top_builddir)/lib':'$(top_builddir)/lib/glibj.zip'
# Setup the compiler to use the GNU Classpath library we just build
if FOUND_GCJ
JCOMPILER = $(GCJ) --bootclasspath '$(top_builddir)/lib' --classpath . -C
JCOMPILER = $(GCJ) -encoding UTF-8 --bootclasspath $(GLIBJ_CLASSPATH) --classpath . -C
else
if FOUND_JIKES
JCOMPILER = $(JIKES) -bootclasspath '' -extdirs '' -sourcepath '' --classpath $(top_builddir)/lib:.
JCOMPILER = $(JIKES) $(JIKESENCODING) -bootclasspath '' -extdirs '' -sourcepath '' --classpath $(GLIBJ_CLASSPATH):.
else
if FOUND_GCJX
JCOMPILER = $(GCJX) -bootclasspath '' -sourcepath '' -classpath $(top_builddir)/lib:.
JCOMPILER = $(GCJX) -encoding UTF-8 -bootclasspath '' -sourcepath '' -classpath $(GLIBJ_CLASSPATH):.
else
if FOUND_ECJ
JCOMPILER = $(ECJ) -bootclasspath '$(top_builddir)/lib' -classpath .
JCOMPILER = $(ECJ) -encoding UTF-8 -bootclasspath $(GLIBJ_CLASSPATH) -classpath .
else
error dunno how to setup the JCOMPILER and compile
endif
@@ -48,36 +50,12 @@ READMES = $(srcdir)/gnu/classpath/tools/giop/README
ALL_TOOLS_FILES = $(TOOLS_JAVA_FILES) $(TOOLS_TEMPLATES) $(TOOLS_HELPS) $(READMES)
# Some architecture independent data to be installed.
TOOLS_DATA = $(TOOLS_ZIP)
TOOLS_DATA = $(TOOLS_ZIP) README
# Where we want these data files installed.
TOOLSdir = $(pkgdatadir)/tools
# Make sure all sources and icons are also installed so users can use them.
# (Be careful to strip off the srcdir part of the path when installing.)
install-data-local:
srcdir_cnt=`echo $(srcdir) | wc -c`; \
for file in $(ALL_TOOLS_FILES); do \
f=`echo $$file | cut -c$$srcdir_cnt-`; \
fdir=`dirname $$f`; \
if test ! -d $(DESTDIR)$(pkgdatadir)/tools/$$fdir; then \
echo "$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/tools/$$fdir"; \
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/tools/$$fdir; \
fi; \
echo "$(INSTALL_DATA) $$file $(DESTDIR)$(pkgdatadir)/tools/$$f"; \
$(INSTALL_DATA) $$file $(DESTDIR)$(pkgdatadir)/tools/$$f; \
done
uninstall-local:
srcdir_cnt=`echo $(srcdir) | wc -c`; \
for file in $(ALL_TOOLS_FILES); do \
f=`echo $$file | cut -c$$srcdir_cnt-`; \
echo "rm -f $(DESTDIR)$(pkgdatadir)/tools/$$f"; \
rm -f $(DESTDIR)$(pkgdatadir)/tools/$$f; \
done
TOOLSdir = $(pkgdatadir)
# Make sure everything is included in the distribution.
EXTRA_DIST = Makefile.am
dist-hook:
srcdir_cnt=`echo $(srcdir) | wc -c`; \
for file in $(ALL_TOOLS_FILES); do \
@@ -91,9 +69,10 @@ dist-hook:
cp -p $$file $(distdir)/$$f; \
done
# To generate the example zip just depend on the sources and ignore the
# class files. Always regenerate all .class files and remove them immediatly.
# And copy the template files we use to the classes dir so they get also included.
# To generate the example zip just depend on the sources and ignore
# the class files. Always regenerate all .class files and remove them
# immediately. And copy the template files we use to the classes dir
# so they get also included.
$(TOOLS_ZIP): $(TOOLS_JAVA_FILES)
mkdir -p classes/gnu/classpath/tools/giop/grmic/templates
mkdir -p classes/gnu/classpath/tools/rmi/rmic/templates
+43 -48
View File
@@ -38,7 +38,8 @@ build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = tools
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(srcdir)/jarsigner.sh.in $(srcdir)/keytool.sh.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../../libtool.m4 \
$(top_srcdir)/m4/acattribute.m4 $(top_srcdir)/m4/accross.m4 \
@@ -51,7 +52,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_FILES = jarsigner.sh keytool.sh
SOURCES =
DIST_SOURCES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
@@ -79,6 +80,7 @@ CAIRO_LIBS = @CAIRO_LIBS@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CLASSPATH_CONVENIENCE = @CLASSPATH_CONVENIENCE@
CLASSPATH_INCLUDES = @CLASSPATH_INCLUDES@
CLASSPATH_MODULE = @CLASSPATH_MODULE@
COLLECTIONS_PREFIX = @COLLECTIONS_PREFIX@
@@ -118,6 +120,8 @@ ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
ECJ = @ECJ@
EGREP = @EGREP@
ENABLE_LOCAL_SOCKETS_FALSE = @ENABLE_LOCAL_SOCKETS_FALSE@
ENABLE_LOCAL_SOCKETS_TRUE = @ENABLE_LOCAL_SOCKETS_TRUE@
ERROR_CFLAGS = @ERROR_CFLAGS@
EXAMPLESDIR = @EXAMPLESDIR@
EXEEXT = @EXEEXT@
@@ -138,6 +142,7 @@ FREETYPE2_LIBS = @FREETYPE2_LIBS@
GCJ = @GCJ@
GCJX = @GCJX@
GJDOC = @GJDOC@
GREP = @GREP@
GTK_CAIRO_ENABLED = @GTK_CAIRO_ENABLED@
GTK_CAIRO_FALSE = @GTK_CAIRO_FALSE@
GTK_CAIRO_TRUE = @GTK_CAIRO_TRUE@
@@ -185,6 +190,7 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
PANGOFT2_CFLAGS = @PANGOFT2_CFLAGS@
PANGOFT2_LIBS = @PANGOFT2_LIBS@
PATH_SEPARATOR = @PATH_SEPARATOR@
PATH_TO_GLIBJ_ZIP = @PATH_TO_GLIBJ_ZIP@
PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
QT_CFLAGS = @QT_CFLAGS@
@@ -203,8 +209,11 @@ USER_SPECIFIED_CLASSLIB_FALSE = @USER_SPECIFIED_CLASSLIB_FALSE@
USER_SPECIFIED_CLASSLIB_TRUE = @USER_SPECIFIED_CLASSLIB_TRUE@
USER_SPECIFIED_JAVAH_FALSE = @USER_SPECIFIED_JAVAH_FALSE@
USER_SPECIFIED_JAVAH_TRUE = @USER_SPECIFIED_JAVAH_TRUE@
USE_PREBUILT_GLIBJ_ZIP_FALSE = @USE_PREBUILT_GLIBJ_ZIP_FALSE@
USE_PREBUILT_GLIBJ_ZIP_TRUE = @USE_PREBUILT_GLIBJ_ZIP_TRUE@
VERSION = @VERSION@
WARNING_CFLAGS = @WARNING_CFLAGS@
XMKMF = @XMKMF@
XML_CFLAGS = @XML_CFLAGS@
XML_LIBS = @XML_LIBS@
XSLT_CFLAGS = @XSLT_CFLAGS@
@@ -216,8 +225,6 @@ X_PRE_LIBS = @X_PRE_LIBS@
ZIP = @ZIP@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
@@ -234,7 +241,10 @@ build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
datarootdir = @datarootdir@
default_toolkit = @default_toolkit@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
glibjdir = @glibjdir@
host = @host@
@@ -242,18 +252,22 @@ host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
nativelibdir = @nativelibdir@
nativeexeclibdir = @nativeexeclibdir@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
@@ -263,12 +277,13 @@ target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
vm_classes = @vm_classes@
@FOUND_ECJ_TRUE@@FOUND_GCJX_FALSE@@FOUND_GCJ_FALSE@@FOUND_JIKES_FALSE@JCOMPILER = $(ECJ) -bootclasspath '$(top_builddir)/lib' -classpath .
@FOUND_GCJX_TRUE@@FOUND_GCJ_FALSE@@FOUND_JIKES_FALSE@JCOMPILER = $(GCJX) -bootclasspath '' -sourcepath '' -classpath $(top_builddir)/lib:.
@FOUND_GCJ_FALSE@@FOUND_JIKES_TRUE@JCOMPILER = $(JIKES) -bootclasspath '' -extdirs '' -sourcepath '' --classpath $(top_builddir)/lib:.
GLIBJ_CLASSPATH = '$(top_builddir)/lib':'$(top_builddir)/lib/glibj.zip'
@FOUND_ECJ_TRUE@@FOUND_GCJX_FALSE@@FOUND_GCJ_FALSE@@FOUND_JIKES_FALSE@JCOMPILER = $(ECJ) -encoding UTF-8 -bootclasspath $(GLIBJ_CLASSPATH) -classpath .
@FOUND_GCJX_TRUE@@FOUND_GCJ_FALSE@@FOUND_JIKES_FALSE@JCOMPILER = $(GCJX) -encoding UTF-8 -bootclasspath '' -sourcepath '' -classpath $(GLIBJ_CLASSPATH):.
@FOUND_GCJ_FALSE@@FOUND_JIKES_TRUE@JCOMPILER = $(JIKES) $(JIKESENCODING) -bootclasspath '' -extdirs '' -sourcepath '' --classpath $(GLIBJ_CLASSPATH):.
# Setup the compiler to use the GNU Classpath library we just build
@FOUND_GCJ_TRUE@JCOMPILER = $(GCJ) --bootclasspath '$(top_builddir)/lib' --classpath . -C
@FOUND_GCJ_TRUE@JCOMPILER = $(GCJ) -encoding UTF-8 --bootclasspath $(GLIBJ_CLASSPATH) --classpath . -C
# All our example java source files
TOOLS_JAVA_FILES = $(srcdir)/gnu/classpath/tools/*.java $(srcdir)/gnu/classpath/tools/*/*.java $(srcdir)/gnu/classpath/tools/*/*/*.java
@@ -296,13 +311,10 @@ READMES = $(srcdir)/gnu/classpath/tools/giop/README
ALL_TOOLS_FILES = $(TOOLS_JAVA_FILES) $(TOOLS_TEMPLATES) $(TOOLS_HELPS) $(READMES)
# Some architecture independent data to be installed.
TOOLS_DATA = $(TOOLS_ZIP)
TOOLS_DATA = $(TOOLS_ZIP) README
# Where we want these data files installed.
TOOLSdir = $(pkgdatadir)/tools
# Make sure everything is included in the distribution.
EXTRA_DIST = Makefile.am
TOOLSdir = $(pkgdatadir)
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-am
@@ -336,6 +348,10 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
jarsigner.sh: $(top_builddir)/config.status $(srcdir)/jarsigner.sh.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
keytool.sh: $(top_builddir)/config.status $(srcdir)/keytool.sh.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
mostlyclean-libtool:
-rm -f *.lo
@@ -452,7 +468,7 @@ info: info-am
info-am:
install-data-am: install-TOOLSDATA install-data-local
install-data-am: install-TOOLSDATA
install-exec-am:
@@ -478,44 +494,22 @@ ps: ps-am
ps-am:
uninstall-am: uninstall-TOOLSDATA uninstall-info-am uninstall-local
uninstall-am: uninstall-TOOLSDATA uninstall-info-am
.PHONY: all all-am check check-am clean clean-generic clean-libtool \
clean-local dist-hook distclean distclean-generic \
distclean-libtool distdir dvi dvi-am html html-am info info-am \
install install-TOOLSDATA install-am install-data \
install-data-am install-data-local install-exec \
install-exec-am install-info install-info-am install-man \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
uninstall uninstall-TOOLSDATA uninstall-am uninstall-info-am \
uninstall-local
install-data-am install-exec install-exec-am install-info \
install-info-am install-man install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am uninstall \
uninstall-TOOLSDATA uninstall-am uninstall-info-am
@FOUND_ECJ_FALSE@@FOUND_GCJX_FALSE@@FOUND_GCJ_FALSE@@FOUND_JIKES_FALSE@error dunno how to setup the JCOMPILER and compile
# Make sure all sources and icons are also installed so users can use them.
# (Be careful to strip off the srcdir part of the path when installing.)
install-data-local:
srcdir_cnt=`echo $(srcdir) | wc -c`; \
for file in $(ALL_TOOLS_FILES); do \
f=`echo $$file | cut -c$$srcdir_cnt-`; \
fdir=`dirname $$f`; \
if test ! -d $(DESTDIR)$(pkgdatadir)/tools/$$fdir; then \
echo "$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/tools/$$fdir"; \
$(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/tools/$$fdir; \
fi; \
echo "$(INSTALL_DATA) $$file $(DESTDIR)$(pkgdatadir)/tools/$$f"; \
$(INSTALL_DATA) $$file $(DESTDIR)$(pkgdatadir)/tools/$$f; \
done
uninstall-local:
srcdir_cnt=`echo $(srcdir) | wc -c`; \
for file in $(ALL_TOOLS_FILES); do \
f=`echo $$file | cut -c$$srcdir_cnt-`; \
echo "rm -f $(DESTDIR)$(pkgdatadir)/tools/$$f"; \
rm -f $(DESTDIR)$(pkgdatadir)/tools/$$f; \
done
# Make sure everything is included in the distribution.
dist-hook:
srcdir_cnt=`echo $(srcdir) | wc -c`; \
for file in $(ALL_TOOLS_FILES); do \
@@ -529,9 +523,10 @@ dist-hook:
cp -p $$file $(distdir)/$$f; \
done
# To generate the example zip just depend on the sources and ignore the
# class files. Always regenerate all .class files and remove them immediatly.
# And copy the template files we use to the classes dir so they get also included.
# To generate the example zip just depend on the sources and ignore
# the class files. Always regenerate all .class files and remove them
# immediately. And copy the template files we use to the classes dir
# so they get also included.
$(TOOLS_ZIP): $(TOOLS_JAVA_FILES)
mkdir -p classes/gnu/classpath/tools/giop/grmic/templates
mkdir -p classes/gnu/classpath/tools/rmi/rmic/templates
+58
View File
@@ -0,0 +1,58 @@
The GNU Classpath tools are stored in the tools.zip. They can be invoked by
putting this archive into classpath and specifying the tool main class as the
class to run (parameters usually follow). The current release contains the
following tools:
== GIOP tools ==
GIOP tools are used for creating the applications that use GIOP communication
protocol. It provides necessary support for org.omg.* and javax.rmi.*
packages.
All GIOP tools support the --help option, for instance:
java -cp tools.zip gnu.classpath.tools.giop.IorParser --help
The list of the currently available GIOP tools (name matches the main
class in gnu.classpath.tools.giop package):
* GRMIC - RMI-IIOP stub and tie generator.
* NameService - GIOP transient naming service (this tool is called
tnameserv in Sun's package).
* NameServicePersistent
- GIOP persistent naming service (this tool is called
orbd in Sun's package).
* IorParser - Parses the stringified form of the interoperable
object references (IOR's).
== RMI tools ==
RMI tools provide support for java.rmi package. All tools support
the --help key by printing more information, for instance:
java -cp tools.zip gnu.classpath.tools.rmi.RMIC --help
The list of the currently available RMI tools (name matches the main tool class
in gnu.classpath.tools.rmi package):
* RMIC - RMI stub and tie source code generator (complements
the ASM based bytecode generator in the separate
cp-tools project). This tool is only needed for
research and backward-compatibile applications, as
Classpath supports the 1.5 feature to replace such
stubs by proxy classes.
* REGISTRY - The persistent RMI naming service.
* RMID - The persistent RMI activation daemon, supports the
java.rmi.activation package.
== Security tools ==
Security tools (currently) are used for signing and verifying JAR files
as well as (planned) generating and managing cryptographic tokens and
credentials.
The list of individual tools, the name of their main class that should be
invoked by the Java launcher, and a summary of what they provide follows:
* jarsigner gnu.classpath.tools.jarsigner.Main
A drop-in replacement for the "jarsigner" tool.
@@ -69,6 +69,39 @@ public class HelpPrinter
}
}
/**
* Prints the contents of the resource specified by the designated path.
*
* @param helpResourcePath the path to a help resource, related to the
* HelpPrinter class.
*/
public static void printHelp(String helpResourcePath)
{
InputStream in = HelpPrinter.class.getResourceAsStream(helpResourcePath);
BufferedReader br = new BufferedReader(new InputStreamReader(in));
try
{
String s;
while ((s = br.readLine()) != null)
System.out.println(s);
}
catch (IOException x)
{
System.err.print("Resource loading is broken:");
x.printStackTrace(System.err);
}
finally
{
try
{
br.close();
}
catch (IOException ignored)
{
}
}
}
/**
* Prints the help message and terminates.
*
@@ -77,23 +110,7 @@ public class HelpPrinter
*/
public static void printHelpAndExit(String helpResourcePath)
{
InputStream in = HelpPrinter.class.getResourceAsStream(helpResourcePath);
BufferedReader r = new BufferedReader(new InputStreamReader(in));
try
{
String s;
while ((s = r.readLine()) != null)
{
System.out.println(s);
}
r.close();
}
catch (IOException e)
{
System.err.print("Resource loading is broken:");
e.printStackTrace();
}
printHelp(helpResourcePath);
System.exit(0);
}
}
@@ -0,0 +1,145 @@
/* CallbackUtil.java -- Callback related utilities
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.common;
import gnu.javax.security.auth.callback.ConsoleCallbackHandler;
import java.security.Provider;
import java.security.Security;
import java.util.logging.Logger;
import javax.security.auth.callback.CallbackHandler;
/**
* A <i>Helper</i> class containing general purpose utlity methods dealing with
* callback handlers and their <i>Security Provider</i>.
*/
public abstract class CallbackUtil
{
private static final Logger log = Logger.getLogger(CallbackUtil.class.getName());
// default 0-arguments constructor
// Class methods
// --------------------------------------------------------------------------
/**
* Return an implementation of the {@link CallbackHandler}, from any
* {@link Provider}, capable of handling callbacks through the <i>console</i>;
* i.e. <code>System.in</code> and <code>System.out</code>.
* <p>
* If no <i>Security Provider</i> for this type of callback was found, this
* method returns the default GNU implementation.
*
* @return a console {@link CallbackHandler} implementation.
*/
public static final CallbackHandler getConsoleHandler()
{
CallbackHandler result = getHandler("Console");
if (result == null)
{
log.fine("No console callback handler found. Will use ours");
result = new ConsoleCallbackHandler();
}
return result;
}
/**
* Return a {@link CallbackHandler}, of a designated type, for interacting
* with the user.
* <p>
* This method first finds all currently installed <i>Security Providers</i>
* 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 returned.
*
* @return a {@link CallbackHandler} of the designated type, or
* <code>null</code> if no provider was found for theis type of
* callback.
*/
private static final CallbackHandler getHandler(String handlerType)
{
log.entering(CallbackUtil.class.getName(), "getHandler", handlerType);
CallbackHandler result = null;
String service = "CallbackHandler." + handlerType;
Provider[] providers = Security.getProviders(service);
if (providers != null)
for (int i = 0; i < providers.length; i++)
{
Provider p = providers[i];
String className = p.getProperty(service);
if (className != null)
try
{
result = (CallbackHandler) Class.forName(className.trim()).newInstance();
}
catch (InstantiationException x)
{
log.fine("InstantiationException while creating ["
+ className + "] from provider [" + p.getName()
+ "]. Ignore");
}
catch (IllegalAccessException x)
{
log.fine("IllegalAccessException while creating ["
+ className + "] from provider [" + p.getName()
+ "]. Ignore");
}
catch (ClassNotFoundException x)
{
log.fine("ClassNotFoundException while creating ["
+ className + "] from provider [" + p.getName()
+ "]. Ignore");
}
if (result != null)
{
log.fine("Will use [" + result.getClass().getName()
+ "] from [" + p.getName() + "]");
break;
}
}
log.exiting(CallbackUtil.class.getName(), "getHandler", result);
return result;
}
}
@@ -0,0 +1,163 @@
/* ProviderUtil.java -- Security Provider related utilities
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.common;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.Provider;
import java.security.Security;
import java.util.logging.Logger;
/**
* A <i>Helper</i> class containing general purpose utlity methods dealing with
* installing and removing <i>Security Providers</i> at runtime.
*/
public abstract class ProviderUtil
{
private static final Logger log = Logger.getLogger(ProviderUtil.class.getName());
// default 0-arguments constructor
// Class methods
// --------------------------------------------------------------------------
/**
* Attempt to (a) instantiate, and (b) add a designated {@link Provider} by
* inserting at at the top of the list of <i>Security Providers</i> already
* present at runtime, only if it is not already installed.
* <p>
* <b>IMPORTANT</b>: This method overrides the security check usually carried
* out by the security manager when inserting a new {@link Provider}.
*
* @param providerClass a fully qualified, non-null, class name of a
* <i>Security Provider</i> to add if it is not already installed.
* @return an instance of {@link SecurityProviderInfo} referencing the
* {@link Provider} instance created with the designated class name,
* and its position in the underlying JVM runtime.
*/
public static final SecurityProviderInfo addProvider(String providerClass)
{
log.entering(ProviderUtil.class.getName(), "addProvider", providerClass);
Provider provider = null;
try
{
provider = (Provider) Class.forName(providerClass.trim()).newInstance();
}
catch (InstantiationException x)
{
log.fine("InstantiationException while creating [" + providerClass
+ "]. Ignore");
}
catch (IllegalAccessException x)
{
log.fine("IllegalAccessException while creating [" + providerClass
+ "]. Ignore");
}
catch (ClassNotFoundException x)
{
log.fine("ClassNotFoundException while creating [" + providerClass
+ "]. Ignore");
}
int position = provider != null ? addProvider(provider) : -1;
SecurityProviderInfo result = new SecurityProviderInfo(provider, position);
log.exiting(ProviderUtil.class.getName(), "addProvider", result);
return result;
}
/**
* Attempt to add the designated {@link Provider} by inserting at at the top
* of the list of <i>Security Providers</i> already present at runtime, only
* if it is not already installed.
* <p>
* <b>IMPORTANT</b>: This method overrides the security check usually carried
* out by the security manager when inserting a new {@link Provider}.
*
* @param provider a non-null <i>Security Provider</i> to add if it is not
* already installed.
* @return the new position of the designated provider in the list if it was
* not already present, or <code>-1</code> if it was already
* installed.
*/
public static final int addProvider(final Provider provider)
{
log.entering(ProviderUtil.class.getName(), "addProvider", provider);
Integer actualPosition = (Integer) AccessController.doPrivileged(new PrivilegedAction()
{
public Object run()
{
int result = Security.insertProviderAt(provider, 1);
return Integer.valueOf(result);
}
});
int result = actualPosition.intValue();
log.fine("Provider [" + provider.getName() + "] installed? " + (result != - 1));
log.exiting(ProviderUtil.class.getName(), "addProvider", actualPosition);
return result;
}
/**
* Remove a designated <i>Security Provider</i>.
* <p>
* <b>IMPORTANT</b>: This method overrides the security check usually carried
* out by the security manager when removing a {@link Provider}.
*
* @param providerName the name of the {@link Provider} to remove.
*/
public static final void removeProvider(final String providerName)
{
log.entering(ProviderUtil.class.getName(), "removeProvider", providerName);
AccessController.doPrivileged(new PrivilegedAction()
{
public Object run()
{
Security.removeProvider(providerName);
return null;
}
});
log.exiting(ProviderUtil.class.getName(), "removeProvider");
}
}
@@ -0,0 +1,99 @@
/* SecurityProviderInfo.java -- Data Access Object for a security provider
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.common;
import java.security.Provider;
/**
* A Data Access Object (DAO) referenceing a <i>Security Provider</i> and its
* position in the list of installed <i>Security Providers</i> in the underlying
* JVM runtime.
*/
public class SecurityProviderInfo
{
final private Provider provider;
final private int position;
private transient String str;
/**
* Constructs an instance of <code>SecurityProviderInfo</code>.
* <p>
* Used by {@link ProviderUtil} to indicate the result of adding a provider,
* given its class name.
*
* @param provider the possibly <code>null</code> {@link Provider}.
* @param position the position of <code>provider</code> in the list of
* <i>Security Providers</i> in the underlying JVM runtime. <code>-1</code>
* if that provider (a) is <code>null</code>, or (b) was not added because it
* was already there.
*/
SecurityProviderInfo(Provider provider, int position)
{
super();
this.provider = provider;
this.position = position;
}
/** @return the possibly <code>null</code> {@link Provider} instance. */
public Provider getProvider()
{
return this.provider;
}
/**
* @return the position of the {@link Provider}, or <code>-1</code> if it
* was not added.
*/
public int getPosition()
{
return this.position;
}
public String toString()
{
if (str == null)
if (provider == null)
str = "SecurityProviderInfo{null, -1}";
else
str = "SecurityProviderInfo{" + provider.getName() + ", " + position + "}";
return str;
}
}
@@ -17,23 +17,7 @@ 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.giop;
@@ -105,6 +89,10 @@ public class GRMIC
verbose = true;
compiler.setVerbose(true);
}
else if (c.equals("-force"))
{
compiler.setForce(true);
}
else if (c.equals("-d"))
{
int f = i + 1;
@@ -19,6 +19,9 @@ Usage: grmic <options> <class names>
-help Print this help text
-v Print version
-verbose Verbose output
-force Try to generate code even if the input classes seem not
consistent with RMI specification.
and <class names> can include one or more non abstract classes that implement
Remote and are accessible via current class path.
@@ -17,23 +17,7 @@ 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.giop;
@@ -9,7 +9,8 @@ The list of the currently available tools:
* GRMIC - RMI-IIOP stub and tie generator.
* NameService - GIOP transient naming service (this tool is called
tnameserv in Sun's package).
* NameService - GIOP persistent naming service (this tool is called
* NameServicePersistent
- GIOP persistent naming service (this tool is called
orbd in Sun's package).
* IorParser - Parses the stringified form of the interoperable
object references (IOR's).
@@ -17,23 +17,7 @@ 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.giop.grmic;
@@ -17,23 +17,7 @@ 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.giop.grmic;
@@ -17,23 +17,7 @@ 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.giop.grmic;
@@ -17,23 +17,7 @@ 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.giop.grmic;
@@ -115,6 +99,11 @@ public class GiopRmicCompiler
* Verbose output
*/
protected boolean verbose = false;
/**
* Force mode - do not check the exceptions
*/
protected boolean force = false;
/**
* Clear data, preparing for the next compilation.
@@ -204,7 +193,7 @@ public class GiopRmicCompiler
remEx = true;
break;
}
if (! remEx)
if (! remEx && !force)
throw new CompilationError(m[i].getName() + ", defined in "
+ c.getName()
+ ", does not throw "
@@ -483,6 +472,14 @@ public class GiopRmicCompiler
{
warnings = warn;
}
/**
* Set the error ignore mode.
*/
public void setForce(boolean isforce)
{
force = isforce;
}
/**
* Get the package name.
@@ -1,3 +1,25 @@
/* HashFinder.java -- finds the hash character.
Copyright (C) 2006 Free Software Foundation
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.
*/
package gnu.classpath.tools.giop.grmic;
import java.util.HashSet;
@@ -17,23 +17,7 @@ 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.giop.grmic;
@@ -0,0 +1,122 @@
/* Utils.java -- Utility methods for JAR file signing/verification
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.java.security.hash.Sha160;
import gnu.java.security.util.Base64;
import gnu.java.util.jar.JarUtils;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.logging.Logger;
/**
* Collection of utility methods used in JAR file signing and verification.
*/
class HashUtils
{
private static final Logger log = Logger.getLogger(HashUtils.class.getName());
private Sha160 sha = new Sha160();
// default 0-arguments constructor
/**
* @param stream the input stream to digest.
* @return a base-64 representation of the resulting SHA-1 digest of the
* contents of the designated input stream.
* @throws IOException if an I/O related exception occurs during the process.
*/
String hashStream(InputStream stream) throws IOException
{
BufferedInputStream bis = new BufferedInputStream(stream, 4096);
byte[] buffer = new byte[4096];
int count = 0;
int n;
while ((n = bis.read(buffer)) != - 1)
if (n > 0)
{
sha.update(buffer, 0, n);
count += n;
}
byte[] hash = sha.digest();
log.finest("Hashed " + count + " byte(s)");
String result = Base64.encode(hash);
return result;
}
/**
* @param ba the byte array to digest.
* @return a base-64 representation of the resulting SHA-1 digest of the
* contents of the designated buffer.
*/
String hashByteArray(byte[] ba) throws IOException
{
sha.update(ba);
byte[] hash = sha.digest();
log.finest("Hashed " + ba.length + " byte(s)");
String result = Base64.encode(hash);
return result;
}
/**
* @param name the JAR entry name
* @param entryHash the hash of the entry file which appears in the
* manifest.
* @return the base-64 encoded form of the hash of the corresponding Manifest
* JAR entry which will appear in the SF file under the entry with the
* same name.
* @throws UnsupportedEncodingException If UTF-8 character encoding is not
* supported on this platform.
*/
String hashManifestEntry(String name, String entryHash)
throws UnsupportedEncodingException
{
sha.update((JarUtils.NAME + ": " + name).getBytes("UTF-8"));
sha.update(JarUtils.CRLF);
sha.update((Main.DIGEST + ": " + entryHash).getBytes("UTF-8"));
sha.update(JarUtils.CRLF);
sha.update(JarUtils.CRLF);
byte[] sfHash = sha.digest();
String result = Base64.encode(sfHash);
return result;
}
}
@@ -0,0 +1,167 @@
/* JarSigner.java -- The signing handler of the gjarsigner tool
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.SystemProperties;
import gnu.java.util.jar.JarUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.logging.Logger;
/**
* The JAR signing handler of the <code>gjarsigner</code> tool.
*/
public class JarSigner
{
private static final Logger log = Logger.getLogger(JarSigner.class.getName());
/** The owner tool of this handler. */
private Main main;
JarSigner(Main main)
{
super();
this.main = main;
}
void start() throws Exception
{
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
JarFile jarFile = new JarFile(main.getJarFileName());
SFHelper sfHelper = new SFHelper(jarFile);
sfHelper.startSigning();
// 1. compute the digests
for (Enumeration e = jarFile.entries(); e.hasMoreElements(); )
{
JarEntry je = (JarEntry) e.nextElement();
String jeName = je.getName();
if (jeName.equals(JarFile.MANIFEST_NAME)
|| jeName.endsWith(File.separator))
continue;
sfHelper.updateEntry(je);
if (main.isVerbose())
System.out.println(Messages.getString("JarSigner.1") + jeName); //$NON-NLS-1$
}
sfHelper.finishSigning(main.isSectionsOnly());
if (main.isVerbose())
System.out.println(Messages.getString("JarSigner.2") + JarFile.MANIFEST_NAME); //$NON-NLS-1$
// 2. write jar entries and manifest
File signedJarFile = File.createTempFile("gcp-", ".jar"); //$NON-NLS-1$ //$NON-NLS-2$
FileOutputStream fos = new FileOutputStream(signedJarFile);
JarOutputStream outSignedJarFile = new JarOutputStream(fos,
sfHelper.getManifest());
for (Enumeration e = jarFile.entries(); e.hasMoreElements(); )
{
JarEntry je = (JarEntry) e.nextElement();
String jeName = je.getName();
if (jeName.equals(JarFile.MANIFEST_NAME)
|| jeName.endsWith(File.separator))
continue;
log.finest("Processing " + jeName); //$NON-NLS-1$
JarEntry newEntry = new JarEntry(jeName);
newEntry.setTime(je.getTime());
outSignedJarFile.putNextEntry(newEntry);
InputStream jeis = jarFile.getInputStream(je);
copyFromTo(jeis, outSignedJarFile);
}
// 3. create the .SF file
String signaturesFileName = main.getSigFileName();
String sfFileName = JarUtils.META_INF + signaturesFileName
+ JarUtils.SF_SUFFIX;
log.finest("Processing " + sfFileName); //$NON-NLS-1$
JarEntry sfEntry = new JarEntry(sfFileName);
sfEntry.setTime(System.currentTimeMillis());
outSignedJarFile.putNextEntry(sfEntry);
sfHelper.writeSF(outSignedJarFile);
log.finer("Created .SF file"); //$NON-NLS-1$
if (main.isVerbose())
System.out.println(Messages.getString("JarSigner.8") + sfFileName); //$NON-NLS-1$
// 4. create the .DSA file
String dsaFileName = JarUtils.META_INF + signaturesFileName
+ JarUtils.DSA_SUFFIX;
log.finest("Processing " + dsaFileName); //$NON-NLS-1$
JarEntry dsaEntry = new JarEntry(dsaFileName);
dsaEntry.setTime(System.currentTimeMillis());
outSignedJarFile.putNextEntry(dsaEntry);
sfHelper.writeDSA(outSignedJarFile,
main.getSignerPrivateKey(),
main.getSignerCertificateChain(),
main.isInternalSF());
log.finer("Created .DSA file"); //$NON-NLS-1$
if (main.isVerbose())
System.out.println(Messages.getString("JarSigner.11") + dsaFileName); //$NON-NLS-1$
// cleanup
outSignedJarFile.close();
fos.close();
signedJarFile.renameTo(new File(main.getSignedJarFileName()));
log.finer("Renamed signed JAR file"); //$NON-NLS-1$
if (main.isVerbose())
System.out.println(SystemProperties.getProperty("line.separator") //$NON-NLS-1$
+ Messages.getString("JarSigner.14")); //$NON-NLS-1$
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
}
private void copyFromTo(InputStream in, JarOutputStream out)
throws IOException
{
byte[] buffer = new byte[8192];
int n;
while ((n = in.read(buffer)) != -1)
if (n > 0)
out.write(buffer, 0, n);
}
}
@@ -0,0 +1,339 @@
/* JarVerifier.java -- The verification handler of the gjarsigner tool
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.java.security.OID;
import gnu.java.security.Registry;
import gnu.java.security.pkcs.PKCS7SignedData;
import gnu.java.security.pkcs.SignerInfo;
import gnu.java.security.sig.ISignature;
import gnu.java.security.sig.ISignatureCodec;
import gnu.java.security.sig.dss.DSSSignature;
import gnu.java.security.sig.dss.DSSSignatureX509Codec;
import gnu.java.security.sig.rsa.RSAPKCS1V1_5Signature;
import gnu.java.security.sig.rsa.RSAPKCS1V1_5SignatureX509Codec;
import gnu.java.security.util.Util;
import gnu.java.util.jar.JarUtils;
import java.io.IOException;
import java.io.InputStream;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CRLException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Logger;
import java.util.zip.ZipException;
/**
* The JAR verification handler of the <code>gjarsigner</code> tool.
*/
public class JarVerifier
{
private static final Logger log = Logger.getLogger(JarVerifier.class.getName());
/** The owner tool of this handler. */
private Main main;
private HashUtils util = new HashUtils();
/** The JAR file to verify. */
private JarFile jarFile;
/** Map of jar entry names to their hash. */
private Map entryHashes = new HashMap();
JarVerifier(Main main)
{
super();
this.main = main;
}
void start() throws Exception
{
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
String jarFileName = main.getJarFileName();
jarFile = new JarFile(jarFileName);
// 1. find all signature (.SF) files
List sfFiles = new ArrayList();
for (Enumeration e = jarFile.entries(); e.hasMoreElements(); )
{
JarEntry je = (JarEntry) e.nextElement();
String jeName = je.getName();
if (! (jeName.startsWith(JarUtils.META_INF)
&& jeName.endsWith(JarUtils.SF_SUFFIX)))
continue;
// only interested in .SF files in, and not deeper than, META-INF
String[] jeNameParts = jeName.split("/"); //$NON-NLS-1$
if (jeNameParts.length != 2)
continue;
String sfName = jeNameParts[1];
String sigFileName = sfName.substring(0, sfName.length() - 3);
sfFiles.add(sigFileName);
}
// 2. verify each one
if (sfFiles.isEmpty())
System.out.println(Messages.getString("JarVerifier.2")); //$NON-NLS-1$
else
{
int limit = sfFiles.size();
int count = 0;
for (Iterator it = sfFiles.iterator(); it.hasNext(); )
{
String alias = (String) it.next();
if (verifySF(alias))
if (verifySFEntries(alias))
count++;
}
if (count == 0)
System.out.println(Messages.getString("JarVerifier.3")); //$NON-NLS-1$
else if (count != limit)
System.out.println(Messages.getFormattedString("JarVerifier.4", //$NON-NLS-1$
new Integer[] {Integer.valueOf(count),
Integer.valueOf(limit)}));
else
System.out.println(Messages.getFormattedString("JarVerifier.7", //$NON-NLS-1$
Integer.valueOf(limit)));
}
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
}
/**
* @param sigFileName the name of the signature file; i.e. the name to use for
* both the .SF and .DSA files.
* @return <code>true</code> if the designated file-name (usually a key-store
* <i>alias</i> name) has been successfully checked as the signer of the
* corresponding <code>.SF</code> file. Returns <code>false</code> otherwise.
* @throws IOException
* @throws ZipException
* @throws CertificateException
* @throws CRLException
*/
private boolean verifySF(String sigFileName) throws CRLException,
CertificateException, ZipException, IOException
{
log.entering(this.getClass().getName(), "verifySF"); //$NON-NLS-1$
log.finest("About to verify signature of " + sigFileName + "..."); //$NON-NLS-1$ //$NON-NLS-2$
// 1. find the corresponding .DSA file for this .SF file
JarEntry dsaEntry = jarFile.getJarEntry(JarUtils.META_INF + sigFileName
+ JarUtils.DSA_SUFFIX);
if (dsaEntry == null)
throw new SecurityException(Messages.getFormattedString("JarVerifier.13", //$NON-NLS-1$
sigFileName));
// 2. read the .DSA file contents as a PKCS7 SignedData
InputStream in = jarFile.getInputStream(dsaEntry);
PKCS7SignedData pkcs7SignedData = new PKCS7SignedData(in);
// 4. get the encrypted digest octet string from the first SignerInfo
// this octet string is the digital signature of the .SF file contents
Set signerInfos = pkcs7SignedData.getSignerInfos();
if (signerInfos == null || signerInfos.isEmpty())
throw new SecurityException(Messages.getString("JarVerifier.14")); //$NON-NLS-1$
SignerInfo signerInfo = (SignerInfo) signerInfos.iterator().next();
byte[] encryptedDigest = signerInfo.getEncryptedDigest();
if (encryptedDigest == null)
throw new SecurityException(Messages.getString("JarVerifier.16")); //$NON-NLS-1$
log.finest("\n" + Util.dumpString(encryptedDigest, "--- signedSFBytes ")); //$NON-NLS-1$ //$NON-NLS-2$
// 5. get the signer public key
Certificate cert = pkcs7SignedData.getCertificates()[0];
PublicKey verifierKey = cert.getPublicKey();
log.finest("--- verifier public key = " + verifierKey); //$NON-NLS-1$
// 6. verify the signature file signature
OID digestEncryptionAlgorithmOID = signerInfo.getDigestEncryptionAlgorithmId();
ISignature signatureAlgorithm;
ISignatureCodec signatureCodec;
if (digestEncryptionAlgorithmOID.equals(Main.DSA_SIGNATURE_OID))
{
signatureAlgorithm = new DSSSignature();
signatureCodec = new DSSSignatureX509Codec();
}
else
{
signatureAlgorithm = new RSAPKCS1V1_5Signature(Registry.MD5_HASH);
signatureCodec = new RSAPKCS1V1_5SignatureX509Codec();
}
Map signatureAttributes = new HashMap();
signatureAttributes.put(ISignature.VERIFIER_KEY, verifierKey);
signatureAlgorithm.setupVerify(signatureAttributes);
Object herSignature = signatureCodec.decodeSignature(encryptedDigest);
// 7. verify the signature file contents
JarEntry sfEntry = jarFile.getJarEntry(JarUtils.META_INF + sigFileName
+ JarUtils.SF_SUFFIX);
in = jarFile.getInputStream(sfEntry);
byte[] buffer = new byte[2048];
int n;
while ((n = in.read(buffer)) != -1)
if (n > 0)
signatureAlgorithm.update(buffer, 0, n);
boolean result = signatureAlgorithm.verify(herSignature);
log.finer("Signature block [" + sigFileName + "] is " //$NON-NLS-1$ //$NON-NLS-2$
+ (result ? "" : "NOT ") + "OK"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
log.exiting(this.getClass().getName(), "verifySF", Boolean.valueOf(result)); //$NON-NLS-1$
return result;
}
/**
* This method is called after at least one signer (usually a key-store
* <code>alias</code> name) was found to be trusted; i.e. his/her signature
* block in the corresponding <code>.DSA</code> file was successfully
* verified using his/her public key.
* <p>
* This method, uses the contents of the corresponding <code>.SF</code> file
* to compute and verify the hashes of the manifest entries in the JAR file.
*
* @param alias the name of the signature file; i.e. the name to use for both
* the .SF and .DSA files.
* @return <code>true</code> if all the entries in the corresponding
* <code>.SF</code> file have the same hash values as their
* alter-ego in the <i>manifest</i> file of the JAR file inquestion.
* @throws IOException if an I/O related exception occurs during the process.
*/
private boolean verifySFEntries(String alias) throws IOException
{
log.entering(this.getClass().getName(), "verifySFEntries"); //$NON-NLS-1$
// 1. read the signature file
JarEntry jarEntry = jarFile.getJarEntry(JarUtils.META_INF + alias
+ JarUtils.SF_SUFFIX);
InputStream in = jarFile.getInputStream(jarEntry);
Attributes attr = new Attributes();
Map entries = new HashMap();
JarUtils.readSFManifest(attr, entries, in);
// 2. The .SF file by default includes a header containing a hash of the
// entire manifest file. When the header is present, then the verification
// can check to see whether or not the hash in the header indeed matches
// the hash of the manifest file.
boolean result = false;
String hash = attr.getValue(Main.DIGEST_MANIFEST_ATTR);
if (hash != null)
result = verifyManifest(hash);
// A verification is still considered successful if none of the files that
// were in the JAR file when the signature was generated have been changed
// since then, which is the case if the hashes in the non-header sections
// of the .SF file equal the hashes of the corresponding sections in the
// manifest file.
//
// 3. Read each file in the JAR file that has an entry in the .SF file.
// While reading, compute the file's digest, and then compare the result
// with the digest for this file in the manifest section. The digests
// should be the same, or verification fails.
if (! result)
for (Iterator it = entries.keySet().iterator(); it.hasNext();)
{
Entry me = (Entry) it.next();
String name = (String) me.getKey();
attr = (Attributes) me.getValue();
hash = attr.getValue(Main.DIGEST_ATTR);
result = verifySFEntry(name, hash);
if (! result)
break;
}
log.exiting(this.getClass().getName(), "verifySFEntries",
Boolean.valueOf(result)); //$NON-NLS-1$
return result;
}
/**
* @param hash Base-64 encoded form of the manifest's digest.
* @return <code>true</code> if our computation of the manifest's hash
* matches the given value; <code>false</code> otherwise.
* @throws IOException if unable to acquire the JAR's manifest entry.
*/
private boolean verifyManifest(String hash) throws IOException
{
return verifySFEntry(JarFile.MANIFEST_NAME, hash);
}
/**
* @param name the name of a JAR entry to verify.
* @param hash Base-64 encoded form of the designated entry's digest.
* @return <code>true</code> if our computation of the JAR entry's hash
* matches the given value; <code>false</code> otherwise.
* @throws IOException if an exception occurs while returning the entry's
* input stream.
*/
private boolean verifySFEntry(String name, String hash) throws IOException
{
String expectedValue = getEntryHash(JarFile.MANIFEST_NAME);
boolean result = expectedValue.equalsIgnoreCase(hash);
log.finest("Is " + name + " OK? " + result); //$NON-NLS-1$ //$NON-NLS-2$
return result;
}
private String getEntryHash(String entryName) throws IOException
{
String result = (String) entryHashes.get(entryName);
if (result == null)
{
JarEntry manifest = jarFile.getJarEntry(entryName);
InputStream in = jarFile.getInputStream(manifest);
result = util.hashStream(in);
entryHashes.put(entryName, result);
}
return result;
}
}
@@ -0,0 +1,567 @@
/* 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.SystemProperties;
import gnu.classpath.tools.HelpPrinter;
import gnu.classpath.tools.common.CallbackUtil;
import gnu.classpath.tools.common.ProviderUtil;
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.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
{
private static final Logger log = Logger.getLogger(Main.class.getName());
private static final String HELP_PATH = "jarsigner/jarsigner.txt"; //$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);
private boolean verify;
private String ksURL;
private String ksType;
private String password;
private String ksPassword;
private String sigFileName;
private String signedJarFileName;
private boolean verbose;
private boolean certs;
private boolean internalSF;
private boolean sectionsOnly;
private String providerClassName;
private String jarFileName;
private 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;
private Main()
{
super();
}
public static final void main(String[] args)
{
log.entering(Main.class.getName(), "main", args); //$NON-NLS-1$
Main tool = new Main();
try
{
tool.processArgs(args);
tool.start();
}
catch (SecurityException x)
{
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)
{
log.throwing(Main.class.getName(), "main", x); //$NON-NLS-1$
System.err.println(Messages.getString("Main.9") + x); //$NON-NLS-1$
}
tool.teardown();
log.exiting(Main.class.getName(), "main"); //$NON-NLS-1$
// System.exit(0);
}
// 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 exceptio occurs during the process.
*/
private void processArgs(String[] args) throws Exception
{
log.entering(this.getClass().getName(), "processArgs", args); //$NON-NLS-1$
HelpPrinter.checkHelpKey(args, HELP_PATH);
if (args == null || args.length == 0)
HelpPrinter.printHelpAndExit(HELP_PATH);
int limit = args.length;
log.finest("args.length=" + limit); //$NON-NLS-1$
int i = 0;
String opt;
while (i < limit)
{
opt = args[i++];
log.finest("args[" + (i - 1) + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
if (opt == null || opt.length() == 0)
continue;
if ("-verify".equals(opt)) // -verify //$NON-NLS-1$
verify = true;
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
ksURL = args[i++];
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
ksType = args[i++];
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
ksPassword = args[i++];
else if ("-keypass".equals(opt)) // -keypass PASSWORD //$NON-NLS-1$
password = args[i++];
else if ("-sigfile".equals(opt)) // -sigfile NAME //$NON-NLS-1$
sigFileName = args[i++];
else if ("-signedjar".equals(opt)) // -signedjar FILE_NAME //$NON-NLS-1$
signedJarFileName = args[i++];
else if ("-verbose".equals(opt)) // -verbose //$NON-NLS-1$
verbose = true;
else if ("-certs".equals(opt)) // -certs //$NON-NLS-1$
certs = true;
else if ("-internalsf".equals(opt)) // -internalsf //$NON-NLS-1$
internalSF = true;
else if ("-sectionsonly".equals(opt)) // -sectionsonly //$NON-NLS-1$
sectionsOnly = true;
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
providerClassName = args[i++];
else
{
jarFileName = opt;
if (! verify)
alias = args[i++];
break;
}
}
if (i < limit) // more options than needed
log.fine("Last argument is assumed at index #" + (i - 1) //$NON-NLS-1$
+ ". Remaining arguments (" + args[i] //$NON-NLS-1$
+ "...) will be ignored"); //$NON-NLS-1$
setupCommonParams();
if (verify)
{
log.finer("Will verify with the following parameters:"); //$NON-NLS-1$
log.finer(" jar-file = '" + jarFileName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
log.finer("Options:"); //$NON-NLS-1$
log.finer(" provider = '" + providerClassName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
log.finer(" verbose ? " + verbose); //$NON-NLS-1$
log.finer(" certs ? " + certs); //$NON-NLS-1$
log.finer(" internalsf ? " + internalSF); //$NON-NLS-1$
log.finer(" sectionsonly ? " + sectionsOnly); //$NON-NLS-1$
}
else // sign
{
setupSigningParams();
log.finer("Will sign with the following parameters:"); //$NON-NLS-1$
log.finer(" jar-file = '" + jarFileName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
log.finer(" alias = '" + alias + "'"); //$NON-NLS-1$ //$NON-NLS-2$
log.finer("Options:"); //$NON-NLS-1$
log.finer(" keystore = '" + ksURL + "'"); //$NON-NLS-1$ //$NON-NLS-2$
log.finer(" storetype = '" + ksType + "'"); //$NON-NLS-1$ //$NON-NLS-2$
log.finer(" storepass = '" + ksPassword + "'"); //$NON-NLS-1$ //$NON-NLS-2$
log.finer(" keypass = '" + password + "'"); //$NON-NLS-1$ //$NON-NLS-2$
log.finer(" sigfile = '" + sigFileName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
log.finer(" signedjar = '" + signedJarFileName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
log.finer(" provider = '" + providerClassName + "'"); //$NON-NLS-1$ //$NON-NLS-2$
log.finer(" verbose ? " + verbose); //$NON-NLS-1$
log.finer(" internalsf ? " + internalSF); //$NON-NLS-1$
log.finer(" sectionsonly ? " + sectionsOnly); //$NON-NLS-1$
}
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
{
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();
}
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()
{
log.entering(this.getClass().getName(), "teardown"); //$NON-NLS-1$
if (providerInstalled)
ProviderUtil.removeProvider(provider.getName());
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
{
log.entering(this.getClass().getName(), "setupCommonParams"); //$NON-NLS-1$
if (jarFileName == null)
HelpPrinter.printHelpAndExit(HELP_PATH);
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)
log.finer("Provider " + providerName + " is already installed"); //$NON-NLS-1$ //$NON-NLS-2$
else // install it
installNewProvider();
}
if (! verbose && certs)
{
log.fine("Option <certs> is set but <verbose> is not. Ignored"); //$NON-NLS-1$
certs = false;
}
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()
{
log.entering(this.getClass().getName(), "installNewProvider"); //$NON-NLS-1$
providerInstalled = ProviderUtil.addProvider(provider) != -1;
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
{
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 (alias == null)
HelpPrinter.printHelpAndExit(HELP_PATH);
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);
log.finest(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;
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;
}
}
@@ -0,0 +1,115 @@
/* Messages.java -- I18N related helper class
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 java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.logging.Logger;
/**
* An initially generated Eclipse helper class to ease the use of localized
* messages.
* <p>
* Enriched to handle localized message formats.
*/
class Messages
{
private static final Logger log = Logger.getLogger(Messages.class.getName());
private static final String BUNDLE_NAME = "gnu.classpath.tools.jarsigner.MessageBundle"; //$NON-NLS-1$
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
private static final Map CACHED_FORMATS = new HashMap(5);
private Messages()
{
super();
}
public static String getString(String key)
{
try
{
return RESOURCE_BUNDLE.getString(key);
}
catch (MissingResourceException e)
{
return constructMessage(key, null);
}
}
public static String getFormattedString(String key, Object args)
{
MessageFormat mf = (MessageFormat) CACHED_FORMATS.get(key);
if (mf == null)
{
String formatString = getString(key);
if (formatString.startsWith("!"))
return constructMessage(key, args);
mf = new MessageFormat(formatString);
CACHED_FORMATS.put(key, mf);
}
// if the argument is not an array, then build one consisiting of the
// sole argument before passing it to the format() method
try
{
if (args instanceof Object[])
return mf.format(args);
return mf.format(new Object[] { args });
}
catch (IllegalArgumentException x)
{
log.fine("Exception while rendering a message format keyed by ["
+ key + "]: " + mf.toPattern());
return constructMessage(mf.toPattern(), args);
}
}
private static final String constructMessage(String m, Object args)
{
if (args == null)
return '!' + m + '!';
return '!' + m + '!' + String.valueOf(args) + '!';
}
}
@@ -0,0 +1,373 @@
/* SFHelper -- A .SF file helper
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.java.security.OID;
import gnu.java.security.Registry;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERValue;
import gnu.java.security.pkcs.PKCS7Data;
import gnu.java.security.pkcs.PKCS7SignedData;
import gnu.java.security.pkcs.SignerInfo;
import gnu.java.security.sig.ISignature;
import gnu.java.security.sig.ISignatureCodec;
import gnu.java.security.sig.dss.DSSSignature;
import gnu.java.security.sig.dss.DSSSignatureX509Codec;
import gnu.java.security.sig.rsa.RSAPKCS1V1_5Signature;
import gnu.java.security.sig.rsa.RSAPKCS1V1_5SignatureX509Codec;
import gnu.java.security.util.Util;
import gnu.java.util.jar.JarUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.security.PrivateKey;
import java.security.cert.CRLException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509CRL;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.logging.Logger;
import javax.security.auth.x500.X500Principal;
import java.security.cert.X509Certificate;
/**
* A helper class for the .SF file found in signed jars.
*/
public class SFHelper
{
// Constants and fields
// --------------------------------------------------------------------------
private static final Logger log = Logger.getLogger(SFHelper.class.getName());
private static final int READY = 0;
private static final int STARTED = 1;
private static final int FINISHED = 2;
private static final int SF_GENERATED = 3;
private static final int DSA_GENERATED = 4;
/** http://asn1.elibel.tm.fr/cgi-bin/oid/display?oid=1.3.14.3.2.26&action=display */
private static final OID hashAlgorithmIdentifierSHA1 = new OID("1.3.14.3.2.26"); //$NON-NLS-1$
private int state;
private JarFile jar;
private Manifest manifest;
private Attributes sfMainAttributes;
private Map sfEntries;
private byte[] sfBytes;
private HashUtils util;
// Constructor(s)
// --------------------------------------------------------------------------
/**
* @param jar the JAR archive the .SF file belongs to.
*/
public SFHelper(JarFile jar)
{
super();
this.jar = jar;
this.state = READY;
}
// Class methods
// --------------------------------------------------------------------------
// Instance methods
// --------------------------------------------------------------------------
/**
* Writes the contents of the <code>.SF</code> file to the designated JAR
* output stream. Line-endings are platform-independent and consist of the
* 2-codepoint sequence <code>0x0D</code> and <code>0x0A</code>.
*
* @param jar the JAR output stream to write a <code>.SF</code> file to.
* @throws IOException if an I/O related exception occurs during the process.
*/
void writeSF(JarOutputStream jar) throws IOException
{
if (this.state != FINISHED)
throw new IllegalStateException(Messages.getString("SFHelper.1")); //$NON-NLS-1$
ByteArrayOutputStream baos = new ByteArrayOutputStream();
JarUtils.writeSFManifest(sfMainAttributes, sfEntries, baos);
sfBytes = baos.toByteArray();
log.finest("\n" + Util.dumpString(sfBytes, "+++ sfBytes ")); //$NON-NLS-1$ //$NON-NLS-2$
jar.write(sfBytes);
jar.flush();
this.state = SF_GENERATED;
}
/**
* The contents of the .DSA file is the DER encoded form of a PKCS#7
* ContentInfo of the type SignedData.
* <p>
* The ContentInfo ASN.1 syntax is as described in the "PKCS#7 Cryptographic
* Message Syntax Standard" (RSA Labs) specifications:
* <pre>
* ContentInfo ::= SEQUENCE {
* contentType ContentType,
* content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
* }
*
* ContentType ::= OBJECT IDENTIFIER
* </pre>
* <p>
* The ContentType is an OID which determines the type of the contents field
* that follows it. For the .DSA file the OID is "1.2.840.113549.1.7.2", while
* the content field is the byte array representing the DER encoded form of a
* SignedData content-type. The ASN.1 syntax of the SignedData type is as
* follows:
* <pre>
* SignedData ::= SEQUENCE {
* version Version, -- always 1 for PKCS#7 1.5
* digestAlgorithms DigestAlgorithmIdentifiers,
* contentInfo ContentInfo,
* certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
* crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
* signerInfos SignerInfos
* }
*
* DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
*
* SignerInfos ::= SET OF SignerInfo
* </pre>
* <p>
* Finally the SignerInfo is a per-signer structure. Its ASN.1 syntax looks
* like so:
* <pre>
* SignerInfo ::= SEQUENCE {
* version Version, -- always 1 for PKCS#7 1.5
* issuerAndSerialNumber IssuerAndSerialNumber,
* digestAlgorithm DigestAlgorithmIdentifier,
* authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
* digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
* encryptedDigest EncryptedDigest,
* unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
* }
*
* EncryptedDigest ::= OCTET STRING
* </pre>
*
* @param jar the JAR output stream to write a <code>.DSA</code> file to.
* @param signerKey the private key to sign with.
* @param certificates the possibly null signer certificate chain.
* @param internalSF if <code>true</code> then include the .SF file contents
* in the signed .DSA file; otherwise don't.
* @throws IOException if an I/O related exception occurs during the process.
* @throws CRLException
* @throws CertificateEncodingException
*/
void writeDSA(JarOutputStream jar, PrivateKey signerKey,
Certificate[] certificates, boolean internalSF)
throws IOException, CertificateEncodingException, CRLException
{
if (this.state != SF_GENERATED)
throw new IllegalStateException(Messages.getString("SFHelper.4")); //$NON-NLS-1$
log.finest("+++ signer private key = " + signerKey); //$NON-NLS-1$
ISignature signatureAlgorithm;
ISignatureCodec signatureCodec;
OID digestEncryptionAlgorithmOID;
if (signerKey instanceof DSAPrivateKey)
{
signatureAlgorithm = new DSSSignature();
signatureCodec = new DSSSignatureX509Codec();
digestEncryptionAlgorithmOID = Main.DSA_SIGNATURE_OID;
}
else if (signerKey instanceof RSAPrivateKey)
{
signatureAlgorithm = new RSAPKCS1V1_5Signature(Registry.MD5_HASH);
signatureCodec = new RSAPKCS1V1_5SignatureX509Codec();
digestEncryptionAlgorithmOID = Main.RSA_SIGNATURE_OID;
}
else
throw new SecurityException(Messages.getString("SFHelper.6")); //$NON-NLS-1$
Map signatureAttributes = new HashMap();
signatureAttributes.put(ISignature.SIGNER_KEY, signerKey);
signatureAlgorithm.setupSign(signatureAttributes);
signatureAlgorithm.update(sfBytes, 0, sfBytes.length);
Object signature = signatureAlgorithm.sign();
byte[] signedSFBytes = signatureCodec.encodeSignature(signature);
log.finest("\n" + Util.dumpString(signedSFBytes, "+++ signedSFBytes ")); //$NON-NLS-1$ //$NON-NLS-2$
Set digestAlgorithms = new HashSet();
List digestAlgorithm = new ArrayList(2);
DERValue derDigestAlgorithmOID = new DERValue(DER.OBJECT_IDENTIFIER,
hashAlgorithmIdentifierSHA1);
DERValue derDigestAlgorithmParams = new DERValue(DER.NULL, null);
digestAlgorithm.add(derDigestAlgorithmOID);
digestAlgorithm.add(derDigestAlgorithmParams);
DERValue derDigestAlgorithm = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
digestAlgorithm);
digestAlgorithms.add(derDigestAlgorithm);
// TODO (rsn): test with internalsf == true
PKCS7Data data = internalSF ? new PKCS7Data(sfBytes) : null;
X509CRL[] crls = null;
Set signerInfos = new HashSet();
X509Certificate cert = (X509Certificate) certificates[0];
X500Principal issuer = cert.getIssuerX500Principal();
BigInteger serialNumber = cert.getSerialNumber();
byte[] authenticatedAttributes = null;
byte[] encryptedDigest = signedSFBytes;
byte[] unauthenticatedAttributes = null;
SignerInfo signerInfo = new SignerInfo(issuer,
serialNumber,
hashAlgorithmIdentifierSHA1,
authenticatedAttributes,
digestEncryptionAlgorithmOID,
encryptedDigest,
unauthenticatedAttributes);
signerInfos.add(signerInfo);
PKCS7SignedData dsaContents = new PKCS7SignedData(digestAlgorithms,
data,
certificates,
crls,
signerInfos);
dsaContents.encode(jar);
jar.flush();
this.state = DSA_GENERATED;
}
Manifest getManifest()
{
return this.manifest;
}
// own methods --------------------------------------------------------------
void startSigning() throws IOException
{
if (this.state != READY)
throw new IllegalStateException(Messages.getString("SFHelper.9")); //$NON-NLS-1$
Manifest oldManifest = jar.getManifest();
this.manifest = oldManifest == null ? new Manifest()
: new Manifest(oldManifest);
this.sfMainAttributes = new Attributes();
this.sfEntries = new HashMap();
util = new HashUtils();
this.state = STARTED;
}
/**
* Hashes the designated JAR entry (the file itself); adds the resulting hash
* as an attribute to the manifest, and computes the hash of the added (to
* the Manifest) two headers and add the result as an attribute of the
* corresponding entry in the .SF file.
*/
void updateEntry(JarEntry entry) throws IOException
{
if (this.state != STARTED)
throw new IllegalStateException(Messages.getString("SFHelper.10")); //$NON-NLS-1$
String name = entry.getName();
InputStream jeis = jar.getInputStream(entry);
String hash = util.hashStream(jeis);
log.finer("Hash of " + name + " = " + hash); //$NON-NLS-1$ //$NON-NLS-2$
Attributes mainfestAttributes = manifest.getAttributes(name);
if (mainfestAttributes == null)
{
mainfestAttributes = new Attributes();
manifest.getEntries().put(name, mainfestAttributes);
}
mainfestAttributes.putValue(Main.DIGEST, hash);
// hash the newly added 2-header block and add it as an attribute to .SF
String sfHash = util.hashManifestEntry(name, hash);
Attributes sfAttributes = (Attributes) sfEntries.get(name);
if (sfAttributes == null)
{
sfAttributes = new Attributes();
sfEntries.put(name, sfAttributes);
}
sfAttributes.putValue(Main.DIGEST, sfHash);
log.finest("Name: " + name); //$NON-NLS-1$
log.finest(Main.DIGEST + ": " + sfHash); //$NON-NLS-1$
log.finest(""); //$NON-NLS-1$
}
/**
* @param sectionsOnly whether to compute, in addition to the files, the hash
* of the mainfest itself (<code>false</code>) or not (<code>true</code>).
*/
void finishSigning(boolean sectionsOnly) throws IOException
{
if (state != STARTED)
throw new IllegalStateException(Messages.getString("SFHelper.10")); //$NON-NLS-1$
if (sectionsOnly)
return;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
manifest.write(baos);
baos.flush();
String manifestHash = util.hashByteArray(baos.toByteArray());
log.fine("Hashed Manifest " + manifestHash); //$NON-NLS-1$
sfMainAttributes.putValue(Main.DIGEST_MANIFEST, manifestHash);
this.state = FINISHED;
}
}
@@ -0,0 +1,405 @@
/* CertReqCmd.java -- The certreq command handler of the keytool
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.keytool;
import gnu.java.security.OID;
import gnu.java.security.der.BitString;
import gnu.java.security.der.DER;
import gnu.java.security.der.DERReader;
import gnu.java.security.der.DERValue;
import gnu.java.security.der.DERWriter;
import gnu.java.security.util.Base64;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.logging.Logger;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.x500.X500Principal;
/**
* The <b>-certreq</b> keytool command handler is used to generate a Certificate
* Signing Request (CSR) in PKCS#10 format.
* <p>
* The ASN.1 specification of a CSR, as stated in RFC-2986 is as follows:
* <p>
* <pre>
* CertificationRequest ::= SEQUENCE {
* certificationRequestInfo CertificationRequestInfo,
* signatureAlgorithm AlgorithmIdentifier,
* signature BIT STRING
* }
*
* CertificationRequestInfo ::= SEQUENCE {
* version INTEGER -- v1(0)
* subject Name,
* subjectPKInfo SubjectPublicKeyInfo,
* attributes [0] IMPLICIT Attributes -- see note later
* }
*
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING
* }
* </pre>
* <b>IMPORTANT</b>: Some documentation (e.g. RSA examples) claims that the
* <code>attributes</code> field is <i>OPTIONAL</i> while <i>RFC-2986</i>
* implies the opposite. This implementation considers this field, by default,
* as <i>OPTIONAL</i>, unless the option <code>-attributes</code> is included
* on the command line.
* <p>
* Possible options for this command are:
* <p>
* <dl>
* <dt>-alias ALIAS</dt>
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
* Certificate</i>, in a key store is uniquely identified by a user-defined
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
* when referring to an entry in the key store. Unless specified otherwise,
* a default value of <code>mykey</code> shall be used when this option is
* omitted from the command line.
* <p></dd>
*
* <dt>-sigalg ALGORITHM</dt>
* <dd>The canonical name of the digital signature algorithm to use for
* signing the certificate. If this option is omitted, a default value will
* be chosen based on the type of the private key associated with the
* designated <i>Alias</i>. If the private key is a <code>DSA</code> one,
* the value for the signature algorithm will be <code>SHA1withDSA</code>.
* If on the other hand the private key is an <code>RSA</code> one, then
* the tool will use <code>MD5withRSA</code> as the signature algorithm.
* <p></dd>
*
* <dt>-file FILE_NAME</dt>
*
* <dt>-keypass PASSWORD</dt>
*
* <dt>-storetype STORE_TYP}</dt>
* <dd>Use this option to specify the type of the key store to use. The
* default value, if this option is omitted, is that of the property
* <code>keystore.type</code> in the security properties file, which is
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
* static method.
* <p></dd>
*
* <dt>-keystore URL</dt>
* <dd>Use this option to specify the location of the key store to use.
* The default value is a file {@link java.net.URL} referencing the file
* named <code>.keystore</code> located in the path returned by the call to
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
* as argument.
* <p>
* If a URL was specified, but was found to be malformed --e.g. missing
* protocol element-- the tool will attempt to use the URL value as a file-
* name (with absolute or relative path-name) of a key store --as if the
* protocol was <code>file:</code>.
* <p></dd>
*
* <dt>-storepass PASSWORD</dt>
* <dd>Use this option to specify the password protecting the key store. If
* this option is omitted from the command line, you will be prompted to
* provide a password.
* <p></dd>
*
* <dt>-provider PROVIDER_CLASS_NAME</dt>
* <dd>A fully qualified class name of a Security Provider to add to the
* current list of Security Providers already installed in the JVM in-use.
* If a provider class is specified with this option, and was successfully
* added to the runtime --i.e. it was not already installed-- then the tool
* will attempt to removed this Security Provider before exiting.
* <p></dd>
*
* <dt>-v</dt>
* <dd>Use this option to enable more verbose output.
* <p></dd>
*
* <dt>-attributes</dt>
* <dd>Use this option to force the tool to encode a NULL DER value in the
* CSR as the value of the Attributes field.</dd>
* </dl>
*/
class CertReqCmd extends Command
{
private static final Logger log = Logger.getLogger(CertReqCmd.class.getName());
private String _alias;
private String _sigAlgorithm;
private String _certReqFileName;
private String _password;
private String _ksType;
private String _ksURL;
private String _ksPassword;
private String _providerClassName;
private boolean nullAttributes;
// default 0-arguments constructor
// public setters -----------------------------------------------------------
/** @param alias the alias to use. */
public void setAlias(String alias)
{
this._alias = alias;
}
/**
* @param algorithm the canonical name of the digital signature algorithm to
* use.
*/
public void setSigalg(String algorithm)
{
this._sigAlgorithm = algorithm;
}
/** @param pathName the fully qualified path name of the file to process. */
public void setFile(String pathName)
{
this._certReqFileName = pathName;
}
/** @param password the (private) key password to use. */
public void setKeypass(String password)
{
this._password = password;
}
/** @param type the key-store type to use. */
public void setStoretype(String type)
{
this._ksType = type;
}
/** @param url the key-store URL to use. */
public void setKeystore(String url)
{
this._ksURL = url;
}
/** @param password the key-store password to use. */
public void setStorepass(String password)
{
this._ksPassword = password;
}
/** @param className a security provider fully qualified class name to use. */
public void setProvider(String className)
{
this._providerClassName = className;
}
/**
* @param flag whether to use, or not, a <code>NULL</code> DER value for
* the certificate's Attributes field.
*/
public void setAttributes(String flag)
{
this.nullAttributes = Boolean.valueOf(flag).booleanValue();
}
// life-cycle methods -------------------------------------------------------
int processArgs(String[] args, int i)
{
int limit = args.length;
String opt;
while (++i < limit)
{
opt = args[i];
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
if (opt == null || opt.length() == 0)
continue;
if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
_alias = args[++i];
else if ("-sigalg".equals(opt)) // -sigalg ALGORITHM //$NON-NLS-1$
_sigAlgorithm = args[++i];
else if ("-file".equals(opt)) // -file FILE_NAME //$NON-NLS-1$
_certReqFileName = args[++i];
else if ("-keypass".equals(opt)) // -keypass PASSWORD //$NON-NLS-1$
_password = args[++i];
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
_ksType = args[++i];
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
_ksURL = args[++i];
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
_ksPassword = args[++i];
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
_providerClassName = args[++i];
else if ("-v".equals(opt)) //$NON-NLS-1$
verbose = true;
else if ("-attributes".equals(opt)) //$NON-NLS-1$
nullAttributes = true;
else
break;
}
return i;
}
void setup() throws Exception
{
setOutputStreamParam(_certReqFileName);
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
setAliasParam(_alias);
setKeyPasswordNoPrompt(_password);
// setSignatureAlgorithm(_sigAlgorithm);
log.finer("-certreq handler will use the following options:"); //$NON-NLS-1$
log.finer(" -alias=" + alias); //$NON-NLS-1$
log.finer(" -sigalg=" + _sigAlgorithm); //$NON-NLS-1$
log.finer(" -file=" + _certReqFileName); //$NON-NLS-1$
log.finer(" -keypass=" + _password); //$NON-NLS-1$
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
log.finer(" -provider=" + provider); //$NON-NLS-1$
log.finer(" -v=" + verbose); //$NON-NLS-1$
log.finer(" -attributes=" + nullAttributes); //$NON-NLS-1$
}
void start() throws KeyStoreException, NoSuchAlgorithmException, IOException,
UnsupportedCallbackException, UnrecoverableKeyException,
InvalidKeyException, SignatureException
{
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
// 1. get the key entry and certificate chain associated to alias
Key privateKey = getAliasPrivateKey();
Certificate[] chain = store.getCertificateChain(alias);
// 2. get alias's DN and public key to use in the CSR
X509Certificate bottomCertificate = (X509Certificate) chain[0];
X500Principal aliasName = bottomCertificate.getIssuerX500Principal();
PublicKey publicKey = bottomCertificate.getPublicKey();
// 3. generate the CSR
setSignatureAlgorithmParam(_sigAlgorithm, privateKey);
byte[] derBytes = getCSR(aliasName, publicKey, (PrivateKey) privateKey);
// 4. encode it in base-64 and write it to outStream
String encoded = Base64.encode(derBytes, 0, derBytes.length, true);
PrintWriter writer = new PrintWriter(outStream, true);
writer.println("-----BEGIN NEW CERTIFICATE REQUEST-----"); //$NON-NLS-1$
writer.println(encoded);
writer.println("-----END NEW CERTIFICATE REQUEST-----"); //$NON-NLS-1$
if (verbose)
{
if (! systemOut)
System.out.println(Messages.getFormattedString("CertReqCmd.27", //$NON-NLS-1$
_certReqFileName));
System.out.println(Messages.getString("CertReqCmd.28")); //$NON-NLS-1$
}
writer.close();
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
}
// own methods --------------------------------------------------------------
/**
* @param aliasName
* @param publicKey
* @param privateKey
* @return the DER encoded Certificate Signing Request.
* @throws IOException
* @throws InvalidKeyException
* @throws SignatureException
*/
private byte[] getCSR(X500Principal aliasName, PublicKey publicKey,
PrivateKey privateKey)
throws IOException, InvalidKeyException, SignatureException
{
DERValue derVersion = new DERValue(DER.INTEGER, BigInteger.ZERO);
DERValue derSubject = new DERReader(aliasName.getEncoded()).read();
DERValue derSubjectPKInfo = new DERReader(publicKey.getEncoded()).read();
byte[] b = nullAttributes ? new byte[] { 0x05, 0x00 } : new byte[0];
DERValue derAttributes = new DERValue(DER.CONSTRUCTED | DER.CONTEXT | 0,
b.length, b, null);
ArrayList certRequestInfo = new ArrayList(4);
certRequestInfo.add(derVersion);
certRequestInfo.add(derSubject);
certRequestInfo.add(derSubjectPKInfo);
certRequestInfo.add(derAttributes);
DERValue derCertRequestInfo = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
certRequestInfo);
OID sigAlgorithmID = getSignatureAlgorithmOID();
DERValue derSigAlgorithmID = new DERValue(DER.OBJECT_IDENTIFIER,
sigAlgorithmID);
ArrayList sigAlgorithm = new ArrayList(2);
sigAlgorithm.add(derSigAlgorithmID);
if (! sigAlgorithmID.equals(Command.SHA1_WITH_DSA)) // it's an RSA-based
sigAlgorithm.add(new DERValue(DER.NULL, null));
sigAlgorithm.trimToSize();
DERValue derSignatureAlgorithm = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE,
sigAlgorithm);
signatureAlgorithm.initSign(privateKey);
signatureAlgorithm.update(derCertRequestInfo.getEncoded());
byte[] sigBytes = signatureAlgorithm.sign();
DERValue derSignature = new DERValue(DER.BIT_STRING, new BitString(sigBytes));
ArrayList csr = new ArrayList(3);
csr.add(derCertRequestInfo);
csr.add(derSignatureAlgorithm);
csr.add(derSignature);
DERValue derCSR = new DERValue(DER.CONSTRUCTED | DER.SEQUENCE, csr);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DERWriter.write(baos, derCSR);
byte[] result = baos.toByteArray();
return result;
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,235 @@
/* DeleteCmd.java -- The delete command handler of the keytool
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.keytool;
import java.io.IOException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.logging.Logger;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
/**
* The <b>-delete</b> keytool command handler is used to delete from the key
* store the entry associated with a designated alias.
* <p>
* Possible options for this command are:
* <p>
* <dl>
* <dt>-alias ALIAS</dt>
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
* Certificate</i>, in a key store is uniquely identified by a user-defined
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
* when referring to an entry in the key store. Unless specified otherwise,
* a default value of <code>mykey</code> shall be used when this option is
* omitted from the command line.
* <p></dd>
*
* <dt>-storetype STORE_TYP}</dt>
* <dd>Use this option to specify the type of the key store to use. The
* default value, if this option is omitted, is that of the property
* <code>keystore.type</code> in the security properties file, which is
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
* static method.
* <p></dd>
*
* <dt>-keystore URL</dt>
* <dd>Use this option to specify the location of the key store to use.
* The default value is a file {@link java.net.URL} referencing the file
* named <code>.keystore</code> located in the path returned by the call to
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
* as argument.
* <p>
* If a URL was specified, but was found to be malformed --e.g. missing
* protocol element-- the tool will attempt to use the URL value as a file-
* name (with absolute or relative path-name) of a key store --as if the
* protocol was <code>file:</code>.
* <p></dd>
*
* <dt>-storepass PASSWORD</dt>
* <dd>Use this option to specify the password protecting the key store. If
* this option is omitted from the command line, you will be prompted to
* provide a password.
* <p></dd>
*
* <dt>-provider PROVIDER_CLASS_NAME</dt>
* <dd>A fully qualified class name of a Security Provider to add to the
* current list of Security Providers already installed in the JVM in-use.
* If a provider class is specified with this option, and was successfully
* added to the runtime --i.e. it was not already installed-- then the tool
* will attempt to removed this Security Provider before exiting.
* <p></dd>
*
* <dt>-v</dt>
* <dd>Use this option to enable more verbose output.</dd>
* </dl>
*/
class DeleteCmd extends Command
{
private static final Logger log = Logger.getLogger(DeleteCmd.class.getName());
private String _alias;
private String _ksType;
private String _ksURL;
private String _ksPassword;
private String _providerClassName;
// default 0-arguments constructor
// public setters -----------------------------------------------------------
/** @param alias the alias to use. */
public void setAlias(String alias)
{
this._alias = alias;
}
/** @param type the key-store type to use. */
public void setStoretype(String type)
{
this._ksType = type;
}
/** @param url the key-store URL to use. */
public void setKeystore(String url)
{
this._ksURL = url;
}
/** @param password the key-store password to use. */
public void setStorepass(String password)
{
this._ksPassword = password;
}
/** @param className a security provider fully qualified class name to use. */
public void setProvider(String className)
{
this._providerClassName = className;
}
// life-cycle methods -------------------------------------------------------
int processArgs(String[] args, int i)
{
int limit = args.length;
String opt;
while (++i < limit)
{
opt = args[i];
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
if (opt == null || opt.length() == 0)
continue;
if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
_alias = args[++i];
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
_ksType = args[++i];
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
_ksURL = args[++i];
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
_ksPassword = args[++i];
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
_providerClassName = args[++i];
else if ("-v".equals(opt)) //$NON-NLS-1$
verbose = true;
else
break;
}
return i;
}
void setup() throws Exception
{
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
setTheAlias(_alias);
log.finer("-delete handler will use the following options:"); //$NON-NLS-1$
log.finer(" -alias=" + alias); //$NON-NLS-1$
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
log.finer(" -provider=" + provider); //$NON-NLS-1$
log.finer(" -v=" + verbose); //$NON-NLS-1$
}
void start() throws KeyStoreException, NoSuchAlgorithmException,
CertificateException, IOException
{
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
ensureStoreContainsAlias();
store.deleteEntry(alias);
saveKeyStore();
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
}
// own methods --------------------------------------------------------------
/**
* Set the alias to delete from the key store.
* <p>
* Unlike in other keytool handlers, the default value (<i>mykey</i>) for the
* Alias is not used. Instead, if an alias was not found on the command line,
* the user is prompted to enter one.
*
* @param anAlias a possibly null Alias gleaned from the command line.
* @throws IOException if an I/O related exception occurs during the process.
* @throws UnsupportedCallbackException if no implementation of a password
* callback handler was found.
*/
private void setTheAlias(String anAlias) throws IOException,
UnsupportedCallbackException
{
if (anAlias == null || anAlias.trim().length() == 0)
{
String prompt = Messages.getString("DeleteCmd.19"); //$NON-NLS-1$
NameCallback ncb = new NameCallback(prompt);
getCallbackHandler().handle(new Callback[] { ncb });
anAlias = ncb.getName();
if (anAlias == null || anAlias.trim().length() == 0)
throw new SecurityException(Messages.getString("DeleteCmd.20")); //$NON-NLS-1$
}
alias = anAlias.trim();
}
}
@@ -0,0 +1,266 @@
/* ExportCmd.java -- The export command handler of the keytool
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.keytool;
import gnu.java.security.util.Base64;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.KeyStoreException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.util.logging.Logger;
/**
* The <b>-export</b> keytool command handler is used to read the certificate
* associated with a designated alias from the key store, and write it to a
* designated file.
* <p>
* Possible options for this command are:
* <p>
* <dl>
* <dt>-alias ALIAS</dt>
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
* Certificate</i>, in a key store is uniquely identified by a user-defined
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
* when referring to an entry in the key store. Unless specified otherwise,
* a default value of <code>mykey</code> shall be used when this option is
* omitted from the command line.
* <p></dd>
*
* <dt>-file FILE_NAME</dt>
* <dd>The fully qualified path of the file where the certificate will be
* exported to. If omitted, STDOUT will be used instead.
* <p></dd>
*
* <dt>-storetype STORE_TYP}</dt>
* <dd>Use this option to specify the type of the key store to use. The
* default value, if this option is omitted, is that of the property
* <code>keystore.type</code> in the security properties file, which is
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
* static method.
* <p></dd>
*
* <dt>-keystore URL</dt>
* <dd>Use this option to specify the location of the key store to use.
* The default value is a file {@link java.net.URL} referencing the file
* named <code>.keystore</code> located in the path returned by the call to
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
* as argument.
* <p>
* If a URL was specified, but was found to be malformed --e.g. missing
* protocol element-- the tool will attempt to use the URL value as a file-
* name (with absolute or relative path-name) of a key store --as if the
* protocol was <code>file:</code>.
* <p></dd>
*
* <dt>-storepass PASSWORD</dt>
* <dd>Use this option to specify the password protecting the key store. If
* this option is omitted from the command line, you will be prompted to
* provide a password.
* <p></dd>
*
* <dt>-provider PROVIDER_CLASS_NAME</dt>
* <dd>A fully qualified class name of a Security Provider to add to the
* current list of Security Providers already installed in the JVM in-use.
* If a provider class is specified with this option, and was successfully
* added to the runtime --i.e. it was not already installed-- then the tool
* will attempt to removed this Security Provider before exiting.
* <p></dd>
*
* <dt>-rfc</dt>
* <dd>Use RFC-1421 specifications when encoding the output.
* <p></dd>
*
* <dt>-v</dt>
* <dd>Output the certificate in binary DER encoding. This is the default
* output format of the command if neither <code>-rfc</code> nor
* <code>-v</code> options were detected on the command line. If both this
* option and the <code>-rfc</code> option are detected on the command
* line, the tool will opt for the RFC-1421 style encoding.</dd>
* </dl>
*/
class ExportCmd extends Command
{
private static final Logger log = Logger.getLogger(ExportCmd.class.getName());
private String _alias;
private String _certFileName;
private String _ksType;
private String _ksURL;
private String _ksPassword;
private String _providerClassName;
private boolean rfc;
// default 0-arguments constructor
// public setters -----------------------------------------------------------
/** @param alias the alias to use. */
public void setAlias(String alias)
{
this._alias = alias;
}
/** @param pathName the fully qualified path name of the file to process. */
public void setFile(String pathName)
{
this._certFileName = pathName;
}
/** @param type the key-store type to use. */
public void setStoretype(String type)
{
this._ksType = type;
}
/** @param url the key-store URL to use. */
public void setKeystore(String url)
{
this._ksURL = url;
}
/** @param password the key-store password to use. */
public void setStorepass(String password)
{
this._ksPassword = password;
}
/** @param className a security provider fully qualified class name to use. */
public void setProvider(String className)
{
this._providerClassName = className;
}
/**
* @param flag whether to use, or not, RFC-1421 format when exporting the
* certificate(s).
*/
public void setRfc(String flag)
{
this.rfc = Boolean.valueOf(flag).booleanValue();
}
// life-cycle methods -------------------------------------------------------
int processArgs(String[] args, int i)
{
int limit = args.length;
String opt;
while (++i < limit)
{
opt = args[i];
log.finest("args[" + i + "]=" + opt);
if (opt == null || opt.length() == 0)
continue;
if ("-alias".equals(opt)) // -alias ALIAS
_alias = args[++i];
else if ("-file".equals(opt)) // -file FILE_NAME
_certFileName = args[++i];
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE
_ksType = args[++i];
else if ("-keystore".equals(opt)) // -keystore URL
_ksURL = args[++i];
else if ("-storepass".equals(opt)) // -storepass PASSWORD
_ksPassword = args[++i];
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME
_providerClassName = args[++i];
else if ("-rfc".equals(opt))
rfc = true;
else if ("-v".equals(opt))
verbose = true;
else
break;
}
return i;
}
void setup() throws Exception
{
setOutputStreamParam(_certFileName);
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
setAliasParam(_alias);
log.finer("-export handler will use the following options:");
log.finer(" -alias=" + alias);
log.finer(" -file=" + _certFileName);
log.finer(" -storetype=" + storeType);
log.finer(" -keystore=" + storeURL);
log.finer(" -storepass=" + String.valueOf(storePasswordChars));
log.finer(" -provider=" + provider);
log.finer(" -rfc=" + rfc);
log.finer(" -v=" + verbose);
}
void start() throws KeyStoreException, CertificateEncodingException,
IOException
{
log.entering(this.getClass().getName(), "start");
ensureStoreContainsAlias();
Certificate certificate;
if (store.isCertificateEntry(alias))
{
log.fine("Alias [" + alias + "] is a trusted certificate");
certificate = store.getCertificate(alias);
}
else
{
log.fine("Alias [" + alias + "] is a key entry");
Certificate[] chain = store.getCertificateChain(alias);
certificate = chain[0];
}
byte[] derBytes = certificate.getEncoded();
if (rfc)
{
String encoded = Base64.encode(derBytes, 0, derBytes.length, true);
PrintWriter pw = new PrintWriter(outStream, true);
pw.println("-----BEGIN CERTIFICATE-----");
pw.println(encoded);
pw.println("-----END CERTIFICATE-----");
}
else
outStream.write(derBytes);
// stream is closed in Command.teardown()
log.exiting(this.getClass().getName(), "start");
}
}
@@ -0,0 +1,511 @@
/* GenKeyCmd.java -- The genkey command handler of the keytool
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.keytool;
import gnu.java.security.util.Util;
import gnu.java.security.x509.X500DistinguishedName;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.logging.Logger;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.TextInputCallback;
import javax.security.auth.callback.TextOutputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
/**
* The <b>-genkey</b> keytool command handler is used to generate a key pair (a
* public, and associated private keys). It then generates a self-signed X509 v1
* certificate (authenticating the public key) and stores this certificate and
* the private key in the key store associating both to a designated alias.
* <p>
* Possible options for this command are:
* <p>
* <dl>
* <dt>-alias ALIAS</dt>
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
* Certificate</i>, in a key store is uniquely identified by a user-defined
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
* when referring to an entry in the key store. Unless specified otherwise,
* a default value of <code>mykey</code> shall be used when this option is
* omitted from the command line.
* <p></dd>
*
* <dt>-keyalg ALGORITHM</dt>
* <dd>Use this option to specify the canonical name of the key-pair
* generation algorithm. The default value for this option is
* <code>DSS</code> (a synonym for the Digital Signature Algorithm also
* known as <code>DSA</code>).
* <p></dd>
*
* <dt>-keysize KEY_SIZE</dt>
* <dd>Use this option to specify the number of bits of the shared modulus
* (for both the public and private keys) to use when generating new keys.
* A default value of <code>1024</code> will be used if this option is
* omitted from the command line.
* <p></dd>
*
* <dt>-sigalg ALGORITHM</dt>
* <dd>The canonical name of the digital signature algorithm to use for
* signing certificates. If this option is omitted, a default value will be
* chosen based on the type of the key-pair; i.e. the algorithm that ends
* up being used by the <code>-keyalg</code> option. If the key-pair
* generation algorithm is <code>DSA</code>, the value for the signature
* algorithm will be <code>SHA1withDSA</code>. If on the other hand the
* key-pair generation algorithm is <code>RSA</code>, then the tool will
* use <code>MD5withRSA</code> as the signature algorithm.
* <p></dd>
*
* <dt>-dname NAME</dt>
* <dd>This a mandatory value for this command. If this option is omitted
* the tool will prompt you to enter a <i>Distinguished Name</i> to use as
* both the <i>Owner</i> and <i>Issuer</i> of the generated self-signed
* certificate.
* <p>
* The syntax of a valid value for this option MUST follow RFC-2253
* specifications. Namely the following components (with their accepted
* meaning) will be recognized. Note that the component name is case-
* insensitive:
* <dl>
* <dt>CN</dt>
* <dd>The Common Name; e.g. "host.domain.com"</dd>
*
* <dt>OU</dt>
* <dd>The Organizational Unit; e.g. "IT Department"</dd>
*
* <dt>O</dt>
* <dd>The Organization Name; e.g. "The Sample Company"</dd>
*
* <dt>L</dt>
* <dd>The Locality Name; e.g. "Sydney"</dd>
*
* <dt>ST</dt>
* <dd>The State Name; e.g. "New South Wales"</dd>
*
* <dt>C</dt>
* <dd>The 2-letter Country identifier; e.g. "AU"</dd>
* </dl>
* <p>
* When specified with a <code>-dname</code> option, each pair of component
* / value will be separated from the other with a comma. Each component
* and value pair MUST be separated by an equal sign. For example, the
* following is a valid DN value:
* <pre>
* CN=host.domain.com, O=The Sample Company, L=Sydney, ST=NSW, C=AU
* </pre>
* If this option is omitted, the tool will prompt you to enter the
* information through the console.
* <p></dd>
*
* <dt>-keypass PASSWORD</dt>
* <dd>Use this option to specify the password which the tool will use to
* protect the newly created Key Entry.
* <p>
* If this option is omitted, you will be prompted to provide a password.
* <p></dd>
*
* <dt>-validity DAY_COUNT</dt>
*
* <dt>-storetype STORE_TYP}</dt>
* <dd>Use this option to specify the type of the key store to use. The
* default value, if this option is omitted, is that of the property
* <code>keystore.type</code> in the security properties file, which is
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
* static method.
* <p></dd>
*
* <dt>-keystore URL</dt>
* <dd>Use this option to specify the location of the key store to use.
* The default value is a file {@link java.net.URL} referencing the file
* named <code>.keystore</code> located in the path returned by the call to
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
* as argument.
* <p>
* If a URL was specified, but was found to be malformed --e.g. missing
* protocol element-- the tool will attempt to use the URL value as a file-
* name (with absolute or relative path-name) of a key store --as if the
* protocol was <code>file:</code>.
* <p></dd>
*
* <dt>-storepass PASSWORD</dt>
* <dd>Use this option to specify the password protecting the key store. If
* this option is omitted from the command line, you will be prompted to
* provide a password.
* <p></dd>
*
* <dt>-provider PROVIDER_CLASS_NAME</dt>
* <dd>A fully qualified class name of a Security Provider to add to the
* current list of Security Providers already installed in the JVM in-use.
* If a provider class is specified with this option, and was successfully
* added to the runtime --i.e. it was not already installed-- then the tool
* will attempt to removed this Security Provider before exiting.
* <p></dd>
*
* <dt>-v</dt>
* <dd>Use this option to enable more verbose output.</dd>
* </dl>
*/
class GenKeyCmd extends Command
{
private static final Logger log = Logger.getLogger(GenKeyCmd.class.getName());
/** Default key size in bits. */
private static final int DEFAULT_KEY_SIZE = 1024;
private String _alias;
private String _keyAlgorithm;
private String _keySizeStr;
private String _sigAlgorithm;
private String _dName;
private String _password;
private String _validityStr;
private String _ksType;
private String _ksURL;
private String _ksPassword;
private String _providerClassName;
private int keySize;
private X500DistinguishedName distinguishedName;
// default 0-arguments constructor
// public setters -----------------------------------------------------------
/** @param alias the alias to use. */
public void setAlias(String alias)
{
this._alias = alias;
}
/** @param algorithm the canonical name of the key-pair algorithm to use. */
public void setKeyalg(String algorithm)
{
this._keyAlgorithm = algorithm;
}
/**
* @param bits the string representation of the number of bits (a decimal
* positive integer) the modulus of the generated keys (private and
* public) should have.
*/
public void setKeysize(String bits)
{
this._validityStr = bits;
}
/**
* @param algorithm the canonical name of the digital signature algorithm to
* use.
*/
public void setSigalg(String algorithm)
{
this._sigAlgorithm = algorithm;
}
/** @param name the distiniguished name to use. */
public void setDname(String name)
{
this._dName = name;
}
/** @param password the (private) key password to use. */
public void setKeypass(String password)
{
this._password = password;
}
/**
* @param days the string representation of the number of days (a decimal,
* positive integer) to assign to the generated certificate.
*/
public void setValidity(String days)
{
this._validityStr = days;
}
/** @param type the key-store type to use. */
public void setStoretype(String type)
{
this._ksType = type;
}
/** @param url the key-store URL to use. */
public void setKeystore(String url)
{
this._ksURL = url;
}
/** @param password the key-store password to use. */
public void setStorepass(String password)
{
this._ksPassword = password;
}
/** @param className a security provider fully qualified class name to use. */
public void setProvider(String className)
{
this._providerClassName = className;
}
// life-cycle methods -------------------------------------------------------
int processArgs(String[] args, int i)
{
int limit = args.length;
String opt;
while (++i < limit)
{
opt = args[i];
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
if (opt == null || opt.length() == 0)
continue;
if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
_alias = args[++i];
else if ("-keyalg".equals(opt)) // -keyalg ALGORITHM //$NON-NLS-1$
_keyAlgorithm = args[++i];
else if ("-keysize".equals(opt)) // -keysize KEY_SIZE //$NON-NLS-1$
_keySizeStr = args[++i];
else if ("-sigalg".equals(opt)) // -sigalg ALGORITHM //$NON-NLS-1$
_sigAlgorithm = args[++i];
else if ("-dname".equals(opt)) // -dname NAME //$NON-NLS-1$
_dName = args[++i];
else if ("-keypass".equals(opt)) // -keypass PASSWORD //$NON-NLS-1$
_password = args[++i];
else if ("-validity".equals(opt)) // -validity DAY_COUNT //$NON-NLS-1$
_validityStr = args[++i];
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
_ksType = args[++i];
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
_ksURL = args[++i];
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
_ksPassword = args[++i];
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
_providerClassName = args[++i];
else if ("-v".equals(opt)) //$NON-NLS-1$
verbose = true;
else
break;
}
return i;
}
void setup() throws Exception
{
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
setAliasParam(_alias);
setKeyPasswordParam(_password);
setAlgorithmParams(_keyAlgorithm, _sigAlgorithm);
setKeySize(_keySizeStr);
setDName(_dName);
setValidityParam(_validityStr);
log.finer("-genkey handler will use the following options:"); //$NON-NLS-1$
log.finer(" -alias=" + alias); //$NON-NLS-1$
log.finer(" -keyalg=" + keyPairGenerator.getAlgorithm()); //$NON-NLS-1$
log.finer(" -keysize=" + keySize); //$NON-NLS-1$
log.finer(" -sigalg=" + signatureAlgorithm.getAlgorithm()); //$NON-NLS-1$
log.finer(" -dname=" + distinguishedName); //$NON-NLS-1$
log.finer(" -keypass=" + String.valueOf(keyPasswordChars)); //$NON-NLS-1$
log.finer(" -validity=" + validityInDays); //$NON-NLS-1$
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
log.finer(" -provider=" + provider); //$NON-NLS-1$
log.finer(" -v=" + verbose); //$NON-NLS-1$
}
void start() throws CertificateException, KeyStoreException,
InvalidKeyException, SignatureException, IOException,
NoSuchAlgorithmException
{
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
// 1. generate a new key-pair
log.fine("About to generate key-pair...");
keyPairGenerator.initialize(keySize);
KeyPair kp = keyPairGenerator.generateKeyPair();
PublicKey publicKey = kp.getPublic();
PrivateKey privateKey = kp.getPrivate();
// 2. generate a self-signed certificate
log.fine("About to generate a self-signed certificate...");
byte[] derBytes = getSelfSignedCertificate(distinguishedName,
publicKey,
privateKey);
log.finest(Util.dumpString(derBytes, "derBytes ")); //$NON-NLS-1$
CertificateFactory x509Factory = CertificateFactory.getInstance(Main.X_509);
ByteArrayInputStream bais = new ByteArrayInputStream(derBytes);
Certificate certificate = x509Factory.generateCertificate(bais);
log.finest("certificate = " + certificate); //$NON-NLS-1$
// 3. store it, w/ its private key, associating them to alias
Certificate[] chain = new Certificate[] { certificate };
log.finest("About to store newly generated material in key store..."); //$NON-NLS-1$
store.setKeyEntry(alias, privateKey, keyPasswordChars, chain);
// 4. persist the key store
saveKeyStore();
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
}
// own methods --------------------------------------------------------------
/**
* @param size the desired key size as a string.
* @throws NumberFormatException if the string does not represent a valid
* decimal integer value.
*/
private void setKeySize(String size)
{
if (size == null || size.trim().length() == 0)
this.keySize = DEFAULT_KEY_SIZE;
else
{
size = size.trim();
keySize = Integer.parseInt(size);
// When generating a DSA key pair, the key size must be in the range
// from 512 to 1024 bits, and must be a multiple of 64. The default
// key size for any algorithm is 1024 bits
if (keySize < 1)
throw new IllegalArgumentException(Messages.getString("GenKeyCmd.54")); //$NON-NLS-1$
}
}
/**
* @param name the X.500 distinguished name of the principal for whom the
* key/certificate are being generated.
* @throws UnsupportedCallbackException if no implementation of a name
* callback is available.
* @throws IOException if an I/O related exception occurs during the process.
* @throws IllegalArgumentException if the designated, or captured, value is
* not a valid X.500 distinguished name.
*/
private void setDName(String name) throws IOException,
UnsupportedCallbackException
{
if (name != null && name.trim().length() > 0)
name = name.trim();
else
{
// prompt user to provide one
String dnTxt = Messages.getString("GenKeyCmd.0"); //$NON-NLS-1$
String oDefault = Messages.getString("GenKeyCmd.6"); //$NON-NLS-1$
String lDefault = Messages.getString("GenKeyCmd.7"); //$NON-NLS-1$
String stDefault = Messages.getString("GenKeyCmd.8"); //$NON-NLS-1$
String cDefault = Messages.getString("GenKeyCmd.9"); //$NON-NLS-1$
String cnPrompt = Messages.getString("GenKeyCmd.10"); //$NON-NLS-1$
String oPrompt = Messages.getFormattedString("GenKeyCmd.11", oDefault); //$NON-NLS-1$
String ouPrompt = Messages.getString("GenKeyCmd.13"); //$NON-NLS-1$
String lPrompt = Messages.getFormattedString("GenKeyCmd.14", lDefault); //$NON-NLS-1$
String stPrompt = Messages.getFormattedString("GenKeyCmd.16", stDefault); //$NON-NLS-1$
String cPrompt = Messages.getFormattedString("GenKeyCmd.18", cDefault); //$NON-NLS-1$
TextOutputCallback dnCB = new TextOutputCallback(TextOutputCallback.INFORMATION,
dnTxt);
TextInputCallback cnCB = new TextInputCallback(cnPrompt);
TextInputCallback oCB = new TextInputCallback(oPrompt, oDefault);
TextInputCallback ouCB = new TextInputCallback(ouPrompt);
TextInputCallback lCB = new TextInputCallback(lPrompt, lDefault);
TextInputCallback sCB = new TextInputCallback(stPrompt, stDefault);
TextInputCallback cCB = new TextInputCallback(cPrompt, cDefault);
getCallbackHandler().handle(new Callback[] { dnCB, cnCB, oCB, ouCB, lCB, sCB, cCB });
StringBuilder sb = new StringBuilder();
// handle CN
name = parseUserPrompt(cnCB);
if (name != null && name.length() > 0)
sb.append("CN=").append(name); //$NON-NLS-1$
// handle O
name = parseUserPrompt(oCB);
if (name != null && name.length() > 0)
sb.append(",O=").append(name); //$NON-NLS-1$
// handle OU
name = parseUserPrompt(ouCB);
if (name != null && name.length() > 0)
sb.append(",OU=").append(name.trim()); //$NON-NLS-1$
// handle L
name = parseUserPrompt(lCB);
if (name != null && name.length() > 0)
sb.append(",L=").append(name.trim()); //$NON-NLS-1$
// handle ST
name = parseUserPrompt(sCB);
if (name != null && name.length() > 0)
sb.append(",ST=").append(name.trim()); //$NON-NLS-1$
// handle C
name = parseUserPrompt(cCB);
if (name != null && name.length() > 0)
sb.append(",C=").append(name.trim()); //$NON-NLS-1$
name = sb.toString().trim();
}
log.fine("dName=[" + name + "]"); //$NON-NLS-1$ //$NON-NLS-2$
distinguishedName = new X500DistinguishedName(name);
}
private String parseUserPrompt(TextInputCallback ticb)
{
String result = ticb.getText();
if (result == null || result.trim().length() == 0)
result = ticb.getDefaultText();
else if (result.trim().equals(".")) //$NON-NLS-1$
result = null;
else
result = result.trim();
return result;
}
}
@@ -0,0 +1,185 @@
/* IdentityDBCmd.java -- The identitydb command handler of the keytool
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.keytool;
import java.util.logging.Logger;
/**
* <b>NOT IMPLEMENTED YET</b>
* <p>
* The <b>-identitydb</b> keytool command handler is used to read the JDK 1.1.x-
* style identity database and add its entries to the key store. If a key store
* does not exist, it is created.
* <p>
* Possible options for this command are:
* <p>
* <dl>
* <dt>-file FILE_NAME</dt>
* <dd>The fully qualified path of the identity file to import. If this
* option is omitted, the tool will process STDIN.
* <p></dd>
*
* <dt>-storetype STORE_TYP}</dt>
* <dd>Use this option to specify the type of the key store to use. The
* default value, if this option is omitted, is that of the property
* <code>keystore.type</code> in the security properties file, which is
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
* static method.
* <p></dd>
*
* <dt>-keystore URL</dt>
* <dd>Use this option to specify the location of the key store to use.
* The default value is a file {@link java.net.URL} referencing the file
* named <code>.keystore</code> located in the path returned by the call to
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
* as argument.
* <p>
* If a URL was specified, but was found to be malformed --e.g. missing
* protocol element-- the tool will attempt to use the URL value as a file-
* name (with absolute or relative path-name) of a key store --as if the
* protocol was <code>file:</code>.
* <p></dd>
*
* <dt>-storepass PASSWORD</dt>
* <dd>Use this option to specify the password protecting the key store. If
* this option is omitted from the command line, you will be prompted to
* provide a password.
* <p></dd>
*
* <dt>-provider PROVIDER_CLASS_NAME</dt>
* <dd>A fully qualified class name of a Security Provider to add to the
* current list of Security Providers already installed in the JVM in-use.
* If a provider class is specified with this option, and was successfully
* added to the runtime --i.e. it was not already installed-- then the tool
* will attempt to removed this Security Provider before exiting.
* <p></dd>
*
* <dt>-v</dt>
* <dd>Use this option to enable more verbose output.</dd>
* </dl>
*/
class IdentityDBCmd extends Command
{
private static final Logger log = Logger.getLogger(IdentityDBCmd.class.getName());
private String _idbFileName;
private String _ksType;
private String _ksURL;
private String _ksPassword;
private String _providerClassName;
// default 0-arguments constructor
// public setters -----------------------------------------------------------
/** @param pathName the fully qualified path name of the file to process. */
public void setFile(String pathName)
{
this._idbFileName = pathName;
}
/** @param type the key-store type to use. */
public void setStoretype(String type)
{
this._ksType = type;
}
/** @param url the key-store URL to use. */
public void setKeystore(String url)
{
this._ksURL = url;
}
/** @param password the key-store password to use. */
public void setStorepass(String password)
{
this._ksPassword = password;
}
/** @param className a security provider fully qualified class name to use. */
public void setProvider(String className)
{
this._providerClassName = className;
}
// life-cycle methods -------------------------------------------------------
int processArgs(String[] args, int i)
{
int limit = args.length;
String opt;
while (++i < limit)
{
opt = args[i];
log.finest("args[" + i + "]=" + opt);
if (opt == null || opt.length() == 0)
continue;
if ("-file".equals(opt)) // -file FILE_NAME
_idbFileName = args[++i];
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE
_ksType = args[++i];
else if ("-keystore".equals(opt)) // -keystore URL
_ksURL = args[++i];
else if ("-storepass".equals(opt)) // -storepass PASSWORD
_ksPassword = args[++i];
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME
_providerClassName = args[++i];
else if ("-v".equals(opt))
verbose = true;
else
break;
}
return i;
}
void setup() throws Exception
{
setInputStreamParam(_idbFileName);
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
log.finer("-identitydb handler will use the following options:");
log.finer(" -file=" + _idbFileName);
log.finer(" -storetype=" + storeType);
log.finer(" -keystore=" + storeURL);
log.finer(" -storepass=" + new String(storePasswordChars));
log.finer(" -provider=" + provider);
log.finer(" -v=" + verbose);
}
}
@@ -0,0 +1,751 @@
/* ImportCmd.java -- The import command handler of the keytool
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.keytool;
import gnu.classpath.SystemProperties;
import gnu.java.security.x509.X509CertPath;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertPathValidator;
import java.security.cert.CertPathValidatorException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.PKIXCertPathValidatorResult;
import java.security.cert.PKIXParameters;
import java.security.interfaces.DSAParams;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.util.Collection;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.ConfirmationCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
/**
* The <code>-import</code> keytool command handler is used to read an X.509
* certificate, or a PKCS#7 Certificate Reply from a designated input source and
* incorporate the certificates into the key store.
* <p>
* If the <i>Alias</i> does not already exist in the key store, the tool treats
* the certificate read from the input source as a new Trusted Certificate. It
* then attempts to discover a chain-of-trust, starting from that certificate
* and ending at another <i>Trusted Certificate</i>, already stored in the key
* store. If the <code>-trustcacerts</code> option is present, an additional
* key store, of type <code>JKS</code> named <code>cacerts</code>, and assumed
* to be present in <code>${JAVA_HOME}/lib/security</code> will also be
* consulted if found --<code>${JAVA_HOME}</code> refers to the location of an
* installed Java Runtime Environment (JRE). If no chain-of-trust can be
* established, and unless the <code>-noprompt</code> option has been specified,
* the certificate is printed to STDOUT and the user is prompted for a
* confirmation.
* <p>
* If <i>Alias</i> exists in the key store, the tool will treat the
* certificate(s) read from the input source as a <i>Certificate Reply</i>,
* which can be a chain of certificates, that eventually would replace the chain
* of certificates associated with the <i>Key Entry</i> of that <i>Alias</i>.
* The substitution of the certificates only occurs if a chain-of-trust can be
* established between the bottom certificate of the chain read from the input
* file and the <i>Trusted Certificates</i> already present in the key store.
* Again, if the <code>-trustcacerts</code> option is specified, additional
* <i>Trusted Certificates</i> in the same <code>cacerts</code> key store will
* be considered. If no chain-of-trust can be established, the operation will
* abort.
* <p>
* Possible options for this command are:
* <p>
* <dl>
* <dt>-alias ALIAS</dt>
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
* Certificate</i>, in a key store is uniquely identified by a user-defined
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
* when referring to an entry in the key store. Unless specified otherwise,
* a default value of <code>mykey</code> shall be used when this option is
* omitted from the command line.
* <p></dd>
*
* <dt>-file FILE_NAME</dt>
* <dd>The fully qualified path of the file to read from. If omitted, the
* tool will process STDIN.
* <p></dd>
*
* <dt>-keypass PASSWORD</dt>
* <dd>Use this option to specify the password which the tool will use to
* protect the <i>Key Entry</i> associated with the designated <i>Alias</i>,
* when replacing this <i>Alias</i>' chain of certificates with that found
* in the certificate reply.
* <p>
* If this option is omitted, and the chain-of-trust for the certificate
* reply has been established, the tool will first attempt to unlock the
* <i>Key Entry</i> using the same password protecting the key store. If
* this fails, you will then be prompted to provide a password.
* <p></dd>
*
* <dt>-noprompt</dt>
* <dd>Use this option to prevent the tool from prompting the user.
* <p></dd>
*
* <dt>-trustcacerts</dt>
* <dd>Use this option to indicate to the tool that a key store, of type
* <code>JKS</code>, named <code>cacerts</code>, and usually located in
* <code>lib/security</code> in an installed Java Runtime Environment
* should be considered when trying to establish chain-of-trusts.
* <p></dd>
*
* <dt>-storetype STORE_TYP}</dt>
* <dd>Use this option to specify the type of the key store to use. The
* default value, if this option is omitted, is that of the property
* <code>keystore.type</code> in the security properties file, which is
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
* static method.
* <p></dd>
*
* <dt>-keystore URL</dt>
* <dd>Use this option to specify the location of the key store to use.
* The default value is a file {@link java.net.URL} referencing the file
* named <code>.keystore</code> located in the path returned by the call to
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
* as argument.
* <p>
* If a URL was specified, but was found to be malformed --e.g. missing
* protocol element-- the tool will attempt to use the URL value as a file-
* name (with absolute or relative path-name) of a key store --as if the
* protocol was <code>file:</code>.
* <p></dd>
*
* <dt>-storepass PASSWORD</dt>
* <dd>Use this option to specify the password protecting the key store. If
* this option is omitted from the command line, you will be prompted to
* provide a password.
* <p></dd>
*
* <dt>-provider PROVIDER_CLASS_NAME</dt>
* <dd>A fully qualified class name of a Security Provider to add to the
* current list of Security Providers already installed in the JVM in-use.
* If a provider class is specified with this option, and was successfully
* added to the runtime --i.e. it was not already installed-- then the tool
* will attempt to removed this Security Provider before exiting.
* <p></dd>
*
* <dt>-v</dt>
* <dd>Use this option to enable more verbose output.</dd>
* </dl>
*/
class ImportCmd extends Command
{
private static final Logger log = Logger.getLogger(ImportCmd.class.getName());
private String _alias;
private String _certFileName;
private String _password;
private boolean noPrompt;
private boolean trustCACerts;
private String _ksType;
private String _ksURL;
private String _ksPassword;
private String _providerClassName;
private CertificateFactory x509Factory;
private boolean imported;
// default 0-arguments constructor
// public setters -----------------------------------------------------------
/** @param alias the existing alias to use. */
public void setAlias(String alias)
{
this._alias = alias;
}
/** @param pathName the fully qualified path name of the file to process. */
public void setFile(String pathName)
{
this._certFileName = pathName;
}
/** @param password the existing (private) key password to use. */
public void setKeypass(String password)
{
this._password = password;
}
/**
* @param flag whether to prompt, or not, the user to verify certificate
* fingerprints.
*/
public void setNoprompt(String flag)
{
this.noPrompt = Boolean.valueOf(flag).booleanValue();
}
/**
* @param flag whether to trust, or not, certificates found in the
* <code>cacerts</code> key store.
*/
public void setTrustcacerts(String flag)
{
this.trustCACerts = Boolean.valueOf(flag).booleanValue();
}
/** @param type the key-store type to use. */
public void setStoretype(String type)
{
this._ksType = type;
}
/** @param url the key-store URL to use. */
public void setKeystore(String url)
{
this._ksURL = url;
}
/** @param password the key-store password to use. */
public void setStorepass(String password)
{
this._ksPassword = password;
}
/** @param className a security provider fully qualified class name to use. */
public void setProvider(String className)
{
this._providerClassName = className;
}
// life-cycle methods -------------------------------------------------------
int processArgs(String[] args, int i)
{
int limit = args.length;
String opt;
while (++i < limit)
{
opt = args[i];
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
if (opt == null || opt.length() == 0)
continue;
if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
_alias = args[++i];
else if ("-file".equals(opt)) // -file FILE_NAME //$NON-NLS-1$
_certFileName = args[++i];
else if ("-keypass".equals(opt)) // -keypass PASSWORD //$NON-NLS-1$
_password = args[++i];
else if ("-noprompt".equals(opt)) //$NON-NLS-1$
noPrompt = true;
else if ("-trustcacerts".equals(opt)) //$NON-NLS-1$
trustCACerts = true;
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
_ksType = args[++i];
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
_ksURL = args[++i];
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
_ksPassword = args[++i];
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
_providerClassName = args[++i];
else if ("-v".equals(opt)) //$NON-NLS-1$
verbose = true;
else
break;
}
return i;
}
void setup() throws Exception
{
setInputStreamParam(_certFileName);
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
setAliasParam(_alias);
setKeyPasswordNoPrompt(_password);
log.finer("-import handler will use the following options:"); //$NON-NLS-1$
log.finer(" -alias=" + alias); //$NON-NLS-1$
log.finer(" -file=" + _certFileName); //$NON-NLS-1$
log.finer(" -keypass=" + _password); //$NON-NLS-1$
log.finer(" -noprompt=" + noPrompt); //$NON-NLS-1$
log.finer(" -trustcacerts=" + trustCACerts); //$NON-NLS-1$
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
log.finer(" -provider=" + provider); //$NON-NLS-1$
log.finer(" -v=" + verbose); //$NON-NLS-1$
}
void start() throws CertificateException, KeyStoreException, IOException,
UnsupportedCallbackException, NoSuchAlgorithmException,
CertPathValidatorException, UnrecoverableKeyException
{
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
x509Factory = CertificateFactory.getInstance("X.509"); //$NON-NLS-1$
// the alias will tell us whether we're dealing with
// a new trusted certificate or a certificate reply
if (! store.containsAlias(alias))
importNewTrustedCertificate();
else
{
ensureAliasIsKeyEntry();
importCertificateReply();
}
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
}
// own methods --------------------------------------------------------------
/**
* When importing a new trusted certificate, <i>alias</i> MUST NOT yet exist
* in the key store.
* <p>
* Before adding the certificate to the key store and associate it with the
* designated Alias, this method tries to verify it by attempting to construct
* a chain of trust from that certificate to a self-signed certificate
* (belonging to a root CA), using (already) trusted certificates that are
* available in the key store.
* <p>
* If the <code>-trustcacerts</code> option was detected on the command
* line, additional trusted certificates are considered for establishing the
* chain of trust. Those additional certificates are assumed to be in a key
* store, of type <code>JKS</code> named <code>cacerts</code> and usually
* located in <code>${JAVA_HOME}/lib/security</code>, where
* <code>${JAVA_HOME}</code> is the root folder location of a Java runtime.
* <p>
* If this method fails to establish a trust path from the certificate to be
* imported up to a trusted self-signed certificate, the certificate is
* printed to <code>STDOUT</code>, and the user is prompted to verify it,
* with the option of aborting the import operation. If however the option
* <code>-noprompt</code> was detected on the command line, no interaction
* with the user will take place and the import operation will abort.
*
* @throws CertificateException
* @throws KeyStoreException
* @throws NoSuchAlgorithmException
* @throws UnsupportedCallbackException
* @throws IOException
* @throws UnrecoverableKeyException
* @throws CertPathValidatorException
*/
private void importNewTrustedCertificate() throws CertificateException,
KeyStoreException, NoSuchAlgorithmException, IOException,
UnsupportedCallbackException, CertPathValidatorException,
UnrecoverableKeyException
{
log.entering(this.getClass().getName(), "importNewTrustedCertificate"); //$NON-NLS-1$
Certificate certificate = x509Factory.generateCertificate(inStream);
log.finest("certificate = " + certificate); //$NON-NLS-1$
LinkedList orderedReply = new LinkedList();
orderedReply.addLast(certificate);
if (findTrustAndUpdate(orderedReply, ! noPrompt))
{
store.setCertificateEntry(alias, certificate);
System.out.println(Messages.getString("ImportCmd.29")); //$NON-NLS-1$
saveKeyStore();
}
else
System.out.println(Messages.getString("ImportCmd.28")); //$NON-NLS-1$
log.exiting(this.getClass().getName(), "importNewTrustedCertificate"); //$NON-NLS-1$
}
/**
* A certificate reply is a certificate, whose Owner is stored in the key
* store associated to the designated Alias, and now signed by supposedly a
* trusted CA (Certificate Authority). In other words, the Subject in this
* certificate reply is Alias's own and the Issuer is a CA.
* <p>
* When importing a certificate reply, the reply is validated using trusted
* certificates from the key store, and optionally (if the option
* <code>-trustcacerts</code> was detected on the command line) certificates
* found in the key store, of type <code>JKS</code> named <code>cacerts</code>
* located in <code>${JAVA_HOME}/lib/security</code>, where
* <code>${JAVA_HOME}</code> is the root folder location of a Java runtime.
*
* @throws CertificateException
* @throws UnsupportedCallbackException
* @throws IOException
* @throws KeyStoreException
* @throws CertPathValidatorException
* @throws NoSuchAlgorithmException
* @throws UnrecoverableKeyException
*/
private void importCertificateReply() throws CertificateException,
IOException, UnsupportedCallbackException, KeyStoreException,
NoSuchAlgorithmException, CertPathValidatorException,
UnrecoverableKeyException
{
log.entering(this.getClass().getName(), "importCertificateReply"); //$NON-NLS-1$
Collection certificates = x509Factory.generateCertificates(inStream);
ensureReplyIsOurs(certificates);
// we now have established that the public keys are the same.
// find a chain-of-trust if one exists
if (certificates.size() == 1)
importCertificate((Certificate) certificates.iterator().next());
else
importChain(certificates);
log.exiting(this.getClass().getName(), "importCertificateReply"); //$NON-NLS-1$
}
/**
* If the reply is a single X.509 certificate, keytool attempts to establish a
* trust chain, starting at the certificate reply and ending at a self-signed
* certificate (belonging to a root CA). The certificate reply and the
* hierarchy of certificates used to authenticate the certificate reply form
* the new certificate chain of alias. If a trust chain cannot be established,
* the certificate reply is not imported. In this case, keytool does not print
* out the certificate, nor does it prompt the user to verify it. This is
* because it is very hard (if not impossible) for a user to determine the
* authenticity of the certificate reply.
*
* @param certificate the certificate reply to import into the key store.
* @throws NoSuchAlgorithmException
* @throws CertPathValidatorException
* @throws UnsupportedCallbackException
* @throws IOException
* @throws UnrecoverableKeyException
* @throws KeyStoreException
* @throws CertificateException
*/
private void importCertificate(Certificate certificate)
throws NoSuchAlgorithmException, CertPathValidatorException,
KeyStoreException, UnrecoverableKeyException, IOException,
UnsupportedCallbackException, CertificateException
{
log.entering(this.getClass().getName(), "importCertificate", certificate); //$NON-NLS-1$
LinkedList reply = new LinkedList();
reply.addLast(certificate);
if (! findTrustAndUpdate(reply, false))
throw new CertPathValidatorException(Messages.getString("ImportCmd.34")); //$NON-NLS-1$
Certificate[] newChain = (Certificate[]) reply.toArray(new Certificate[0]);
Key privateKey = getAliasPrivateKey();
store.setKeyEntry(alias, privateKey, keyPasswordChars, newChain);
saveKeyStore();
log.exiting(this.getClass().getName(), "importCertificate"); //$NON-NLS-1$
}
/**
* If the reply is a PKCS#7 formatted certificate chain, the chain is first
* ordered (with the user certificate first and the self-signed root CA
* certificate last), before keytool attempts to match the root CA certificate
* provided in the reply with any of the trusted certificates in the key store
* or the "cacerts" keystore file (if the -trustcacerts option was specified).
* If no match can be found, the information of the root CA certificate is
* printed out, and the user is prompted to verify it, e.g., by comparing the
* displayed certificate fingerprints with the fingerprints obtained from some
* other (trusted) source of information, which might be the root CA itself.
* The user then has the option of aborting the import operation. If the
* -noprompt option is given, however, there will be no interaction with the
* user.
*
* @param chain the collection of certificates parsed from the user
* designated input.
* @throws UnsupportedCallbackException
* @throws IOException
* @throws UnrecoverableKeyException
* @throws KeyStoreException
* @throws CertPathValidatorException
* @throws NoSuchAlgorithmException
* @throws CertificateException
*/
private void importChain(Collection chain) throws NoSuchAlgorithmException,
CertPathValidatorException, KeyStoreException, UnrecoverableKeyException,
IOException, UnsupportedCallbackException, CertificateException
{
log.entering(this.getClass().getName(), "importChain", chain); //$NON-NLS-1$
LinkedList reply = orderChain(chain);
if (findTrustAndUpdate(reply, ! noPrompt))
{
Certificate[] newChain = (Certificate[]) reply.toArray(new Certificate[0]);
Key privateKey = getAliasPrivateKey();
store.setKeyEntry(alias, privateKey, keyPasswordChars, newChain);
saveKeyStore();
}
log.exiting(this.getClass().getName(), "importChain"); //$NON-NLS-1$
}
/**
* Check to ensure that alias's public key is the subject of the first
* certificate in the passed certificate collection. Throws an exception if
* the public keys do not match.
*
* @param certificates a {@link Collection} of certificate replies (either a
* signle certificate reply, or a PKCS#7 certificate reply chain)
* usually sent by a CA as a response to a Certificate Signing
* Request (CSR).
* @throws IOException
* @throws UnsupportedCallbackException
* @throws KeyStoreException
*/
private void ensureReplyIsOurs(Collection certificates) throws IOException,
UnsupportedCallbackException, KeyStoreException
{
log.entering(this.getClass().getName(), "ensureReplyIsOurs"); //$NON-NLS-1$
Certificate certificate = (Certificate) certificates.iterator().next();
log.finest("certificate = " + certificate); //$NON-NLS-1$
Certificate[] chain = store.getCertificateChain(alias);
if (chain == null)
throw new IllegalArgumentException(Messages.getFormattedString("ImportCmd.37", //$NON-NLS-1$
alias));
Certificate anchor = chain[0];
PublicKey anchorPublicKey = anchor.getPublicKey();
PublicKey certPublicKey = certificate.getPublicKey();
boolean sameKey;
if (anchorPublicKey instanceof DSAPublicKey)
{
DSAPublicKey pk1 = (DSAPublicKey) anchorPublicKey;
if (!(certPublicKey instanceof DSAPublicKey))
throw new IllegalArgumentException(Messages.getString("ImportCmd.38")); //$NON-NLS-1$
sameKey = areEqual(pk1, (DSAPublicKey) certPublicKey);
}
else if (anchorPublicKey instanceof RSAPublicKey)
{
RSAPublicKey pk1 = (RSAPublicKey) anchorPublicKey;
if (!(certPublicKey instanceof RSAPublicKey))
throw new IllegalArgumentException(Messages.getString("ImportCmd.38")); //$NON-NLS-1$
sameKey = areEqual(pk1, (RSAPublicKey) certPublicKey);
}
else
throw new IllegalArgumentException(
Messages.getFormattedString("ImportCmd.40", //$NON-NLS-1$
new String[] { alias,
anchorPublicKey.getClass().getName() }));
if (! sameKey)
throw new IllegalArgumentException(Messages.getString("ImportCmd.41")); //$NON-NLS-1$
log.exiting(this.getClass().getName(), "ensureReplyIsOurs"); //$NON-NLS-1$
}
private boolean areEqual(DSAPublicKey pk1, DSAPublicKey pk2)
{
if (pk1.getY().compareTo(pk2.getY()) != 0)
return false;
DSAParams p1 = pk1.getParams();
DSAParams p2 = pk2.getParams();
if (p1.getG().compareTo(p2.getG()) != 0)
return false;
if (p1.getP().compareTo(p2.getP()) != 0)
return false;
return p1.getQ().compareTo(p2.getQ()) == 0;
}
private boolean areEqual(RSAPublicKey pk1, RSAPublicKey pk2)
{
if (pk1.getPublicExponent().compareTo(pk2.getPublicExponent()) != 0)
return false;
return pk1.getModulus().compareTo(pk2.getModulus()) == 0;
}
/**
* @param chain
* @return the input collection, ordered with own certificate first, and CA's
* self-signed certificate last.
*/
private LinkedList orderChain(Collection chain)
{
log.entering(this.getClass().getName(), "orderChain"); //$NON-NLS-1$
LinkedList result = new LinkedList();
log.entering(this.getClass().getName(), "orderChain", result); //$NON-NLS-1$
return result;
}
/**
* Given an ordered list of certificates, this method attempts to validate the
* chain, and if successful, updates the key store entry for the designated
* alias. The list of certificates is expected to be ordered as a chain, where
* the first is the alias's own certificate and the last being a self-signed
* CA certificate.
* <p>
* if <code>promptUser</code> is <code>true</code>, then even if no
* anchor trust certificate is found, the user is prompted to approve, or not,
* the import operation. On the other hand if the <code>promptUser</code>
* parameter is <code>false</code> then this method will throw an exception
* if no trust anchor is to be found.
*
* @param reply an ordered certificate path, where the last entry is the CA's
* self-signed certificate.
* @param promptUser a boolean flag indicating whether or not to prompt the
* user for explicit trust in a CA certificate.
* @return <code>true</code> if the validation succeeds; or <code>false</code>
* otherwise.
* @throws NoSuchAlgorithmException
* @throws CertPathValidatorException
* @throws UnsupportedCallbackException
* @throws IOException
* @throws UnrecoverableKeyException
* @throws KeyStoreException
* @throws CertificateEncodingException
*/
private boolean findTrustAndUpdate(LinkedList reply, boolean promptUser)
throws IOException, NoSuchAlgorithmException, CertPathValidatorException,
KeyStoreException, UnrecoverableKeyException, UnsupportedCallbackException,
CertificateEncodingException
{
log.entering(this.getClass().getName(), "findTrustAndUpdate"); //$NON-NLS-1$
X509CertPath certPath = new X509CertPath(reply);
CertPathValidator validator = CertPathValidator.getInstance("PKIX"); //$NON-NLS-1$
PKIXCertPathValidatorResult cpvr = findTrustInStore(certPath, validator);
if (cpvr == null && trustCACerts)
cpvr = findTrustInCACerts(certPath, validator);
boolean result = false;
if (cpvr == null)
{
if (promptUser)
{
printVerbose((Certificate) reply.getLast());
ConfirmationCallback ccb;
ccb = new ConfirmationCallback(Messages.getString("ImportCmd.32"), //$NON-NLS-1$
ConfirmationCallback.INFORMATION,
ConfirmationCallback.YES_NO_OPTION,
ConfirmationCallback.NO);
getCallbackHandler().handle(new Callback[] { ccb });
int answer = ccb.getSelectedIndex();
result = answer == ConfirmationCallback.YES;
}
}
else
{
log.fine("Found a chain-of-trust anchored by " + cpvr.getTrustAnchor()); //$NON-NLS-1$
Certificate trustedCert = cpvr.getTrustAnchor().getTrustedCert();
reply.addLast(trustedCert);
result = true;
}
log.entering(this.getClass().getName(), "findTrustAndUpdate", //$NON-NLS-1$
Boolean.valueOf(result));
return result;
}
private PKIXCertPathValidatorResult findTrustInStore(X509CertPath certPath,
CertPathValidator validator)
{
log.entering(this.getClass().getName(), "findTrustInStore"); //$NON-NLS-1$
PKIXCertPathValidatorResult result;
try
{
PKIXParameters params = new PKIXParameters(store);
result = (PKIXCertPathValidatorResult) validator.validate(certPath, params);
}
catch (Exception x)
{
log.log(Level.FINE,
"Exception in findTrustInStore(). Ignore + Return NULL", //$NON-NLS-1$
x);
result = null;
}
log.exiting(this.getClass().getName(), "findTrustInStore", result); //$NON-NLS-1$
return result;
}
private PKIXCertPathValidatorResult findTrustInCACerts(X509CertPath certPath,
CertPathValidator validator)
{
log.entering(this.getClass().getName(), "findTrustInCACerts"); //$NON-NLS-1$
FileInputStream stream = null;
PKIXCertPathValidatorResult result = null;
try
{
KeyStore cacerts = KeyStore.getInstance("jks"); //$NON-NLS-1$
String cacertsPath = SystemProperties.getProperty("java.home");
String fs = SystemProperties.getProperty("file.separator"); //$NON-NLS-1$
cacertsPath = new StringBuilder(cacertsPath).append(fs)
.append("lib").append(fs) //$NON-NLS-1$
.append("security").append(fs) //$NON-NLS-1$
.append("cacerts").toString(); //$NON-NLS-1$
stream = new FileInputStream(cacertsPath);
cacerts.load(stream, "changeit".toCharArray()); //$NON-NLS-1$
PKIXParameters params = new PKIXParameters(cacerts);
result = (PKIXCertPathValidatorResult) validator.validate(certPath,
params);
}
catch (Exception x)
{
log.log(Level.FINE,
"Exception in findTrustInCACerts(). Ignore + Return NULL", //$NON-NLS-1$
x);
}
finally
{
if (stream != null)
try
{
stream.close();
}
catch (Exception ignored)
{
}
}
log.exiting(this.getClass().getName(), "findTrustInCACerts", result); //$NON-NLS-1$
return result;
}
}
@@ -0,0 +1,344 @@
/* KeyCloneCmd.java -- The keyclone command handler of the keytool
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.keytool;
import java.io.IOException;
import java.security.Key;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.logging.Logger;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.TextOutputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
/**
* The <b>-keyclone</b> keytool command handler is used to clone an existing
* key store entry associated with a designated alias, with its private key and
* chain of certificates.
* <p>
* Possible options for this command are:
* <p>
* <dl>
* <dt>-alias ALIAS</dt>
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
* Certificate</i>, in a key store is uniquely identified by a user-defined
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
* when referring to an entry in the key store. Unless specified otherwise,
* a default value of <code>mykey</code> shall be used when this option is
* omitted from the command line.
* <p></dd>
*
* <dt>-dest ALIAS</dt>
* <dd>Use this option to specify the new <i>Alias</i> which will be used
* to identify the cloned copy of the <i>Key Entry</i>.
* <p></dd>
*
* <dt>-keypass PASSWORD</dt>
* <dd>Use this option to specify the password which the tool will use to
* unlock the <i>Key Entry</i> associated with the designated <i>Alias</i>.
* <p>
* If this option is omitted, the tool will first attempt to unlock the
* <i>Key Entry</i> using the same password protecting the key store. If
* this fails, you will then be prompted to provide a password.
* <p></dd>
*
* <dt>-new PASSWORD</dt>
* <dd>Use this option to specify the password protecting the private key
* material of the newly cloned copy of the <i>Key Entry</i>.
* <p></dd>
*
* <dt>-storetype STORE_TYP}</dt>
* <dd>Use this option to specify the type of the key store to use. The
* default value, if this option is omitted, is that of the property
* <code>keystore.type</code> in the security properties file, which is
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
* static method.
* <p></dd>
*
* <dt>-keystore URL</dt>
* <dd>Use this option to specify the location of the key store to use.
* The default value is a file {@link java.net.URL} referencing the file
* named <code>.keystore</code> located in the path returned by the call to
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
* as argument.
* <p>
* If a URL was specified, but was found to be malformed --e.g. missing
* protocol element-- the tool will attempt to use the URL value as a file-
* name (with absolute or relative path-name) of a key store --as if the
* protocol was <code>file:</code>.
* <p></dd>
*
* <dt>-storepass PASSWORD</dt>
* <dd>Use this option to specify the password protecting the key store. If
* this option is omitted from the command line, you will be prompted to
* provide a password.
* <p></dd>
*
* <dt>-provider PROVIDER_CLASS_NAME</dt>
* <dd>A fully qualified class name of a Security Provider to add to the
* current list of Security Providers already installed in the JVM in-use.
* If a provider class is specified with this option, and was successfully
* added to the runtime --i.e. it was not already installed-- then the tool
* will attempt to removed this Security Provider before exiting.
* <p></dd>
*
* <dt>-v</dt>
* <dd>Use this option to enable more verbose output.</dd>
* </dl>
*/
class KeyCloneCmd extends Command
{
private static final Logger log = Logger.getLogger(KeyCloneCmd.class.getName());
private String _alias;
private String _destAlias;
private String _password;
private String _newPassword;
private String _ksType;
private String _ksURL;
private String _ksPassword;
private String _providerClassName;
private String destinationAlias;
private char[] newKeyPasswordChars;
// default 0-arguments constructor
// public setters -----------------------------------------------------------
/** @param alias the existing alias to use. */
public void setAlias(String alias)
{
this._alias = alias;
}
/** @param alias the new alias to use. */
public void setDest(String alias)
{
this._destAlias = alias;
}
/** @param password the existing (private) key password to use. */
public void setKeypass(String password)
{
this._password = password;
}
/** @param password the new (private) key password to use. */
public void setNew(String password)
{
this._newPassword = password;
}
/** @param type the key-store type to use. */
public void setStoretype(String type)
{
this._ksType = type;
}
/** @param url the key-store URL to use. */
public void setKeystore(String url)
{
this._ksURL = url;
}
/** @param password the key-store password to use. */
public void setStorepass(String password)
{
this._ksPassword = password;
}
/** @param className a security provider fully qualified class name to use. */
public void setProvider(String className)
{
this._providerClassName = className;
}
// life-cycle methods -------------------------------------------------------
int processArgs(String[] args, int i)
{
int limit = args.length;
String opt;
while (++i < limit)
{
opt = args[i];
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
if (opt == null || opt.length() == 0)
continue;
if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
_alias = args[++i];
else if ("-dest".equals(opt)) // -dest ALIAS //$NON-NLS-1$
_destAlias = args[++i];
else if ("-keypass".equals(opt)) // -keypass PASSWORD //$NON-NLS-1$
_password = args[++i];
else if ("-new".equals(opt)) // -new PASSWORD //$NON-NLS-1$
_newPassword = args[++i];
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
_ksType = args[++i];
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
_ksURL = args[++i];
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
_ksPassword = args[++i];
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
_providerClassName = args[++i];
else if ("-v".equals(opt)) //$NON-NLS-1$
verbose = true;
else
break;
}
return i;
}
void setup() throws Exception
{
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
setAliasParam(_alias);
setKeyPasswordNoPrompt(_password);
setDestinationAlias(_destAlias);
// setNewKeyPassword(_newPassword);
log.finer("-keyclone handler will use the following options:"); //$NON-NLS-1$
log.finer(" -alias=" + alias); //$NON-NLS-1$
log.finer(" -dest=" + destinationAlias); //$NON-NLS-1$
log.finer(" -keypass=" + _password); //$NON-NLS-1$
log.finer(" -new=" + _newPassword); //$NON-NLS-1$
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
log.finer(" -provider=" + provider); //$NON-NLS-1$
log.finer(" -v=" + verbose); //$NON-NLS-1$
}
void start() throws KeyStoreException, NoSuchAlgorithmException, IOException,
UnsupportedCallbackException, UnrecoverableKeyException,
CertificateException
{
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
if (store.containsAlias(destinationAlias))
throw new SecurityException(Messages.getString("KeyCloneCmd.23")); //$NON-NLS-1$
Key privateKey = getAliasPrivateKey();
setNewKeyPassword(_newPassword);
Certificate[] chain = store.getCertificateChain(alias);
store.setKeyEntry(destinationAlias, privateKey, newKeyPasswordChars, chain);
saveKeyStore();
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
}
// own methods --------------------------------------------------------------
private void setDestinationAlias(String name) throws IOException,
UnsupportedCallbackException
{
if (name == null || name.trim().length() == 0) // ask user to provide one
{
NameCallback ncb = new NameCallback(Messages.getString("KeyCloneCmd.26")); //$NON-NLS-1$
getCallbackHandler().handle(new Callback[] { ncb });
name = ncb.getName();
if (name == null || name.trim().length() == 0)
throw new IllegalArgumentException(Messages.getString("KeyCloneCmd.27")); //$NON-NLS-1$
}
destinationAlias = name.trim();
}
private void setNewKeyPassword(String password) throws IOException,
UnsupportedCallbackException
{
if (password != null) // ask user to provide one
newKeyPasswordChars = password.toCharArray();
else
{
boolean ok = false;
Callback[] prompts = new Callback[1];
Callback[] errors = new Callback[1];
for (int i = 0; i < 3; i++)
if (prompt4NewPassword(getCallbackHandler(), prompts, errors))
{
ok = true;
break;
}
if (! ok)
throw new SecurityException(Messages.getString("StorePasswdCmd.19")); //$NON-NLS-1$
}
}
private boolean prompt4NewPassword(CallbackHandler handler,
Callback[] prompts, Callback[] errors)
throws IOException, UnsupportedCallbackException
{
String p = Messages.getFormattedString("KeyCloneCmd.28", //$NON-NLS-1$
new String[] { destinationAlias,
String.valueOf(keyPasswordChars) });
PasswordCallback pcb = new PasswordCallback(p, false);
prompts[0] = pcb;
handler.handle(prompts);
char[] pwd1 = pcb.getPassword();
pcb.clearPassword();
if (pwd1 == null || pwd1.length == 0)
{
newKeyPasswordChars = (char[]) keyPasswordChars.clone();
return true;
}
if (pwd1.length < 6)
{
errors[0] = new TextOutputCallback(TextOutputCallback.ERROR,
Messages.getString("StorePasswdCmd.21")); //$NON-NLS-1$
handler.handle(errors);
return false;
}
newKeyPasswordChars = pwd1;
return true;
}
}
@@ -0,0 +1,339 @@
/* KeyPasswdCmd.java -- The keypasswd command handler of the keytool
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.keytool;
import gnu.classpath.SystemProperties;
import java.io.IOException;
import java.security.Key;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.util.Arrays;
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.TextOutputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
/**
* The <b>-keypasswd</b> keytool command handler is used to change the password
* protecting the private key associated to a designated alias.
* <p>
* Possible options for this command are:
* <p>
* <dl>
* <dt>-alias ALIAS</dt>
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
* Certificate</i>, in a key store is uniquely identified by a user-defined
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
* when referring to an entry in the key store. Unless specified otherwise,
* a default value of <code>mykey</code> shall be used when this option is
* omitted from the command line.
* <p></dd>
*
* <dt>-keypass PASSWORD</dt>
* <dd>Use this option to specify the password which the tool will use to
* unlock the <i>Key Entry</i> associated with the designated <i>Alias</i>.
* <p>
* If this option is omitted, the tool will first attempt to unlock the
* <i>Key Entry</i> using the same password protecting the key store. If
* this fails, you will then be prompted to provide a password.
* <p></dd>
*
* <dt>-new PASSWORD</dt>
* <dd>The new, and different, password which will be used to protect the
* private key material of the designated Key Entry.
* <p></dd>
*
* <dt>-storetype STORE_TYP}</dt>
* <dd>Use this option to specify the type of the key store to use. The
* default value, if this option is omitted, is that of the property
* <code>keystore.type</code> in the security properties file, which is
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
* static method.
* <p></dd>
*
* <dt>-keystore URL</dt>
* <dd>Use this option to specify the location of the key store to use.
* The default value is a file {@link java.net.URL} referencing the file
* named <code>.keystore</code> located in the path returned by the call to
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
* as argument.
* <p>
* If a URL was specified, but was found to be malformed --e.g. missing
* protocol element-- the tool will attempt to use the URL value as a file-
* name (with absolute or relative path-name) of a key store --as if the
* protocol was <code>file:</code>.
* <p></dd>
*
* <dt>-storepass PASSWORD</dt>
* <dd>Use this option to specify the password protecting the key store. If
* this option is omitted from the command line, you will be prompted to
* provide a password.
* <p></dd>
*
* <dt>-provider PROVIDER_CLASS_NAME</dt>
* <dd>A fully qualified class name of a Security Provider to add to the
* current list of Security Providers already installed in the JVM in-use.
* If a provider class is specified with this option, and was successfully
* added to the runtime --i.e. it was not already installed-- then the tool
* will attempt to removed this Security Provider before exiting.
* <p></dd>
*
* <dt>-v</dt>
* <dd>Use this option to enable more verbose output.</dd>
* </dl>
*/
class KeyPasswdCmd extends Command
{
private static final Logger log = Logger.getLogger(KeyPasswdCmd.class.getName());
private String _alias;
private String _password;
private String _newPassword;
private String _ksType;
private String _ksURL;
private String _ksPassword;
private String _providerClassName;
private char[] newPasswordChars;
// default 0-arguments constructor
// public setters -----------------------------------------------------------
/** @param alias the alias to use. */
public void setAlias(String alias)
{
this._alias = alias;
}
/** @param password the existing (private) key password to use. */
public void setKeypass(String password)
{
this._password = password;
}
/** @param password the new (private) key password to use. */
public void setNew(String password)
{
this._newPassword = password;
}
/** @param type the key-store type to use. */
public void setStoretype(String type)
{
this._ksType = type;
}
/** @param url the key-store URL to use. */
public void setKeystore(String url)
{
this._ksURL = url;
}
/** @param password the key-store password to use. */
public void setStorepass(String password)
{
this._ksPassword = password;
}
/** @param className a security provider fully qualified class name to use. */
public void setProvider(String className)
{
this._providerClassName = className;
}
// life-cycle methods -------------------------------------------------------
int processArgs(String[] args, int i)
{
int limit = args.length;
String opt;
while (++i < limit)
{
opt = args[i];
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
if (opt == null || opt.length() == 0)
continue;
if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
_alias = args[++i];
else if ("-keypass".equals(opt)) // -keypass PASSWORD //$NON-NLS-1$
_password = args[++i];
else if ("-new".equals(opt)) // -new PASSWORD //$NON-NLS-1$
_newPassword = args[++i];
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
_ksType = args[++i];
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
_ksURL = args[++i];
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
_ksPassword = args[++i];
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
_providerClassName = args[++i];
else if ("-v".equals(opt)) //$NON-NLS-1$
verbose = true;
else
break;
}
return i;
}
void setup() throws Exception
{
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
setAliasParam(_alias);
setKeyPasswordNoPrompt(_password);
// setNewKeyPassword(_newPassword);
log.finer("-keypasswd handler will use the following options:"); //$NON-NLS-1$
log.finer(" -alias=" + alias); //$NON-NLS-1$
log.finer(" -keypass=" + _password); //$NON-NLS-1$
log.finer(" -new=" + _newPassword); //$NON-NLS-1$
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
log.finer(" -provider=" + provider); //$NON-NLS-1$
log.finer(" -v=" + verbose); //$NON-NLS-1$
}
void start() throws KeyStoreException, NoSuchAlgorithmException, IOException,
UnsupportedCallbackException, UnrecoverableKeyException,
CertificateException
{
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
// 1. get the key entry and certificate chain associated to alias
Key privateKey = getAliasPrivateKey();
Certificate[] chain = store.getCertificateChain(alias);
// 2. replace the old entry
setNewKeyPassword(_newPassword);
store.setKeyEntry(alias, privateKey, newPasswordChars, chain);
// 3. persist the key store
saveKeyStore();
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
}
// own methods --------------------------------------------------------------
/**
* Set the new password to use for protecting Alias's private key.
*
* @param password the new key password. if <code>null</code> prompt the
* user to provide one. When prompting, the password is entered twice
* and compared for a match.
* @throws IOException if an I/O related exception occurs during the process.
* @throws UnsupportedCallbackException if no implementation of a password
* callback handler was found.
*/
private void setNewKeyPassword(String password) throws IOException,
UnsupportedCallbackException
{
if (password != null)
newPasswordChars = password.toCharArray();
else
{
boolean ok = false;
Callback[] prompts = new Callback[1];
Callback[] errors = new Callback[1];
for (int i = 0; i < 3; i++)
if (prompt4NewPassword(getCallbackHandler(), prompts, errors))
{
ok = true;
break;
}
if (! ok)
throw new SecurityException(Messages.getString("StorePasswdCmd.19")); //$NON-NLS-1$
}
}
private boolean prompt4NewPassword(CallbackHandler handler,
Callback[] prompts, Callback[] errors)
throws IOException, UnsupportedCallbackException
{
// prompt user (1st time) to provide one
String p = Messages.getFormattedString("KeyPasswdCmd.24", alias); //$NON-NLS-1$
PasswordCallback pcb = new PasswordCallback(p, false);
prompts[0] = pcb;
handler.handle(prompts);
char[] pwd1 = pcb.getPassword();
pcb.clearPassword();
String ls = SystemProperties.getProperty("line.separator"); //$NON-NLS-1$
if (pwd1 == null || pwd1.length < 6)
{
String m = Messages.getString("StorePasswdCmd.21") + ls; //$NON-NLS-1$
errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
handler.handle(errors);
return false;
}
if (Arrays.equals(keyPasswordChars, pwd1))
{
String m = Messages.getString("StorePasswdCmd.22") + ls; //$NON-NLS-1$
errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
handler.handle(errors);
return false;
}
// prompt user (2nd time) for confirmation
p = Messages.getFormattedString("KeyPasswdCmd.28", alias); //$NON-NLS-1$
pcb = new PasswordCallback(p, false);
prompts[0] = pcb;
handler.handle(prompts);
char[] pwd2 = pcb.getPassword();
pcb.clearPassword();
if (! Arrays.equals(pwd1, pwd2))
{
String m = Messages.getString("StorePasswdCmd.24") + ls; //$NON-NLS-1$
errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
handler.handle(errors);
return false;
}
newPasswordChars = pwd2;
return true;
}
}
@@ -0,0 +1,380 @@
/* ListCmd.java -- The list command handler of the keytool
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.keytool;
import gnu.java.security.util.Base64;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.KeyStoreException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.util.Enumeration;
import java.util.logging.Logger;
/**
* The <b>-list</b> keytool command handler is used to output one or all key
* store entries.
* <p>
* Possible options for this command are:
* <p>
* <dl>
* <dt>-alias ALIAS</dt>
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
* Certificate</i>, in a key store is uniquely identified by a user-defined
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
* when referring to an entry in the key store. Unless specified otherwise,
* a default value of <code>mykey</code> shall be used when this option is
* omitted from the command line.
* <p></dd>
*
* <dt>-storetype STORE_TYP}</dt>
* <dd>Use this option to specify the type of the key store to use. The
* default value, if this option is omitted, is that of the property
* <code>keystore.type</code> in the security properties file, which is
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
* static method.
* <p></dd>
*
* <dt>-keystore URL</dt>
* <dd>Use this option to specify the location of the key store to use.
* The default value is a file {@link java.net.URL} referencing the file
* named <code>.keystore</code> located in the path returned by the call to
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
* as argument.
* <p>
* If a URL was specified, but was found to be malformed --e.g. missing
* protocol element-- the tool will attempt to use the URL value as a file-
* name (with absolute or relative path-name) of a key store --as if the
* protocol was <code>file:</code>.
* <p></dd>
*
* <dt>-storepass PASSWORD</dt>
* <dd>Use this option to specify the password protecting the key store. If
* this option is omitted from the command line, you will be prompted to
* provide a password.
* <p></dd>
*
* <dt>-provider PROVIDER_CLASS_NAME</dt>
* <dd>A fully qualified class name of a Security Provider to add to the
* current list of Security Providers already installed in the JVM in-use.
* If a provider class is specified with this option, and was successfully
* added to the runtime --i.e. it was not already installed-- then the tool
* will attempt to removed this Security Provider before exiting.
* <p></dd>
*
* <dt>-rfc</dt>
* <dd>Use RFC-1421 specifications when encoding the output.
* <p></dd>
*
* <dt>-v</dt>
* <dd>Output the certificate in human-readable format. If both this option
* and the <code>-rfc</code> option are detected on the command line, the
* tool will opt for the human-readable form and will not abort the
* command.</dd>
* </dl>
*/
class ListCmd extends Command
{
private static final Logger log = Logger.getLogger(ListCmd.class.getName());
private String _alias;
private String _ksType;
private String _ksURL;
private String _ksPassword;
private String _providerClassName;
private boolean rfc;
private boolean all;
// default 0-arguments constructor
// public setters -----------------------------------------------------------
/** @param alias the alias to use. */
public void setAlias(String alias)
{
this._alias = alias;
}
/** @param type the key-store type to use. */
public void setStoretype(String type)
{
this._ksType = type;
}
/** @param url the key-store URL to use. */
public void setKeystore(String url)
{
this._ksURL = url;
}
/** @param password the key-store password to use. */
public void setStorepass(String password)
{
this._ksPassword = password;
}
/** @param className a security provider fully qualified class name to use. */
public void setProvider(String className)
{
this._providerClassName = className;
}
/**
* @param flag whether to use, or not, RFC-1421 format when listing the
* certificate(s).
*/
public void setRfc(String flag)
{
this.rfc = Boolean.valueOf(flag).booleanValue();
}
// life-cycle methods -------------------------------------------------------
int processArgs(String[] args, int i)
{
int limit = args.length;
String opt;
while (++i < limit)
{
opt = args[i];
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
if (opt == null || opt.length() == 0)
continue;
if ("-alias".equals(opt)) // -alias ALIAS //$NON-NLS-1$
_alias = args[++i];
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
_ksType = args[++i];
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
_ksURL = args[++i];
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
_ksPassword = args[++i];
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
_providerClassName = args[++i];
else if ("-v".equals(opt)) //$NON-NLS-1$
verbose = true;
else if ("-rfc".equals(opt)) //$NON-NLS-1$
rfc = true;
else
break;
}
all = _alias == null;
return i;
}
void setup() throws Exception
{
setOutputStreamParam(null); // use stdout
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
if (! all)
setAliasParam(_alias);
if (verbose & rfc)
{
log.warning("Both -v and -rfc options were found on the command line. " //$NON-NLS-1$
+ "Only the former will be considered"); //$NON-NLS-1$
rfc = false;
}
log.finer("-list handler will use the following options:"); //$NON-NLS-1$
log.finer(" -alias=" + alias); //$NON-NLS-1$
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
log.finer(" -provider=" + provider); //$NON-NLS-1$
log.finer(" -v=" + verbose); //$NON-NLS-1$
log.finer(" -rfc=" + rfc); //$NON-NLS-1$
}
void start() throws KeyStoreException, CertificateEncodingException,
IOException
{
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
PrintWriter writer = new PrintWriter(outStream, true);
writer.println(Messages.getFormattedString("ListCmd.21", store.getType())); //$NON-NLS-1$
writer.println(Messages.getFormattedString("ListCmd.22", //$NON-NLS-1$
store.getProvider().getName()));
if (all)
{
log.finest("About to list all aliases in key store..."); //$NON-NLS-1$
writer.println();
writer.println(Messages.getFormattedString("ListCmd.24", //$NON-NLS-1$
Integer.valueOf(store.size())));
for (Enumeration e = store.aliases(); e.hasMoreElements(); )
{
String anAlias = (String) e.nextElement();
if (anAlias != null)
list1Alias(anAlias, writer);
}
}
else
list1Alias(alias, writer);
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
}
// own methods --------------------------------------------------------------
/**
* Prints the certificate(s) associated with the designated alias.
*
* @param anAlias a non-null string denoting an alias in the key-store.
* @param writer where to print.
* @throws KeyStoreException if an exception occurs while obtaining the
* certificate associated to the designated alias.
* @throws CertificateEncodingException if an exception occurs while obtaining
* the DER encoded form of the certificate.
* @throws IOException if an I/O related exception occurs during the process.
*/
private void list1Alias(String anAlias, PrintWriter writer)
throws KeyStoreException, CertificateEncodingException, IOException
{
log.entering(this.getClass().getName(), "list1Alias", anAlias); //$NON-NLS-1$
writer.println();
writer.println(Messages.getFormattedString("ListCmd.30", anAlias)); //$NON-NLS-1$
writer.println(Messages.getFormattedString("ListCmd.31", store.getCreationDate(anAlias))); //$NON-NLS-1$
if (store.isCertificateEntry(anAlias))
{
writer.println(Messages.getString("ListCmd.32")); //$NON-NLS-1$
Certificate certificate = store.getCertificate(anAlias);
print1Certificate(certificate, writer);
}
else if (store.isKeyEntry(anAlias))
{
writer.println(Messages.getString("ListCmd.33")); //$NON-NLS-1$
Certificate[] chain = store.getCertificateChain(anAlias);
print1Chain(chain, writer);
}
else
throw new IllegalArgumentException(Messages.getFormattedString("ListCmd.34", //$NON-NLS-1$
anAlias));
log.exiting(this.getClass().getName(), "list1Alias"); //$NON-NLS-1$
}
/**
* Prints the designated certificate chain, or a fingerprint of the first
* certificate (bottom) in the chain, depending on the values of the flags
* <code>v</code> (for verbose) and <code>rfc</code>.
* <p>
* If both flags are <code>false</code>, only the fingerprint is generated,
* otherwise, if the <code>v</code> flag is set, then a human readable output
* is generated. If <code>rfc</code> is set, then an RFC-1421 like output
* is generated.
* <p>Note that both <code>v</code> and <code>rfc</code> cannot both be
* <code>true</code> at the same time.
*
* @param chain the certificate chain to process.
* @param writer where to print.
* @throws CertificateEncodingException if an exception occurs while obtaining
* the DER encoded form of the certificate.
*/
private void print1Chain(Certificate[] chain, PrintWriter writer)
throws CertificateEncodingException
{
if (!verbose && !rfc)
fingerprint(chain[0], writer);
else
{
int limit = chain.length;
writer.println(Messages.getFormattedString("ListCmd.38", //$NON-NLS-1$
Integer.valueOf(limit)));
writer.println(Messages.getString("ListCmd.39")); //$NON-NLS-1$
print1Certificate(chain[0], writer);
for (int i = 1; i < limit; i++)
{
writer.println();
writer.println(Messages.getFormattedString("ListCmd.40", //$NON-NLS-1$
Integer.valueOf(i + 1)));
print1Certificate(chain[i], writer);
}
writer.println();
writer.println(Messages.getString("ListCmd.42")); //$NON-NLS-1$
}
}
/**
* Prints the designated certificate, or its fingerprint, depending on the
* values of the flags <code>v</code> (for verbose) and <code>rfc</code>.
* <p>
* If both flags are <code>false</code>, only a fingerprint is generated,
* otherwise, if the <code>v</code> flag is set, then a human readable output
* is generated. If <code>rfc</code> is set, then an RFC-1421 like output
* is generated.
* <p>Note that both <code>v</code> and <code>rfc</code> cannot both be
* <code>true</code> at the same time.
*
* @param certificate the certificate to process.
* @param writer where to print.
* @throws CertificateEncodingException if an exception occurs while obtaining
* the DER encoded form of the certificate.
*/
private void print1Certificate(Certificate certificate, PrintWriter writer)
throws CertificateEncodingException
{
if (verbose)
printVerbose(certificate, writer);
else if (rfc)
printRFC1421(certificate, writer);
else
fingerprint(certificate, writer);
}
private void printRFC1421(Certificate certificate, PrintWriter writer)
throws CertificateEncodingException
{
byte[] derBytes = certificate.getEncoded();
String encoded = Base64.encode(derBytes, 0, derBytes.length, true);
writer.println(Messages.getString("ListCmd.43")); //$NON-NLS-1$
writer.println(encoded);
writer.println(Messages.getString("ListCmd.44")); //$NON-NLS-1$
}
private void fingerprint(Certificate certificate, PrintWriter writer)
throws CertificateEncodingException
{
byte[] derBytes = certificate.getEncoded();
String fingerPrint = digestWithMD5(derBytes);
writer.println(Messages.getFormattedString("ListCmd.45", fingerPrint)); //$NON-NLS-1$
}
}
@@ -0,0 +1,219 @@
/* Main.java -- Implementation of the keytool security tool
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.keytool;
import gnu.classpath.tools.HelpPrinter;
import gnu.classpath.tools.common.ProviderUtil;
import gnu.java.security.Registry;
import gnu.javax.crypto.jce.GnuCrypto;
import gnu.javax.security.auth.callback.GnuCallbacks;
import java.util.logging.Logger;
/**
* The GNU Classpath implementation of the keytool security tool.
* <p>
* Except for the <code>-identitydb</code> command, available for importing
* JDK 1.1 <i>identities</i> into a key store, 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
{
private static final Logger log = Logger.getLogger(Main.class.getName());
/** The relative file path to the command tool's help text. */
private static final String HELP_PATH = "keytool/keytool.txt"; //$NON-NLS-1$
/** The Preferences key name for the last issued certificate serial nbr. */
static final String LAST_SERIAL_NUMBER = "lastSerialNumber"; //$NON-NLS-1$
/** Constant denoting the X.509 certificate type. */
static final String X_509 = "X.509"; //$NON-NLS-1$
/** Whether we have already printed the help text or not. */
private boolean helpPrinted;
/** The new position of GnuCRYPTO provider if it is not already installed. */
private int gnuCryptoProviderNdx = -2;
/** The new position of GNU Callbacks provider if it is not already installed. */
private int gnuCallbacksNdx = -2;
private Main()
{
super();
}
public static final void main(String[] args)
{
log.entering(Main.class.getName(), "main", args); //$NON-NLS-1$
Main tool = new Main();
try
{
tool.setup();
tool.start(args);
}
catch (SecurityException x)
{
log.throwing(Main.class.getName(), "main", x); //$NON-NLS-1$
System.err.println(Messages.getString("Main.6") + x.getMessage()); //$NON-NLS-1$
}
catch (Exception x)
{
log.throwing(Main.class.getName(), "main", x); //$NON-NLS-1$
System.err.println(Messages.getString("Main.8") + x); //$NON-NLS-1$
}
finally
{
tool.teardown();
}
log.exiting(Main.class.getName(), "main"); //$NON-NLS-1$
// System.exit(0);
}
// helper methods -----------------------------------------------------------
private void start(String[] args) throws Exception
{
log.entering(this.getClass().getName(), "start", args); //$NON-NLS-1$
if (args == null)
args = new String[0];
int limit = args.length;
log.finest("args.length=" + limit); //$NON-NLS-1$
int i = 0;
String opt;
Command cmd;
while (i < limit)
{
opt = args[i];
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
if (opt == null || opt.length() == 0)
continue;
cmd = null;
if ("-genkey".equals(opt)) //$NON-NLS-1$
cmd = new GenKeyCmd();
else if ("-import".equals(opt)) //$NON-NLS-1$
cmd = new ImportCmd();
else if ("-selfcert".equals(opt)) //$NON-NLS-1$
cmd = new SelfCertCmd();
else if ("-identitydb".equals(opt)) //$NON-NLS-1$
cmd = new IdentityDBCmd();
else if ("-certreq".equals(opt)) //$NON-NLS-1$
cmd = new CertReqCmd();
else if ("-export".equals(opt)) //$NON-NLS-1$
cmd = new ExportCmd();
else if ("-list".equals(opt)) //$NON-NLS-1$
cmd = new ListCmd();
else if ("-printcert".equals(opt)) //$NON-NLS-1$
cmd = new PrintCertCmd();
else if ("-keyclone".equals(opt)) //$NON-NLS-1$
cmd = new KeyCloneCmd();
else if ("-storepasswd".equals(opt)) //$NON-NLS-1$
cmd = new StorePasswdCmd();
else if ("-keypasswd".equals(opt)) //$NON-NLS-1$
cmd = new KeyPasswdCmd();
else if ("-delete".equals(opt)) //$NON-NLS-1$
cmd = new DeleteCmd();
else if ("-help".equals(opt)) //$NON-NLS-1$
{
printHelp();
i++;
}
else
{
log.fine("Unknown command [" + opt + "] at index #" + i //$NON-NLS-1$ //$NON-NLS-2$
+ ". Arguments from that token onward will be ignored"); //$NON-NLS-1$
break;
}
if (cmd != null)
{
i = cmd.processArgs(args, i);
cmd.doCommand();
}
}
// the -help command is the default; i.e.
// keytool
// is equivalent to:
// keytool -help
if (i == 0)
printHelp();
if (i < limit) // more options than needed
log.fine("Last recognized argument is assumed at index #" + (i - 1) //$NON-NLS-1$
+ ". Remaining arguments (" + args[i] + "...) will be ignored"); //$NON-NLS-1$ //$NON-NLS-2$
log.exiting(this.getClass().getName(), "start"); //$NON-NLS-1$
}
private void setup()
{
log.entering(this.getClass().getName(), "setup"); //$NON-NLS-1$
gnuCryptoProviderNdx = ProviderUtil.addProvider(new GnuCrypto());
gnuCallbacksNdx = ProviderUtil.addProvider(new GnuCallbacks());
log.exiting(this.getClass().getName(), "setup"); //$NON-NLS-1$
}
private void teardown()
{
log.entering(this.getClass().getName(), "teardown"); //$NON-NLS-1$
// if we added our own providers remove them
if (gnuCryptoProviderNdx > 0)
ProviderUtil.removeProvider(Registry.GNU_CRYPTO);
if (gnuCallbacksNdx > 0)
ProviderUtil.removeProvider("GNU-CALLBACKS"); //$NON-NLS-1$
log.exiting(this.getClass().getName(), "teardown"); //$NON-NLS-1$
}
private void printHelp()
{
if (helpPrinted)
return;
HelpPrinter.printHelp(HELP_PATH);
helpPrinted = true;
}
}
@@ -0,0 +1,115 @@
/* Messages.java -- I18N related helper class
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.keytool;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.logging.Logger;
/**
* An initially generated Eclipse helper class to ease the use of localized
* messages.
* <p>
* Enriched to handle localized message formats.
*/
class Messages
{
private static final Logger log = Logger.getLogger(Messages.class.getName());
private static final String BUNDLE_NAME = "gnu.classpath.tools.keytool.MessageBundle"; //$NON-NLS-1$
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
private static final Map CACHED_FORMATS = new HashMap(5);
private Messages()
{
super();
}
public static String getString(String key)
{
try
{
return RESOURCE_BUNDLE.getString(key);
}
catch (MissingResourceException e)
{
return constructMessage(key, null);
}
}
public static String getFormattedString(String key, Object args)
{
MessageFormat mf = (MessageFormat) CACHED_FORMATS.get(key);
if (mf == null)
{
String formatString = getString(key);
if (formatString.startsWith("!"))
return constructMessage(key, args);
mf = new MessageFormat(formatString);
CACHED_FORMATS.put(key, mf);
}
// if the argument is not an array, then build one consisiting of the
// sole argument before passing it to the format() method
try
{
if (args instanceof Object[])
return mf.format(args);
return mf.format(new Object[] { args });
}
catch (IllegalArgumentException x)
{
log.fine("Exception while rendering a message format keyed by ["
+ key + "]: " + mf.toPattern());
return constructMessage(mf.toPattern(), args);
}
}
private static final String constructMessage(String m, Object args)
{
if (args == null)
return '!' + m + '!';
return '!' + m + '!' + String.valueOf(args) + '!';
}
}
@@ -0,0 +1,123 @@
/* PrintCertCmd.java -- The printcert command handler of the keytool
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.keytool;
import java.io.PrintWriter;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.logging.Logger;
/**
* The <b>-printcert</b> keytool command handler is used to read a certificate
* from a designated file, and print its contents in a human-readable format.
* <p>
* Possible options for this command are:
* <p>
* <dl>
* <dt>-file FILE_NAME</dt>
* <dd>The fully qualified path of the file to read the certificate from.
* If this option is omitted, the tool will process STDIN.
* <p></dd>
*
* <dt>-v</dt>
* <dd>Use this option to enable more verbose output.</dd>
* </dl>
*/
class PrintCertCmd extends Command
{
private static final Logger log = Logger.getLogger(PrintCertCmd.class.getName());
private String _certFileName;
// default 0-arguments constructor
// public setters -----------------------------------------------------------
/** @param pathName the fully qualified path name of the file to process. */
public void setFile(String pathName)
{
this._certFileName = pathName;
}
// life-cycle methods -------------------------------------------------------
int processArgs(String[] args, int i)
{
int limit = args.length;
String opt;
while (++i < limit)
{
opt = args[i];
log.finest("args[" + i + "]=" + opt);
if (opt == null || opt.length() == 0)
continue;
if ("-file".equals(opt)) // -file FILE_NAME
_certFileName = args[++i];
else if ("-v".equals(opt))
verbose = true;
else
break;
}
return i;
}
void setup() throws Exception
{
setInputStreamParam(_certFileName);
log.finer("-printcert handler will use the following options:");
log.finer(" -file=" + _certFileName);
log.finer(" -v=" + verbose);
}
void start() throws CertificateException
{
log.entering(getClass().getName(), "start");
CertificateFactory x509Factory = CertificateFactory.getInstance(Main.X_509);
Certificate certificate = x509Factory.generateCertificate(inStream);
PrintWriter writer = new PrintWriter(System.out, true);
writer.println();
printVerbose(certificate, writer);
log.exiting(getClass().getName(), "start");
}
}
@@ -0,0 +1,371 @@
/* SelfCertCmd.java -- The selfcert command handler of the keytool
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.keytool;
import gnu.java.security.x509.X500DistinguishedName;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.logging.Logger;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.x500.X500Principal;
/**
* The <b>-selfcert</b> keytool command handler is used to generate a self-
* signed X.509 version 1 certificate using key store credentials stored under a
* designated alias.
* <p>
* Possible options for this command are:
* <p>
* <dl>
* <dt>-alias ALIAS</dt>
* <dd>Every entry, be it a <i>Key Entry</i> or a <i>Trusted
* Certificate</i>, in a key store is uniquely identified by a user-defined
* <i>Alias</i> string. Use this option to specify the <i>Alias</i> to use
* when referring to an entry in the key store. Unless specified otherwise,
* a default value of <code>mykey</code> shall be used when this option is
* omitted from the command line.
* <p></dd>
*
* <dt>-sigalg ALGORITHM</dt>
* <dd>The canonical name of the digital signature algorithm to use for
* signing the certificate. If this option is omitted, a default value will
* be chosen based on the type of the private key associated with the
* designated <i>Alias</i>. If the private key is a <code>DSA</code> one,
* the value for the signature algorithm will be <code>SHA1withDSA</code>.
* If on the other hand the private key is an <code>RSA</code> one, then
* the tool will use <code>MD5withRSA</code> as the signature algorithm.
* <p></dd>
*
* <dt>-dname NAME</dt>
* <dd>Use this option to specify the <i>Distinguished Name</i> of the
* newly generated self-signed certificate. If this option is omitted, the
* existing <i>Distinguished Name</i> of the base certificate in the chain
* associated with the designated <i>Alias</i> will be used instead.
* <p>
* The syntax of a valid value for this option MUST follow RFC-2253
* specifications. Namely the following components (with their accepted
* meaning) will be recognized. Note that the component name is case-
* insensitive:
* <dl>
* <dt>CN</dt>
* <dd>The Common Name; e.g. "host.domain.com"</dd>
*
* <dt>OU</dt>
* <dd>The Organizational Unit; e.g. "IT Department"</dd>
*
* <dt>O</dt>
* <dd>The Organization Name; e.g. "The Sample Company"</dd>
*
* <dt>L</dt>
* <dd>The Locality Name; e.g. "Sydney"</dd>
*
* <dt>ST</dt>
* <dd>The State Name; e.g. "New South Wales"</dd>
*
* <dt>C</dt>
* <dd>The 2-letter Country identifier; e.g. "AU"</dd>
* </dl>
* <p>
* When specified with a <code>-dname</code> option, each pair of component
* / value will be separated from the other with a comma. Each component
* and value pair MUST be separated by an equal sign. For example, the
* following is a valid DN value:
* <pre>
* CN=host.domain.com, O=The Sample Company, L=Sydney, ST=NSW, C=AU
* </pre>
* <p></dd>
*
* <dt>-validity DAY_COUNT</dt>
*
* <dt>-keypass PASSWORD</dt>
*
* <dt>-storetype STORE_TYP}</dt>
* <dd>Use this option to specify the type of the key store to use. The
* default value, if this option is omitted, is that of the property
* <code>keystore.type</code> in the security properties file, which is
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
* static method.
* <p></dd>
*
* <dt>-keystore URL</dt>
* <dd>Use this option to specify the location of the key store to use.
* The default value is a file {@link java.net.URL} referencing the file
* named <code>.keystore</code> located in the path returned by the call to
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
* as argument.
* <p>
* If a URL was specified, but was found to be malformed --e.g. missing
* protocol element-- the tool will attempt to use the URL value as a file-
* name (with absolute or relative path-name) of a key store --as if the
* protocol was <code>file:</code>.
* <p></dd>
*
* <dt>-storepass PASSWORD</dt>
* <dd>Use this option to specify the password protecting the key store. If
* this option is omitted from the command line, you will be prompted to
* provide a password.
* <p></dd>
*
* <dt>-provider PROVIDER_CLASS_NAME</dt>
* <dd>A fully qualified class name of a Security Provider to add to the
* current list of Security Providers already installed in the JVM in-use.
* If a provider class is specified with this option, and was successfully
* added to the runtime --i.e. it was not already installed-- then the tool
* will attempt to removed this Security Provider before exiting.
* <p></dd>
*
* <dt>-v</dt>
* <dd>Use this option to enable more verbose output.</dd>
* </dl>
*/
class SelfCertCmd extends Command
{
private static final Logger log = Logger.getLogger(SelfCertCmd.class.getName());
private String _alias;
private String _sigAlgorithm;
private String _dName;
private String _password;
private String _validityStr;
private String _ksType;
private String _ksURL;
private String _ksPassword;
private String _providerClassName;
private X500DistinguishedName distinguishedName;
private int validityInDays;
// default 0-arguments constructor
// public setters -----------------------------------------------------------
/** @param alias the alias to use. */
public void setAlias(String alias)
{
this._alias = alias;
}
/**
* @param algorithm the canonical name of the digital signature algorithm to
* use.
*/
public void setSigalg(String algorithm)
{
this._sigAlgorithm = algorithm;
}
/**
* @param name the distiniguished name of both the issuer and subject (since
* we are dealing with a self-signed certificate) to use.
*/
public void setDname(String name)
{
this._dName = name;
}
/**
* @param days the string representation of the number of days (a decimal,
* positive integer) to assign to the generated (self-signed)
* certificate.
*/
public void setValidity(String days)
{
this._validityStr = days;
}
/** @param password the (private) key password to use. */
public void setKeypass(String password)
{
this._password = password;
}
/** @param type the key-store type to use. */
public void setStoretype(String type)
{
this._ksType = type;
}
/** @param url the key-store URL to use. */
public void setKeystore(String url)
{
this._ksURL = url;
}
/** @param password the key-store password to use. */
public void setStorepass(String password)
{
this._ksPassword = password;
}
/** @param className a security provider fully qualified class name to use. */
public void setProvider(String className)
{
this._providerClassName = className;
}
// life-cycle methods -------------------------------------------------------
int processArgs(String[] args, int i)
{
int limit = args.length;
String opt;
while (++i < limit)
{
opt = args[i];
log.finest("args[" + i + "]=" + opt);
if (opt == null || opt.length() == 0)
continue;
if ("-alias".equals(opt)) // -alias ALIAS
_alias = args[++i];
else if ("-sigalg".equals(opt)) // -sigalg ALGORITHM
_sigAlgorithm = args[++i];
else if ("-dname".equals(opt)) // -dname NAME
_dName = args[++i];
else if ("-keypass".equals(opt)) // -keypass PASSWORD
_password = args[++i];
else if ("-validity".equals(opt)) // -validity DAY_COUNT
_validityStr = args[++i];
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE
_ksType = args[++i];
else if ("-keystore".equals(opt)) // -keystore URL
_ksURL = args[++i];
else if ("-storepass".equals(opt)) // -storepass PASSWORD
_ksPassword = args[++i];
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME
_providerClassName = args[++i];
else if ("-v".equals(opt))
verbose = true;
else
break;
}
return i;
}
void setup() throws Exception
{
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
setAliasParam(_alias);
setKeyPasswordNoPrompt(_password);
// setDName(_dName);
setValidityParam(_validityStr);
// setSignatureAlgorithm(_sigAlgorithm);
log.finer("-selfcert handler will use the following options:");
log.finer(" -alias=" + alias);
log.finer(" -sigalg=" + _sigAlgorithm);
log.finer(" -dname=" + _dName);
log.finer(" -keypass=" + _password);
log.finer(" -validity=" + validityInDays);
log.finer(" -storetype=" + storeType);
log.finer(" -keystore=" + storeURL);
log.finer(" -storepass=" + String.valueOf(storePasswordChars));
log.finer(" -provider=" + provider);
log.finer(" -v=" + verbose);
}
void start() throws KeyStoreException, NoSuchAlgorithmException,
UnrecoverableKeyException, IOException, UnsupportedCallbackException,
InvalidKeyException, SignatureException, CertificateException
{
log.entering(getClass().getName(), "start");
// 1. get the key entry and certificate chain associated to alias
Key privateKey = getAliasPrivateKey();
Certificate[] chain = store.getCertificateChain(alias);
// 2. if the user has not supplied a DN use one from the certificate chain
X509Certificate bottomCertificate = (X509Certificate) chain[0];
X500Principal defaultPrincipal = bottomCertificate.getIssuerX500Principal();
setDName(_dName, defaultPrincipal);
// 4. get alias's public key from certificate's SubjectPublicKeyInfo
PublicKey publicKey = bottomCertificate.getPublicKey();
// 5. issue the self-signed certificate
setSignatureAlgorithmParam(_sigAlgorithm, privateKey);
byte[] derBytes = getSelfSignedCertificate(distinguishedName,
publicKey,
(PrivateKey) privateKey);
CertificateFactory x509Factory = CertificateFactory.getInstance("X.509");
ByteArrayInputStream bais = new ByteArrayInputStream(derBytes);
Certificate certificate = x509Factory.generateCertificate(bais);
// 6. store it, w/ its private key, associating them to alias
chain = new Certificate[] { certificate };
store.setKeyEntry(alias, privateKey, keyPasswordChars, chain);
// 7. persist the key store
saveKeyStore();
log.exiting(getClass().getName(), "start");
}
// own methods --------------------------------------------------------------
private void setDName(String name, X500Principal defaultName)
{
if (name != null && name.trim().length() > 0)
name = name.trim();
else
{
// If dname is supplied at the command line, it is used as the X.500
// Distinguished Name for both the issuer and subject of the certificate.
// Otherwise, the X.500 Distinguished Name associated with alias (at the
// bottom of its existing certificate chain) is used.
name = defaultName.toString().trim();
}
distinguishedName = new X500DistinguishedName(name);
}
}
@@ -0,0 +1,275 @@
/* StorePasswdCmd.java -- The storepasswd command handler of the keytool
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.keytool;
import gnu.classpath.SystemProperties;
import java.io.IOException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Arrays;
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.TextOutputCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
/**
* The <b>-storepasswd</b> keytool command handler is used to change the
* password which protects the integrity of the key store.
* <p>
* Possible options for this command are:
* <p>
* <dl>
* <dt>-new PASSWORD</dt>
* <dd>The new, and different, password which will be used to protect the
* designated key store.
* <p></dd>
*
* <dt>-storetype STORE_TYP}</dt>
* <dd>Use this option to specify the type of the key store to use. The
* default value, if this option is omitted, is that of the property
* <code>keystore.type</code> in the security properties file, which is
* obtained by invoking the {@link java.security.KeyStore#getDefaultType()}
* static method.
* <p></dd>
*
* <dt>-keystore URL</dt>
* <dd>Use this option to specify the location of the key store to use.
* The default value is a file {@link java.net.URL} referencing the file
* named <code>.keystore</code> located in the path returned by the call to
* {@link java.lang.System#getProperty(String)} using <code>user.home</code>
* as argument.
* <p>
* If a URL was specified, but was found to be malformed --e.g. missing
* protocol element-- the tool will attempt to use the URL value as a file-
* name (with absolute or relative path-name) of a key store --as if the
* protocol was <code>file:</code>.
* <p></dd>
*
* <dt>-storepass PASSWORD</dt>
* <dd>Use this option to specify the password protecting the key store. If
* this option is omitted from the command line, you will be prompted to
* provide a password.
* <p></dd>
*
* <dt>-provider PROVIDER_CLASS_NAME</dt>
* <dd>A fully qualified class name of a Security Provider to add to the
* current list of Security Providers already installed in the JVM in-use.
* If a provider class is specified with this option, and was successfully
* added to the runtime --i.e. it was not already installed-- then the tool
* will attempt to removed this Security Provider before exiting.
* <p></dd>
*
* <dt>-v</dt>
* <dd>Use this option to enable more verbose output.</dd>
* </dl>
*/
class StorePasswdCmd extends Command
{
private static final Logger log = Logger.getLogger(StorePasswdCmd.class.getName());
private String _newPassword;
private String _ksType;
private String _ksURL;
private String _ksPassword;
private String _providerClassName;
private char[] newStorePasswordChars;
// default 0-arguments constructor
// public setters -----------------------------------------------------------
/** @param password the new key-store password to use. */
public void setNew(String password)
{
this._newPassword = password;
}
/** @param type the key-store type to use. */
public void setStoretype(String type)
{
this._ksType = type;
}
/** @param url the key-store URL to use. */
public void setKeystore(String url)
{
this._ksURL = url;
}
/** @param password the key-store password to use. */
public void setStorepass(String password)
{
this._ksPassword = password;
}
/** @param className a security provider fully qualified class name to use. */
public void setProvider(String className)
{
this._providerClassName = className;
}
// life-cycle methods -------------------------------------------------------
int processArgs(String[] args, int i)
{
int limit = args.length;
String opt;
while (++i < limit)
{
opt = args[i];
log.finest("args[" + i + "]=" + opt); //$NON-NLS-1$ //$NON-NLS-2$
if (opt == null || opt.length() == 0)
continue;
if ("-new".equals(opt)) // -new PASSWORD //$NON-NLS-1$
_newPassword = args[++i];
else if ("-storetype".equals(opt)) // -storetype STORE_TYPE //$NON-NLS-1$
_ksType = args[++i];
else if ("-keystore".equals(opt)) // -keystore URL //$NON-NLS-1$
_ksURL = args[++i];
else if ("-storepass".equals(opt)) // -storepass PASSWORD //$NON-NLS-1$
_ksPassword = args[++i];
else if ("-provider".equals(opt)) // -provider PROVIDER_CLASS_NAME //$NON-NLS-1$
_providerClassName = args[++i];
else if ("-v".equals(opt)) //$NON-NLS-1$
verbose = true;
else
break;
}
return i;
}
void setup() throws Exception
{
setKeyStoreParams(_providerClassName, _ksType, _ksPassword, _ksURL);
setNewKeystorePassword(_newPassword);
log.finer("-storepasswd handler will use the following options:"); //$NON-NLS-1$
log.finer(" -new=" + String.valueOf(newStorePasswordChars)); //$NON-NLS-1$
log.finer(" -storetype=" + storeType); //$NON-NLS-1$
log.finer(" -keystore=" + storeURL); //$NON-NLS-1$
log.finer(" -storepass=" + String.valueOf(storePasswordChars)); //$NON-NLS-1$
log.finer(" -provider=" + provider); //$NON-NLS-1$
log.finer(" -v=" + verbose); //$NON-NLS-1$
}
void start() throws KeyStoreException, NoSuchAlgorithmException,
CertificateException, IOException
{
log.entering(this.getClass().getName(), "start"); //$NON-NLS-1$
saveKeyStore(newStorePasswordChars);
log.exiting(getClass().getName(), "start"); //$NON-NLS-1$
}
// own methods --------------------------------------------------------------
protected void setNewKeystorePassword(String password) throws IOException,
UnsupportedCallbackException
{
if (password != null)
newStorePasswordChars = password.toCharArray();
else
{
boolean ok = false;
Callback[] prompts = new Callback[1];
Callback[] errors = new Callback[1];
for (int i = 0; i < 3; i++)
if (prompt4NewPassword(getCallbackHandler(), prompts, errors))
{
ok = true;
break;
}
if (! ok)
throw new SecurityException(Messages.getString("StorePasswdCmd.19")); //$NON-NLS-1$
}
}
private boolean prompt4NewPassword(CallbackHandler handler,
Callback[] prompts, Callback[] errors)
throws IOException, UnsupportedCallbackException
{
// prompt user (1st time) to provide one
String p = Messages.getString("StorePasswdCmd.20"); //$NON-NLS-1$
PasswordCallback pcb = new PasswordCallback(p, false);
prompts[0] = pcb;
handler.handle(prompts);
char[] pwd1 = pcb.getPassword();
pcb.clearPassword();
String ls = SystemProperties.getProperty("line.separator"); //$NON-NLS-1$
if (pwd1 == null || pwd1.length < 6)
{
String m = Messages.getString("StorePasswdCmd.21") + ls; //$NON-NLS-1$
errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
handler.handle(errors);
return false;
}
if (Arrays.equals(storePasswordChars, pwd1))
{
String m = Messages.getString("StorePasswdCmd.22") + ls; //$NON-NLS-1$
errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
handler.handle(errors);
return false;
}
// prompt user (2nd time) for confirmation
pcb = new PasswordCallback(Messages.getString("StorePasswdCmd.23"), false); //$NON-NLS-1$
prompts[0] = pcb;
handler.handle(prompts);
char[] pwd2 = pcb.getPassword();
pcb.clearPassword();
if (! Arrays.equals(pwd1, pwd2))
{
String m = Messages.getString("StorePasswdCmd.24") + ls; //$NON-NLS-1$
errors[0] = new TextOutputCallback(TextOutputCallback.ERROR, m);
handler.handle(errors);
return false;
}
newStorePasswordChars = pwd2;
return true;
}
}
@@ -0,0 +1,87 @@
/* PersistentBidiHasthable.java -- Constants for the persistent tables.
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.rmi;
import java.util.Timer;
import java.util.TimerTask;
/**
* The static fields, shared by the multiple classes, implementing the
* persistent work.
*
* @author Audrius Meskauskas (audriusa@bioinformatics.org)
*/
public interface Persistent
{
/**
* Sheduled termination task.
*/
static class ExitTask extends TimerTask
{
public void run()
{
System.exit(0);
}
}
/**
* The timer, sheduling all disk database update events, shared by all
* instances.
*/
static Timer timer = new Timer(true);
/**
* The longest time, in ms, after that the database content on the disk must
* be updated. The algorithm is written to avoid the very frequent writings to
* the disk.
*/
static long SAVE_AT_MOST_AFTER = 5000;
/**
* States how long the database may stay not updated during the intensive
* operations, in ms. Otherwise the intensively used structure may never
* be stored to the disk.
*/
static long ALWAYS_UPDATE = 300000;
/**
* Write the database content to the disk.
*/
void writeContent();
}
@@ -0,0 +1,268 @@
/* PersistentBidiHasthable.java -- Bidirectional persistent hash table.
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.rmi;
import gnu.classpath.tools.rmi.rmid.ActivationSystemImpl;
import gnu.java.rmi.activation.BidiTable;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.TimerTask;
/**
* The persistent bidirectional hash table, maps both a to b and b to a. The
* changes are written to dist after SAVE_AT_MOST_AFTER time from the latest
* database change or at most after ALWAYS_UPDATE, if the database is updated
* very frequently. To ensure that no information is lost, the shutdown method
* must be called before exit.
*
* @author Audrius Meskauskas (audriusa@bioinformatics.org)
*/
public class PersistentBidiHashTable extends BidiTable implements
Persistent
{
class WriteToDiskTask extends TimerTask
{
/**
* Save the database.
*/
public void run()
{
writeContent();
sheduled = null;
}
}
/**
* Replaces instances of ActivationSystemImpl into the currently active
* instance of the ActivationSystemImpl
*/
class AdaptedReader extends ObjectInputStream
{
AdaptedReader(InputStream in) throws IOException
{
super(in);
enableResolveObject(true);
}
protected Object resolveObject(Object obj) throws IOException
{
if (obj instanceof ActivationSystemImpl)
return ActivationSystemImpl.singleton2;
else
return obj;
}
}
/**
* The database file.
*/
File database;
/**
* The currently sheduled write to disk task, null if none.
*/
WriteToDiskTask sheduled = null;
/**
* The time, when the disk database was last updated.
*/
long lastUpdated;
/**
* Create the unitialised instance that must be initalised when
* ActivationSystemImpl.singleton2 is assigned.
*/
public PersistentBidiHashTable()
{
// Do not initalise the table fields - the initalise method must be
// called later.
super(0);
}
/**
* Create a new persistent table that stores its information into the given
* file. The ActivationSystemImpl.singleton2 must be assigned.
*
* @param file
* the file, where the table stores its information.
* @param coldStart
* if true, the existing file with this name will be erased and
* ignored. Otherwise, it will be assumed that the file contains the
* persistent table information.
*/
public void init(File file, boolean coldStart)
{
try
{
database = file;
if (database.exists())
{
if (coldStart)
{
k2v = new Hashtable();
v2k = new Hashtable();
database.delete();
}
else
{
FileInputStream fi = new FileInputStream(file);
BufferedInputStream b = new BufferedInputStream(fi);
ObjectInputStream oin = new AdaptedReader(b);
k2v = (Map) oin.readObject();
oin.close();
v2k = new Hashtable(k2v.size());
// Reguild v2k from k2v:
Iterator en = k2v.keySet().iterator();
Object key;
while (en.hasNext())
{
key = en.next();
v2k.put(k2v.get(key), key);
}
}
}
else
{
k2v = new Hashtable();
v2k = new Hashtable();
}
}
catch (Exception ioex)
{
InternalError ierr = new InternalError("Unable to intialize with file "
+ file);
ierr.initCause(ioex);
throw ierr;
}
}
/**
* Write the database content to the disk.
*/
public synchronized void writeContent()
{
try
{
FileOutputStream fou = new FileOutputStream(database);
BufferedOutputStream b = new BufferedOutputStream(fou);
ObjectOutputStream oout = new ObjectOutputStream(b);
oout.writeObject(k2v);
oout.close();
}
catch (Exception ioex)
{
InternalError ierr = new InternalError(
"Failed to write database to disk: "
+ database);
ierr.initCause(ioex);
throw ierr;
}
}
/**
* Mark the modified database as modified. The database will be written after
* several seconds, unless another modification occurs.
*/
public void markDirty()
{
if (System.currentTimeMillis() - lastUpdated > ALWAYS_UPDATE)
{
// Force storing to disk under intensive operation.
writeContent();
lastUpdated = System.currentTimeMillis();
if (sheduled != null)
{
sheduled.cancel();
sheduled = null;
}
}
else
{
// Otherwise coalesce the disk database copy update events.
if (sheduled != null)
sheduled.cancel();
sheduled = new WriteToDiskTask();
timer.schedule(sheduled, SAVE_AT_MOST_AFTER);
}
}
/**
* Save the current database state to the disk before exit.
*/
public void shutdown()
{
if (sheduled != null)
{
writeContent();
sheduled = null;
}
}
/**
* Update the memory maps and mark as should be written to the disk.
*/
public void put(Object key, Object value)
{
super.put(key, value);
markDirty();
}
/**
* Update the memory maps and mark as should be written to the disk.
*/
public void removeKey(Object key)
{
super.removeKey(key);
markDirty();
}
}
@@ -0,0 +1,246 @@
/* PersistentHasthable.java -- Persistent hash table.
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.rmi;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Hashtable;
import java.util.Map;
import java.util.TimerTask;
/**
* The persistent hash table. The changes are written to dist after
* SAVE_AT_MOST_AFTER time from the latest database change or at most after
* ALWAYS_UPDATE, if the database is updated very frequently. To ensure that no
* information is lost, the shutdown method must be called before exit.
*
* @author Audrius Meskauskas (audriusa@bioinformatics.org)
*/
public class PersistentHashTable
extends Hashtable
implements Serializable, Persistent
{
/**
* Use serialVersionUID for interoperability
*/
private static final long serialVersionUID = 1;
class WriteToDiskTask extends TimerTask
{
/**
* Save the database.
*/
public void run()
{
writeContent();
sheduled = null;
}
}
/**
* The database file.
*/
File database;
/**
* The currently sheduled write to disk task, null if none.
*/
WriteToDiskTask sheduled = null;
/**
* The time, when the disk database was last updated.
*/
long lastUpdated;
/**
* Setting to false prevents the automated disk update.
* The initial value is true to prevent writing while reading and is set
* to false in createInstance.
*/
transient boolean ready;
/**
* Use static method to obtain the instance.
*/
private PersistentHashTable(File file)
{
if (file == null)
throw new NullPointerException("Null file provided");
database = file;
}
/**
* Create a new persistent table that stores its information into the given
* file.
*
* @param file
* the file, where the table stores its information.
* @param coldStart
* if true, the existing file with this name will be erased and
* ignored. Otherwise, it will be assumed that the file contains the
* persistent table information.
*/
public static Map createInstance(File file, boolean coldStart)
{
try
{
PersistentHashTable k2v;
if (file.exists())
{
if (coldStart)
{
file.delete();
k2v = new PersistentHashTable(file);
}
else
{
FileInputStream fi = new FileInputStream(file);
BufferedInputStream b = new BufferedInputStream(fi);
ObjectInputStream oin = new ObjectInputStream(b);
k2v = (PersistentHashTable) oin.readObject();
oin.close();
}
}
else
k2v = new PersistentHashTable(file);
k2v.ready = true;
return k2v;
}
catch (Exception ioex)
{
InternalError ierr = new InternalError("Unable to intialize with file "
+ file);
ierr.initCause(ioex);
throw ierr;
}
}
/**
* Write the database content to the disk.
*/
public synchronized void writeContent()
{
try
{
FileOutputStream fou = new FileOutputStream(database);
BufferedOutputStream b = new BufferedOutputStream(fou);
ObjectOutputStream oout = new ObjectOutputStream(b);
oout.writeObject(this);
oout.close();
}
catch (Exception ioex)
{
InternalError ierr = new InternalError(
"Failed to write database to disk: "+ database);
ierr.initCause(ioex);
throw ierr;
}
}
/**
* Mark the modified database as modified. The database will be written after
* several seconds, unless another modification occurs.
*/
public void markDirty()
{
if (System.currentTimeMillis() - lastUpdated > ALWAYS_UPDATE)
{
// Force storing to disk under intensive operation.
writeContent();
lastUpdated = System.currentTimeMillis();
if (sheduled != null)
{
sheduled.cancel();
sheduled = null;
}
}
else
{
// Otherwise coalesce the disk database copy update events.
if (sheduled != null)
sheduled.cancel();
sheduled = new WriteToDiskTask();
timer.schedule(sheduled, SAVE_AT_MOST_AFTER);
}
}
/**
* Save the current database state to the disk before exit.
*/
public void shutdown()
{
if (sheduled != null)
{
writeContent();
sheduled = null;
}
}
/**
* Update the memory maps and mark as should be written to the disk.
*/
public Object put(Object key, Object value)
{
super.put(key, value);
if (ready)
markDirty();
return value;
}
/**
* Update the memory maps and mark as should be written to the disk.
*/
public Object remove(Object key)
{
Object removed = super.remove(key);
if (ready)
markDirty();
return removed;
}
}
@@ -0,0 +1,165 @@
/* REGISTY.java -- RMI registry starter.
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.rmi;
import gnu.classpath.tools.HelpPrinter;
import gnu.classpath.tools.rmi.registry.RegistryImpl;
import gnu.java.rmi.server.UnicastServerRef;
import java.io.File;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.ObjID;
import java.rmi.server.RMIServerSocketFactory;
import java.util.Hashtable;
import java.util.Map;
/**
* The optionally persistent RMI registry implementation.
*
* @author Audrius Meskauskas (audriusa@bioinformatics.org)
*/
public class REGISTRY
{
/**
* The stop command.
*/
public static String STOP = "gnu.classpath.tools.rmi.registry.command.STOP";
/**
* If true, the registry prints registration events to console.
*/
public static boolean verbose = false;
/**
* The RMI registry implementation entry point.
*/
public static void main(String[] args)
{
String HelpPath = "rmi/REGISTRY.txt";
HelpPrinter.checkHelpKey(args, HelpPath);
// Parse parameters:
String folder = ".";
boolean cold = false;
boolean trans = false;
boolean stop = false;
int port = Registry.REGISTRY_PORT;
RMIServerSocketFactory ssf = null;
for (int i = 0; i < args.length; i++)
{
String a = args[i];
if (a.equals("-restart"))
cold = true;
else if (a.equals("-transient"))
trans = true;
else if (a.equals("-verbose"))
verbose = true;
else if (a.equals("-stop"))
stop = true;
else if (i < args.length - 1)
{
// The additional key parameter is possible.
if (a.equals("-port"))
port = Integer.parseInt(args[++i]);
else if (a.equals("-folder"))
folder = args[++i];
}
}
if (!stop)
{
Map table;
if (trans)
table = new Hashtable();
else
{
// Start the system.
File dataFolder = new File(folder);
if (!dataFolder.exists())
dataFolder.mkdirs();
table = PersistentHashTable.createInstance(
new File(dataFolder, "rmiregistry.data"), cold);
}
RegistryImpl system = new RegistryImpl(table);
// We must export with the specific activation id that is only
// possible when going into the gnu.java.rmi
try
{
UnicastServerRef sref = new UnicastServerRef(
new ObjID(ObjID.REGISTRY_ID), port, ssf);
sref.exportObject(system);
System.out.println("The RMI naming service is listening at " + port);
}
catch (Exception ex)
{
System.out.println("Failed to start RMI naming service at " + port);
}
}
else
{
// Stop the naming service.
try
{
Registry r = LocateRegistry.getRegistry(port);
// Search for this specific line will command to stop the registry.
// Our service returns null, but any other service will thrown
// NotBoundException.
r.unbind(STOP);
}
catch (RemoteException e)
{
System.out.println("Failed to stop RMI naming service at " + port);
}
catch (NotBoundException e)
{
System.out.println("The naming service at port "+port+" is not a "+
REGISTRY.class.getName());
}
}
}
}
@@ -0,0 +1,28 @@
The persistent RMI naming service, required for the remote method invocations
(packages java.rmi.*, java.rmi.Registry.*).
Copyright 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Please report bugs at http://www.gnu.org/software/classpath/bugs.html
Usage: rmiregistry <options>
where <options> includes:
-port N Start the registry on the given local port. If this key
is not specified, the service starts on the port 1099.
-verbose Log binding events to stdout.
-stop Stop the running naming service at the given port.
-transient Start transient registry service that does not write any
data to the disk. Such service looses the stored bindings if
restarted. If this key is not specified, the
persistent naming service is started.
-restart "Cold start:, clear the persistent naming database, if any.
-folder Folder Store the persistent binding file in the given folder. If this
key is not specified, the file with persistent bindings is
stored into the current folder.
@@ -17,30 +17,13 @@ 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.rmi;
import gnu.classpath.tools.HelpPrinter;
import gnu.classpath.tools.giop.GRMIC;
import gnu.classpath.tools.giop.grmic.GiopRmicCompiler;
import gnu.classpath.tools.rmi.rmic.RmicCompiler;
import java.io.File;
@@ -114,6 +97,10 @@ public class RMIC
verbose = true;
compiler.setVerbose(true);
}
else if (c.equals("-force"))
{
compiler.setForce(true);
}
else if (c.equals("-d"))
{
int f = i + 1;
@@ -16,6 +16,8 @@ Usage: rmic <options> <class names>
-help Print this help text
-v Print version
-verbose Verbose output
-force Try to generate code even if the input classes seem not
consistent with RMI specification.
-1.2 Generate v 1.2 stubs (default)*
@@ -0,0 +1,189 @@
/* RMID.java -- the RMI activation daemon.
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.rmi;
import gnu.classpath.tools.HelpPrinter;
import gnu.classpath.tools.rmi.rmid.ActivationSystemImpl;
import gnu.java.rmi.activation.ActivationSystemTransient;
import gnu.java.rmi.server.UnicastServerRef;
import java.io.File;
import java.net.InetAddress;
import java.rmi.Remote;
import java.rmi.activation.ActivationSystem;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.ObjID;
import java.rmi.server.RMIServerSocketFactory;
/**
* The persistent RMI activation daemon.
*
* @author Audrius Meskauskas (audriusa@bioinformatics.org)
*/
public class RMID
{
/**
* The RMI server socket factory.
*/
static RMIServerSocketFactory ACTIVATION_REGISTY_SOCKET_FACTORY = null;
/**
* The activation registry port.
*/
static int ACTIVATION_REGISTRY_PORT = ActivationSystem.SYSTEM_PORT;
/**
* The activation system name.
*/
static String ACTIVATION_SYSTEM_NAME = "java.rmi.activation.ActivationSystem";
/**
* The RMI activation daemon entry point.
*/
public static void main(String[] args)
{
String HelpPath = "rmi/RMID.txt";
HelpPrinter.checkHelpKey(args, HelpPath);
// Parse parameters:
boolean stop = false;
String folder = ".";
boolean cold = false;
boolean trans = false;
for (int i = 0; i < args.length; i++)
{
String a = args[i];
if (a.equals("-verbose"))
ActivationSystemTransient.debug = true;
else if (a.equals("-stop"))
stop = true;
else if (a.equals("-restart"))
cold = true;
else if (a.equals("-transient"))
trans = true;
else if (i < args.length - 1)
{
// The additional key parameter is possible.
if (a.equals("-port"))
ACTIVATION_REGISTRY_PORT = Integer.parseInt(args[++i]);
else if (a.equals("-folder"))
folder = args[++i];
}
}
try
{
if (!stop)
{
// Start the system.
File dataFolder = new File(folder);
if (!dataFolder.exists())
dataFolder.mkdirs();
ActivationSystem system;
if (trans)
system = ActivationSystemTransient.getInstance();
else
system = ActivationSystemImpl.getInstance(dataFolder, cold);
// We must export with the specific activation id that is only
// possible when going into the gnu.java.rmi.activation.
UnicastServerRef sref = new UnicastServerRef(
new ObjID(ObjID.ACTIVATOR_ID), ACTIVATION_REGISTRY_PORT,
ACTIVATION_REGISTY_SOCKET_FACTORY);
Remote systemStub = sref.exportObject(system);
// Start the naming system on the activation system port
// (if not already running).
Registry r;
try
{
// Expect the naming service running first.
// The local host may want to use the shared registry
r = LocateRegistry.getRegistry(ACTIVATION_REGISTRY_PORT);
r.rebind(ACTIVATION_SYSTEM_NAME, systemStub);
}
catch (Exception ex)
{
// The naming service is not running. Start it.
r = LocateRegistry.createRegistry(ACTIVATION_REGISTRY_PORT);
r.rebind(ACTIVATION_SYSTEM_NAME, systemStub);
}
String host = InetAddress.getLocalHost().getCanonicalHostName();
System.out.println("The RMI daemon is listening on " + host +
" (port "
+ ACTIVATION_REGISTRY_PORT + ")");
}
else
{
// Stop the activation system.
Registry r;
try
{
System.out.print("Stopping RMI daemon at "
+ ACTIVATION_REGISTRY_PORT+" ... ");
// Expect the naming service running first.
// The local host may want to use the shared registry
r = LocateRegistry.getRegistry(ACTIVATION_REGISTRY_PORT);
ActivationSystem asys =
(ActivationSystem) r.lookup(ACTIVATION_SYSTEM_NAME);
asys.shutdown();
System.out.println("OK.");
}
catch (Exception ex)
{
System.out.println("The RMI daemon seems not running at "
+ ACTIVATION_REGISTRY_PORT);
if (ActivationSystemTransient.debug)
ex.printStackTrace();
}
}
}
catch (Exception e)
{
System.out.println("Failed to start the RMI daemon.");
if (ActivationSystemTransient.debug)
e.printStackTrace();
}
}
}
@@ -0,0 +1,30 @@
The persistent RMI activation daemon, support RMI object activation
(package java.rmi.activation.*).
Copyright 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Please report bugs at http://www.gnu.org/software/classpath/bugs.html
Usage: rmid <options>
where <options> includes:
-port N Start the service on the given local port. If this key
is not specified, the service starts on the port 1098.
-verbose Log registration events to stdout.
-stop Stop the running activation service at the given port.
-transient Start transient activation service that does not write any
data to the disk. Such service looses the stored activation
descriptors, if restarted. If this key is not specified, the
persistent naming service is started.
-restart "Cold start:, clear the activation descriptor database, if any.
-folder Folder Store the persistent descriptor file in the given folder. If this
key is not specified, the file with persistent activation
information is stored into the current folder.
All activation groups are activated on the same virtual machine, where the
daemon is running. For security reasons, all the classes, required for
activation, must be available in the classpath of that machine.
@@ -0,0 +1,139 @@
/* RegistryImpl.java -- the RMI registry implementation
Copyright (c) 1996, 1997, 1998, 1999, 2002, 2005, 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.rmi.registry;
import gnu.classpath.tools.rmi.Persistent;
import gnu.classpath.tools.rmi.REGISTRY;
import java.rmi.AccessException;
import java.rmi.AlreadyBoundException;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.Map;
/**
* The optionally persistent registry implementation.
*
* @author Audrius Meskauskas (audriusa@bioinformatics.org)
*/
public class RegistryImpl implements Registry
{
/**
* The binding table.
*/
Map bindings;
/**
* Create the registry implementation that uses the given bidirectinal
* table to keep the data.
*/
public RegistryImpl(Map aTable)
{
bindings = aTable;
}
/** @inheritDoc */
public Remote lookup(String name) throws RemoteException, NotBoundException,
AccessException
{
Object obj = bindings.get(name);
if (obj == null)
throw new NotBoundException(name);
return ((Remote) obj);
}
/** @inheritDoc */
public void bind(String name, Remote obj) throws RemoteException,
AlreadyBoundException, AccessException
{
if (REGISTRY.verbose)
System.out.println("Bind "+name);
if (bindings.containsKey(name))
throw new AlreadyBoundException(name);
bindings.put(name, obj);
}
/** @inheritDoc */
public void unbind(String name) throws RemoteException, NotBoundException,
AccessException
{
if (name.equals(REGISTRY.STOP))
{
if (bindings instanceof Persistent)
((Persistent) bindings).writeContent();
// Terminate in 10 seconds.
System.out.println("Shutdown command received. Will terminate in 10 s");
Persistent.timer.schedule(new Persistent.ExitTask(), 10000);
}
else
{
if (REGISTRY.verbose)
System.out.println("Unbind "+name);
if (!bindings.containsKey(name))
throw new NotBoundException(name);
else
bindings.remove(name);
}
}
/** @inheritDoc */
public void rebind(String name, Remote obj) throws RemoteException,
AccessException
{
if (REGISTRY.verbose)
System.out.println("Rebind "+name);
bindings.put(name, obj);
}
/** @inheritDoc */
public String[] list() throws RemoteException, AccessException
{
// Create a separated array to prevent race conditions.
ArrayList keys = new ArrayList(bindings.keySet());
int n = keys.size();
String[] rt = new String[n];
for (int i = 0; i < n; i++)
rt[i] = (String) keys.get(i);
return rt;
}
}
@@ -0,0 +1,278 @@
/* RegistryImpl_Skel.java
Copyright (C) 2002, 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.rmi.registry;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.rmi.MarshalException;
import java.rmi.Remote;
import java.rmi.UnmarshalException;
import java.rmi.server.Operation;
import java.rmi.server.RemoteCall;
import java.rmi.server.SkeletonMismatchException;
/**
* This skeleton supports unlikely cases when the naming service is
* contacted from other interoperable java implementation that still uses
* the old style skeleton-dependent invocations.
*/
public final class RegistryImpl_Skel
implements java.rmi.server.Skeleton
{
private static final long interfaceHash = 4905912898345647071L;
/**
* Repeated multiple times.
*/
static final String EUM = "error unmarshalling arguments for Registry";
/**
* Repeated multiple times.
*/
static final String EMR = "error marshalling return from Registry";
private static final Operation[] operations =
{
new Operation("void bind(java.lang.String, Remote"),
new Operation("java.lang.String[] list("),
new Operation("Remote lookup(java.lang.String"),
new Operation("void rebind(java.lang.String, Remote"),
new Operation("void unbind(java.lang.String")
};
public Operation[] getOperations()
{
return ((Operation[]) operations.clone());
}
public void dispatch(Remote obj, RemoteCall call,
int opnum, long hash) throws java.lang.Exception
{
if (opnum < 0)
{
if (hash == 7583982177005850366L)
opnum = 0;
else if (hash == 2571371476350237748L)
opnum = 1;
else if (hash == -7538657168040752697L)
opnum = 2;
else if (hash == -8381844669958460146L)
opnum = 3;
else if (hash == 7305022919901907578L)
opnum = 4;
else
throw new SkeletonMismatchException("interface hash mismatch");
}
else if (hash != interfaceHash)
throw new SkeletonMismatchException("interface hash mismatch");
RegistryImpl server = (RegistryImpl) obj;
switch (opnum)
{
case 0:
{
java.lang.String $param_0;
Remote $param_1;
try
{
ObjectInput in = call.getInputStream();
$param_0 = (java.lang.String) in.readObject();
$param_1 = (Remote) in.readObject();
}
catch (IOException e)
{
throw new UnmarshalException(EUM, e);
}
catch (java.lang.ClassCastException e)
{
throw new UnmarshalException(EUM, e);
}
finally
{
call.releaseInputStream();
}
server.bind($param_0, $param_1);
try
{
ObjectOutput out = call.getResultStream(true);
}
catch (IOException e)
{
throw new MarshalException(EMR, e);
}
break;
}
case 1:
{
try
{
ObjectInput in = call.getInputStream();
}
catch (IOException e)
{
throw new UnmarshalException(EUM, e);
}
finally
{
call.releaseInputStream();
}
java.lang.String[] $result = server.list();
try
{
ObjectOutput out = call.getResultStream(true);
out.writeObject($result);
}
catch (IOException e)
{
throw new MarshalException(EMR, e);
}
break;
}
case 2:
{
java.lang.String $param_0;
try
{
ObjectInput in = call.getInputStream();
$param_0 = (java.lang.String) in.readObject();
}
catch (IOException e)
{
throw new UnmarshalException(EUM, e);
}
catch (java.lang.ClassCastException e)
{
throw new UnmarshalException(EUM, e);
}
finally
{
call.releaseInputStream();
}
Remote $result = server.lookup($param_0);
try
{
ObjectOutput out = call.getResultStream(true);
out.writeObject($result);
}
catch (IOException e)
{
throw new MarshalException(EMR, e);
}
break;
}
case 3:
{
java.lang.String $param_0;
Remote $param_1;
try
{
ObjectInput in = call.getInputStream();
$param_0 = (java.lang.String) in.readObject();
$param_1 = (Remote) in.readObject();
}
catch (IOException e)
{
throw new UnmarshalException(EUM, e);
}
catch (java.lang.ClassCastException e)
{
throw new UnmarshalException(EUM, e);
}
finally
{
call.releaseInputStream();
}
server.rebind($param_0, $param_1);
try
{
ObjectOutput out = call.getResultStream(true);
}
catch (IOException e)
{
throw new MarshalException(EMR, e);
}
break;
}
case 4:
{
java.lang.String $param_0;
try
{
ObjectInput in = call.getInputStream();
$param_0 = (java.lang.String) in.readObject();
}
catch (IOException e)
{
throw new UnmarshalException(EUM, e);
}
catch (java.lang.ClassCastException e)
{
throw new UnmarshalException(EUM, e);
}
finally
{
call.releaseInputStream();
}
server.unbind($param_0);
try
{
ObjectOutput out = call.getResultStream(true);
}
catch (IOException e)
{
throw new MarshalException(EMR, e);
}
break;
}
default:
throw new UnmarshalException("invalid method number");
}
}
}
@@ -0,0 +1,263 @@
/* RegistryImpl_Stub.java -- Registry stub.
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.rmi.registry;
import java.rmi.AccessException;
import java.rmi.AlreadyBoundException;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.Registry;
import java.lang.reflect.Method;
import java.rmi.server.RemoteRef;
import java.rmi.server.RemoteStub;
import java.rmi.UnexpectedException;
/**
* This class delegates its method calls to the remote RMI object, referenced
* by {@link RemoteRef}.
*
* It is normally generated with rmic.
*/
public final class RegistryImpl_Stub
extends RemoteStub
implements Registry
{
/**
* Use serialVersionUID for interoperability
*/
private static final long serialVersionUID = 3;
/**
* The explaining message for {@ling UnexpectedException}.
*/
private static final String exception_message =
"undeclared checked exception";
/* All remote methods, invoked by this stub: */
private static final Method met_list;
private static final Method met_rebind;
private static final Method met_unbind;
private static final Method met_lookup;
private static final Method met_bind;
private static final Object[] NO_ARGS = new Object[0];
static
{
final Class[] NO_ARGSc = new Class[0];
try
{
met_list =
Registry.class.getMethod("list", NO_ARGSc);
met_rebind =
Registry.class.getMethod("rebind", new Class[]
{
String.class, Remote.class
});
met_unbind =
Registry.class.getMethod("unbind", new Class[]
{
String.class
});
met_lookup =
Registry.class.getMethod("lookup", new Class[]
{
String.class
});
met_bind =
Registry.class.getMethod("bind", new Class[]
{
String.class, Remote.class
});
}
catch (NoSuchMethodException nex)
{
NoSuchMethodError err = new NoSuchMethodError(
"RegistryImpl_Stub class initialization failed");
err.initCause(nex);
throw err;
}
}
/**
* Create the instance for _RegistryImpl_Stub that forwards method calls to the
* remote object.
*
* @para the reference to the remote object.
*/
public RegistryImpl_Stub(RemoteRef reference)
{
super(reference);
}
/* Methods */
/** @inheritDoc */
public String [] list()
throws RemoteException, AccessException
{
try
{
Object result = ref.invoke(this, met_list,
NO_ARGS,
2571371476350237748L);
return (String []) result;
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public void rebind(String p0, Remote p1)
throws RemoteException, AccessException
{
try
{
ref.invoke(this, met_rebind,
new Object[] {p0, p1},
-8381844669958460146L);
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public void unbind(String p0)
throws RemoteException, NotBoundException, AccessException
{
try
{
ref.invoke(this, met_unbind,
new Object[] {p0},
7305022919901907578L);
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public Remote lookup(String p0)
throws RemoteException, NotBoundException, AccessException
{
try
{
Object result = ref.invoke(this, met_lookup,
new Object[] {p0},
-7538657168040752697L);
return (Remote) result;
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public void bind(String p0, Remote p1)
throws RemoteException, AlreadyBoundException, AccessException
{
try
{
ref.invoke(this, met_bind,
new Object[] {p0, p1},
7583982177005850366L);
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
}
@@ -22,18 +22,7 @@
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.rmi.rmic;
@@ -43,7 +32,6 @@ import gnu.java.rmi.server.RMIHashes;
import java.lang.reflect.Method;
import java.util.Properties;
import java.util.zip.Adler32;
/**
* Keeps information about the single method and generates the code fragments,
@@ -22,18 +22,7 @@ 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.rmi.rmic;
@@ -17,28 +17,11 @@ 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.rmi.rmic;
import java.lang.reflect.Method;
public class WrapUnWrapper
{
@@ -19,7 +19,7 @@
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.initCause(e);
uex.detail = e;
throw uex;
}
}
@@ -18,7 +18,7 @@
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.initCause(e);
uex.detail = e;
throw uex;
}
}
@@ -0,0 +1,244 @@
/* ActivationSystemImpl.java -- implementation of the activation system.
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.rmi.rmid;
import gnu.classpath.tools.rmi.Persistent;
import gnu.classpath.tools.rmi.PersistentBidiHashTable;
import gnu.java.rmi.activation.ActivationSystemTransient;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.rmi.MarshalledObject;
import java.rmi.RemoteException;
import java.rmi.activation.ActivationDesc;
import java.rmi.activation.ActivationException;
import java.rmi.activation.ActivationGroupDesc;
import java.rmi.activation.ActivationGroupID;
import java.rmi.activation.ActivationID;
import java.rmi.activation.ActivationInstantiator;
import java.rmi.activation.ActivationMonitor;
import java.rmi.activation.ActivationSystem;
import java.rmi.activation.Activator;
import java.rmi.activation.UnknownGroupException;
import java.rmi.activation.UnknownObjectException;
/**
* Implements the rmid activation system.
*
* @author Audrius Meskauskas (audriusa@bioinformatics.org)
*/
public class ActivationSystemImpl extends ActivationSystemTransient implements
ActivationSystem, Activator, ActivationMonitor, Serializable
{
/**
* Use for interoperability.
*/
private static final long serialVersionUID = 1;
/**
* The singleton instance of this class.
*/
public static ActivationSystemImpl singleton2;
/**
* Obtain the singleton instance of this class.
*
* @param folder the folder, where the activation system will keep its files.
* @param cold do the cold start if true, hot (usual) if false.
*/
public static ActivationSystem getInstance(File folder, boolean cold)
{
if (singleton2 == null)
singleton2 = new ActivationSystemImpl(folder, cold);
return singleton2;
}
/**
* Creates the group with transient maps.
*
* @param folder
* the folder, where the activation system will keep its files.
* @param cold
* do the cold start if true, hot (usual) if false.
*/
protected ActivationSystemImpl(File folder, boolean cold)
{
super(new PersistentBidiHashTable(), new PersistentBidiHashTable());
singleton2 = this;
((PersistentBidiHashTable) groupDescs).init(
new File(folder, "asi_objects.data"), cold);
((PersistentBidiHashTable) descriptions).init(
new File(folder, "asi_groups.data"), cold);
}
/** @inheritDoc */
public MarshalledObject activate(ActivationID id, boolean force)
throws ActivationException, UnknownObjectException, RemoteException
{
return super.activate(id, force);
}
/** @inheritDoc */
public ActivationMonitor activeGroup(ActivationGroupID id,
ActivationInstantiator group,
long incarnation)
throws UnknownGroupException, ActivationException, RemoteException
{
return super.activeGroup(id, group, incarnation);
}
/** @inheritDoc */
public void activeObject(ActivationID id, MarshalledObject obj)
throws UnknownObjectException, RemoteException
{
super.activeObject(id, obj);
}
/** @inheritDoc */
public ActivationDesc getActivationDesc(ActivationID id)
throws ActivationException, UnknownObjectException, RemoteException
{
return super.getActivationDesc(id);
}
public ActivationGroupDesc getActivationGroupDesc(ActivationGroupID groupId)
throws ActivationException, UnknownGroupException, RemoteException
{
return super.getActivationGroupDesc(groupId);
}
/** @inheritDoc */
public void inactiveGroup(ActivationGroupID groupId, long incarnation)
throws UnknownGroupException, RemoteException
{
super.inactiveGroup(groupId, incarnation);
}
/** @inheritDoc */
public void inactiveObject(ActivationID id) throws UnknownObjectException,
RemoteException
{
super.inactiveObject(id);
}
/** @inheritDoc */
public ActivationGroupID registerGroup(ActivationGroupDesc groupDesc)
throws ActivationException, RemoteException
{
return super.registerGroup(groupDesc);
}
/** @inheritDoc */
public ActivationID registerObject(ActivationDesc desc)
throws ActivationException, UnknownGroupException, RemoteException
{
return super.registerObject(desc);
}
/** @inheritDoc */
public ActivationDesc setActivationDesc(ActivationID id, ActivationDesc desc)
throws ActivationException, UnknownObjectException,
UnknownGroupException, RemoteException
{
return super.setActivationDesc(id, desc);
}
/** @inheritDoc */
public ActivationGroupDesc setActivationGroupDesc(
ActivationGroupID groupId, ActivationGroupDesc groupDesc)
throws ActivationException, UnknownGroupException, RemoteException
{
return super.setActivationGroupDesc(groupId, groupDesc);
}
/**
* This method saves the state of the activation system and then
* terminates in 10 seconds.
*/
public void shutdown() throws RemoteException
{
super.shutdown();
System.out.println("Shutdown command received. Will terminate in 10 s");
Persistent.timer.schedule(new Persistent.ExitTask(), 10000);
}
/** @inheritDoc */
public void unregisterGroup(ActivationGroupID groupId)
throws ActivationException, UnknownGroupException, RemoteException
{
super.unregisterGroup(groupId);
}
/** @inheritDoc */
public void unregisterObject(ActivationID id) throws ActivationException,
UnknownObjectException, RemoteException
{
super.unregisterObject(id);
}
/**
* Read the object from the input stream.
*
* @param in the stream to read from
*
* @throws IOException if thrown by the stream
* @throws ClassNotFoundException
*/
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException
{
// Read no fields.
}
/**
* Write the object to the output stream.
*
* @param out the stream to write int
* @throws IOException if thrown by the stream
* @throws ClassNotFoundException
*/
private void writeObject(ObjectOutputStream out) throws IOException,
ClassNotFoundException
{
// Write no fields.
};
}
@@ -0,0 +1,556 @@
/* ActivationSystemImpl.java -- implementation of the activation system.
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.rmi.rmid;
import java.rmi.MarshalledObject;
import java.rmi.RemoteException;
import java.rmi.activation.ActivationDesc;
import java.rmi.activation.ActivationException;
import java.rmi.activation.ActivationGroupDesc;
import java.rmi.activation.ActivationGroupID;
import java.rmi.activation.ActivationID;
import java.rmi.activation.ActivationInstantiator;
import java.rmi.activation.ActivationMonitor;
import java.rmi.activation.ActivationSystem;
import java.rmi.activation.Activator;
import java.rmi.activation.UnknownGroupException;
import java.rmi.activation.UnknownObjectException;
import java.lang.reflect.Method;
import java.rmi.server.RemoteRef;
import java.rmi.server.RemoteStub;
import java.rmi.UnexpectedException;
/**
* This class delegates its method calls to the remote RMI object, referenced
* by {@link RemoteRef}.
*
* It is normally generated with rmic.
*/
public final class ActivationSystemImpl_Stub
extends RemoteStub
implements ActivationMonitor, Activator, ActivationSystem
{
/**
* Use serialVersionUID for interoperability
*/
private static final long serialVersionUID = 2;
/**
* The explaining message for {@ling UnexpectedException}.
*/
private static final String exception_message =
"undeclared checked exception";
/* All remote methods, invoked by this stub: */
private static final Method met_setActivationGroupDesc;
private static final Method met_inactiveGroup;
private static final Method met_unregisterObject;
private static final Method met_getActivationDesc;
private static final Method met_setActivationDesc;
private static final Method met_shutdown;
private static final Method met_activate;
private static final Method met_activeGroup;
private static final Method met_registerGroup;
private static final Method met_getActivationGroupDesc;
private static final Method met_activeObject;
private static final Method met_registerObject;
private static final Method met_inactiveObject;
private static final Method met_unregisterGroup;
private static final Object[] NO_ARGS = new Object[0];
static
{
final Class[] NO_ARGSc = new Class[0];
try
{
met_setActivationGroupDesc =
ActivationSystem.class.getMethod("setActivationGroupDesc", new Class[]
{
ActivationGroupID.class, ActivationGroupDesc.class
});
met_inactiveGroup =
ActivationMonitor.class.getMethod("inactiveGroup", new Class[]
{
ActivationGroupID.class, long.class
});
met_unregisterObject =
ActivationSystem.class.getMethod("unregisterObject", new Class[]
{
ActivationID.class
});
met_getActivationDesc =
ActivationSystem.class.getMethod("getActivationDesc", new Class[]
{
ActivationID.class
});
met_setActivationDesc =
ActivationSystem.class.getMethod("setActivationDesc", new Class[]
{
ActivationID.class, ActivationDesc.class
});
met_shutdown =
ActivationSystem.class.getMethod("shutdown", NO_ARGSc);
met_activate =
Activator.class.getMethod("activate", new Class[]
{
ActivationID.class, boolean.class
});
met_activeGroup =
ActivationSystem.class.getMethod("activeGroup", new Class[]
{
ActivationGroupID.class, ActivationInstantiator.class, long.class
});
met_registerGroup =
ActivationSystem.class.getMethod("registerGroup", new Class[]
{
ActivationGroupDesc.class
});
met_getActivationGroupDesc =
ActivationSystem.class.getMethod("getActivationGroupDesc", new Class[]
{
ActivationGroupID.class
});
met_activeObject =
ActivationMonitor.class.getMethod("activeObject", new Class[]
{
ActivationID.class, MarshalledObject.class
});
met_registerObject =
ActivationSystem.class.getMethod("registerObject", new Class[]
{
ActivationDesc.class
});
met_inactiveObject =
ActivationMonitor.class.getMethod("inactiveObject", new Class[]
{
ActivationID.class
});
met_unregisterGroup =
ActivationSystem.class.getMethod("unregisterGroup", new Class[]
{
ActivationGroupID.class
});
}
catch (NoSuchMethodException nex)
{
NoSuchMethodError err = new NoSuchMethodError(
"ActivationSystemImpl_Stub class initialization failed");
err.initCause(nex);
throw err;
}
}
/**
* Create the instance for _ActivationSystemImpl_Stub that forwards method calls to the
* remote object.
*
* @para the reference to the remote object.
*/
public ActivationSystemImpl_Stub(RemoteRef reference)
{
super(reference);
}
/* Methods */
/** @inheritDoc */
public ActivationGroupDesc setActivationGroupDesc(ActivationGroupID p0,
ActivationGroupDesc p1)
throws ActivationException, UnknownGroupException, RemoteException
{
try
{
Object result = ref.invoke(this, met_setActivationGroupDesc,
new Object[] { p0, p1 },
1213918527826541191L);
return (ActivationGroupDesc) result;
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public void inactiveGroup(ActivationGroupID p0, long p1)
throws UnknownGroupException, RemoteException
{
try
{
ref.invoke(this, met_inactiveGroup, new Object[] { p0, new Long(p1) },
-399287892768650944L);
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public void unregisterObject(ActivationID p0) throws ActivationException,
UnknownObjectException, RemoteException
{
try
{
ref.invoke(this, met_unregisterObject, new Object[] { p0 },
-6843850585331411084L);
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public ActivationDesc getActivationDesc(ActivationID p0)
throws ActivationException, UnknownObjectException, RemoteException
{
try
{
Object result = ref.invoke(this, met_getActivationDesc,
new Object[] { p0 }, 4830055440982622087L);
return (ActivationDesc) result;
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public ActivationDesc setActivationDesc(ActivationID p0, ActivationDesc p1)
throws ActivationException, UnknownObjectException,
UnknownGroupException, RemoteException
{
try
{
Object result = ref.invoke(this, met_setActivationDesc,
new Object[] { p0, p1 },
7128043237057180796L);
return (ActivationDesc) result;
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public void shutdown() throws RemoteException
{
try
{
ref.invoke(this, met_shutdown, NO_ARGS, -7207851917985848402L);
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public MarshalledObject activate(ActivationID p0, boolean p1)
throws ActivationException, UnknownObjectException, RemoteException
{
try
{
Object result = ref.invoke(this, met_activate,
new Object[] { p0, new Boolean(p1) },
-8767355154875805558L);
return (MarshalledObject) result;
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public ActivationMonitor activeGroup(ActivationGroupID p0,
ActivationInstantiator p1, long p2)
throws UnknownGroupException, ActivationException, RemoteException
{
try
{
Object result = ref.invoke(this, met_activeGroup,
new Object[] { p0, p1, new Long(p2) },
-4575843150759415294L);
return (ActivationMonitor) result;
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public ActivationGroupID registerGroup(ActivationGroupDesc p0)
throws ActivationException, RemoteException
{
try
{
Object result = ref.invoke(this, met_registerGroup,
new Object[] { p0 }, 6921515268192657754L);
return (ActivationGroupID) result;
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public ActivationGroupDesc getActivationGroupDesc(ActivationGroupID p0)
throws ActivationException, UnknownGroupException, RemoteException
{
try
{
Object result = ref.invoke(this, met_getActivationGroupDesc,
new Object[] { p0 }, -8701843806548736528L);
return (ActivationGroupDesc) result;
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public void activeObject(ActivationID p0, MarshalledObject p1)
throws UnknownObjectException, RemoteException
{
try
{
ref.invoke(this, met_activeObject, new Object[] { p0, p1 },
2543984342209939736L);
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public ActivationID registerObject(ActivationDesc p0)
throws ActivationException, UnknownGroupException, RemoteException
{
try
{
Object result = ref.invoke(this, met_registerObject,
new Object[] { p0 }, -3006759798994351347L);
return (ActivationID) result;
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public void inactiveObject(ActivationID p0) throws UnknownObjectException,
RemoteException
{
try
{
ref.invoke(this, met_inactiveObject, new Object[] { p0 },
-4165404120701281807L);
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
/** @inheritDoc */
public void unregisterGroup(ActivationGroupID p0) throws ActivationException,
UnknownGroupException, RemoteException
{
try
{
ref.invoke(this, met_unregisterGroup, new Object[] { p0 },
3768097077835970701L);
}
catch (RuntimeException e)
{
throw e;
}
catch (RemoteException e)
{
throw e;
}
catch (Exception e)
{
UnexpectedException uex = new UnexpectedException(exception_message);
uex.detail = e;
throw uex;
}
}
}
+63
View File
@@ -0,0 +1,63 @@
#!/bin/sh
## Copyright (C) 2006 Free Software Foundation, Inc.
##
## This file is a 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 of the License, 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; if not, write to the Free Software
## Foundation, Inc., 51 Franklin St, 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.
##
##
## A simple shell script to launch the GNU Classpath jarsigner tool.
##
prefix=@prefix@
tools_dir=@datadir@/@PACKAGE@
tools_cp=${tools_dir}/tools.zip
# find the java executable...
if [ -z "${JAVA}" ] ; then
if [ -n "${JAVA_HOME}" ] ; then
if [ -x "${JAVA_HOME}/jre/sh/java" ] ; then
JAVA="${JAVA_HOME}/jre/sh/java"
else
JAVA="${JAVA_HOME}/bin/java"
fi
else
JAVA=`which java 2> /dev/null `
if [ -z "${JAVA}" ] ; then
JAVA=java
fi
fi
fi
exec "${JAVA}" -Xbootclasspath/p:"${tools_cp}" gnu.classpath.tools.jarsigner.Main $@
+63
View File
@@ -0,0 +1,63 @@
#!/bin/sh
## Copyright (C) 2006 Free Software Foundation, Inc.
##
## This file is a 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 of the License, 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; if not, write to the Free Software
## Foundation, Inc., 51 Franklin St, 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.
##
##
## A simple shell script to launch the GNU Classpath keytool tool.
##
prefix=@prefix@
tools_dir=@datadir@/@PACKAGE@
tools_cp=${tools_dir}/tools.zip
# find the java executable...
if [ -z "${JAVA}" ] ; then
if [ -n "${JAVA_HOME}" ] ; then
if [ -x "${JAVA_HOME}/jre/sh/java" ] ; then
JAVA="${JAVA_HOME}/jre/sh/java"
else
JAVA="${JAVA_HOME}/bin/java"
fi
else
JAVA=`which java 2> /dev/null `
if [ -z "${JAVA}" ] ; then
JAVA=java
fi
fi
fi
exec "${JAVA}" -Xbootclasspath/p:"${tools_cp}" gnu.classpath.tools.keytool.Main $@