diff --git a/.gitignore b/.gitignore
index 551c98d6..60080e52 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,6 +80,8 @@ src/tools/cardos-info
src/tools/sceac-example
src/tools/opensc-notify
src/tools/org.opensc.notify.desktop
+src/tools/pkcs11-register
+src/tools/pkcs11-register.desktop
src/tools/opensc-asn1
win32/OpenSC.iss
diff --git a/MacOSX/Distribution.xml.in b/MacOSX/Distribution.xml.in
index c42f94c9..9443938b 100644
--- a/MacOSX/Distribution.xml.in
+++ b/MacOSX/Distribution.xml.in
@@ -20,4 +20,7 @@ https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/D
OpenSC-tokend.pkg
+
+ OpenSC-startup.pkg
+
diff --git a/MacOSX/build-package.in b/MacOSX/build-package.in
index 04467585..48f4a25a 100755
--- a/MacOSX/build-package.in
+++ b/MacOSX/build-package.in
@@ -122,9 +122,14 @@ imagedir=$(mktemp -d)
mkdir -p ${BUILDPATH}/target/usr/local/bin
cp MacOSX/opensc-uninstall ${BUILDPATH}/target/usr/local/bin
+# Prepare startup root
+mkdir -p ${BUILDPATH}/target_startup/Library/LaunchAgents
+cp src/tools/pkcs11-register.plist ${BUILDPATH}/target_startup/Library/LaunchAgents
+
# Build package
pkgbuild --root ${BUILDPATH}/target --scripts MacOSX/scripts --identifier org.opensc-project.mac --version @PACKAGE_VERSION@ --install-location / OpenSC.pkg
pkgbuild --root ${BUILDPATH}/target_tokend --identifier org.opensc-project.tokend --version @PACKAGE_VERSION@ --install-location / OpenSC-tokend.pkg
+pkgbuild --root ${BUILDPATH}/target_startup --identifier org.opensc-project.startup --version @PACKAGE_VERSION@ --install-location / OpenSC-startup.pkg
# Build product
productbuild --distribution MacOSX/Distribution.xml --package-path . --resources MacOSX/resources "${imagedir}/OpenSC @PACKAGE_VERSION@.pkg"
diff --git a/configure.ac b/configure.ac
index 99806dbf..dd915655 100644
--- a/configure.ac
+++ b/configure.ac
@@ -260,6 +260,13 @@ AC_ARG_ENABLE(
[enable_notify="detect"]
)
+AC_ARG_ENABLE(
+ [autostart-items],
+ [AS_HELP_STRING([--enable-autostart-items],[enable autostart items @<:@enabled@:>@])],
+ ,
+ [enable_autostart="yes"]
+)
+
AC_ARG_ENABLE(
[tests],
[AS_HELP_STRING([--enable-tests],[Build tests in src/tests/ directory @<:@detect@:>@])],
@@ -894,11 +901,14 @@ fi
if test "${with_pkcs11_provider}" = "detect"; then
if test "${WIN32}" != "yes"; then
DEFAULT_PKCS11_PROVIDER="${libdir}/opensc-pkcs11${DYN_LIB_EXT}"
+ DEFAULT_ONEPIN_PKCS11_PROVIDER="${libdir}/onepin-opensc-pkcs11${DYN_LIB_EXT}"
else
DEFAULT_PKCS11_PROVIDER="%PROGRAMFILES%\\\OpenSC Project\\\OpenSC\\\pkcs11\\\opensc-pkcs11.dll"
+ DEFAULT_ONEPIN_PKCS11_PROVIDER="%PROGRAMFILES%\\\OpenSC Project\\\OpenSC\\\pkcs11\\\onepin-opensc-pkcs11.dll"
fi
else
DEFAULT_PKCS11_PROVIDER="${with_pkcs11_provider}"
+ DEFAULT_ONEPIN_PKCS11_PROVIDER="${with_pkcs11_provider}"
fi
if test "${enable_man}" = "detect"; then
@@ -1010,6 +1020,7 @@ AC_SUBST([OPENSC_LT_OLDEST])
AC_SUBST([WIN_LIBPREFIX])
AC_SUBST([DEFAULT_PCSC_PROVIDER])
AC_SUBST([DEFAULT_PKCS11_PROVIDER])
+AC_SUBST([DEFAULT_ONEPIN_PKCS11_PROVIDER])
AC_SUBST([OPTIONAL_ZLIB_CFLAGS])
AC_SUBST([OPTIONAL_ZLIB_LIBS])
AC_SUBST([OPTIONAL_READLINE_CFLAGS])
@@ -1044,6 +1055,7 @@ AM_CONDITIONAL([ENABLE_MINIDRIVER_SETUP_CUSTOMACTION], [test "${enable_minidrive
AM_CONDITIONAL([ENABLE_SM], [test "${enable_sm}" = "yes"])
AM_CONDITIONAL([ENABLE_DNIE_UI], [test "${enable_dnie_ui}" = "yes"])
AM_CONDITIONAL([ENABLE_NPATOOL], [test "${ENABLE_NPATOOL}" = "yes"])
+AM_CONDITIONAL([ENABLE_AUTOSTART], [test "${enable_autostart}" = "yes"])
AM_CONDITIONAL([ENABLE_TESTS], [test "${enable_tests}" = "yes"])
AM_CONDITIONAL([GIT_CHECKOUT], [test "${GIT_CHECKOUT}" = "yes"])
@@ -1143,6 +1155,7 @@ Build tests: ${enable_tests}
PC/SC default provider: ${DEFAULT_PCSC_PROVIDER}
PKCS11 default provider: $(eval eval eval echo "${DEFAULT_PKCS11_PROVIDER}")
+PKCS11 onepin provider: $(eval eval eval echo "${DEFAULT_ONEPIN_PKCS11_PROVIDER}")
Host: ${host}
Compiler: ${CC}
diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am
index 495078d3..13865c9c 100644
--- a/src/tools/Makefile.am
+++ b/src/tools/Makefile.am
@@ -16,18 +16,19 @@ do_subst = $(SED) \
-e 's,[@]PACKAGE_URL[@],$(PACKAGE_URL),g' \
-e 's,[@]PACKAGE_SUMMARY[@],$(PACKAGE_SUMMARY),g' \
-e 's,[@]PACKAGE_VERSION[@],"$(PACKAGE_VERSION)",g' \
+ -e 's,[@]DEFAULT_PKCS11_PROVIDER[@],"$(DEFAULT_PKCS11_PROVIDER)",g' \
-e 's,[@]VDFORMAT[@],$(VDFORMAT),g' \
-e 's,[@]X509DIR[@],$(X509DIR),g'
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in $(srcdir)/versioninfo-tools.rc $(srcdir)/versioninfo-opensc-notify.rc
-EXTRA_DIST = Makefile.mak versioninfo-tools.rc.in versioninfo-opensc-notify.rc.in goid-tool.ggo.in npa-tool.ggo.in opensc-notify.ggo.in egk-tool.ggo.in opensc-asn1.ggo.in org.opensc.notify.desktop.in exe.manifest
+EXTRA_DIST = Makefile.mak versioninfo-tools.rc.in versioninfo-opensc-notify.rc.in goid-tool.ggo.in npa-tool.ggo.in opensc-notify.ggo.in egk-tool.ggo.in opensc-asn1.ggo.in org.opensc.notify.desktop.in exe.manifest pkcs11-register.desktop.in pkcs11-register.plist.in
noinst_HEADERS = util.h fread_to_eof.h \
egk-tool-cmdline.h goid-tool-cmdline.h npa-tool-cmdline.h \
opensc-asn1-cmdline.h opensc-notify-cmdline.h
noinst_PROGRAMS = sceac-example
bin_PROGRAMS = opensc-tool opensc-explorer opensc-notify \
- pkcs15-tool pkcs15-crypt pkcs11-tool \
+ pkcs15-tool pkcs15-crypt pkcs11-tool pkcs11-register \
cardos-tool eidenv openpgp-tool iasecc-tool egk-tool opensc-asn1 goid-tool
if ENABLE_OPENSSL
bin_PROGRAMS += cryptoflex-tool pkcs15-init netkey-tool piv-tool \
@@ -36,7 +37,7 @@ endif
# compile with $(PTHREAD_CFLAGS) to allow debugging with gdb
AM_CFLAGS = $(OPTIONAL_OPENSSL_CFLAGS) $(OPTIONAL_READLINE_CFLAGS) $(PTHREAD_CFLAGS)
-AM_CPPFLAGS = -I$(top_srcdir)/src -D'DEFAULT_PKCS11_PROVIDER="$(DEFAULT_PKCS11_PROVIDER)"'
+AM_CPPFLAGS = -I$(top_srcdir)/src -D'DEFAULT_PKCS11_PROVIDER="$(DEFAULT_PKCS11_PROVIDER)"' -D'DEFAULT_ONEPIN_PKCS11_PROVIDER="$(DEFAULT_ONEPIN_PKCS11_PROVIDER)"'
LIBS = \
$(top_builddir)/src/libopensc/libopensc.la \
$(top_builddir)/src/common/libscdl.la \
@@ -127,6 +128,15 @@ if HAVE_UNKNOWN_WARNING_OPTION
opensc_asn1_CFLAGS += -Wno-unknown-warning-option
endif
+pkcs11_register_SOURCES = pkcs11-register.c fread_to_eof.c pkcs11-register-cmdline.c
+pkcs11_register_CFLAGS = -I$(top_srcdir)/src
+pkcs11_register_CFLAGS += -Wno-unused-but-set-variable -Wno-unused-function
+pkcs11_register_LDADD = \
+ $(top_builddir)/src/common/libpkcs11.la
+if HAVE_UNKNOWN_WARNING_OPTION
+pkcs11_register_CFLAGS += -Wno-unknown-warning-option
+endif
+
.PHONY: cmdline
cmdline:
for f in *.ggo.in; do $(do_subst) < "$$f" > "$${f%.in}"; done
@@ -139,6 +149,7 @@ piv_tool_SOURCES += versioninfo-tools.rc
opensc_explorer_SOURCES += versioninfo-tools.rc
pkcs15_tool_SOURCES += versioninfo-tools.rc
pkcs11_tool_SOURCES += versioninfo-tools.rc
+pkcs11_register_SOURCES += versioninfo-tools.rc
pkcs15_crypt_SOURCES += versioninfo-tools.rc
cryptoflex_tool_SOURCES += versioninfo-tools.rc
pkcs15_init_SOURCES += versioninfo-tools.rc
@@ -156,8 +167,18 @@ endif
applicationsdir = $(datadir)/applications
applications_DATA = org.opensc.notify.desktop
-org.opensc.notify.desktop: org.opensc.notify.desktop.in
- $(do_subst) < $(abs_srcdir)/org.opensc.notify.desktop.in > $@
+if ENABLE_AUTOSTART
+xdg_autostartdir = $(sysconfdir)/xdg/autostart
+xdg_autostart_DATA = pkcs11-register.desktop
+endif
+
+%.desktop: %.desktop.in
+ $(do_subst) < $< > $@
+
+noinst_DATA = pkcs11-register.plist
+
+%.plist: %.plist.in
+ $(do_subst) < $< > $@
clean-local:
- rm -f $(abs_builddir)/npa-tool.ggo $(abs_builddir)/opensc-notify.ggo $(abs_builddir)/opensc-asn1.ggo $(abs_builddir)/goid-tool.ggo $(abs_builddir)/egk-tool.ggo org.opensc.notify.desktop
+ rm -f $(abs_builddir)/npa-tool.ggo $(abs_builddir)/opensc-notify.ggo $(abs_builddir)/opensc-asn1.ggo $(abs_builddir)/goid-tool.ggo $(abs_builddir)/egk-tool.ggo org.opensc.notify.desktop pkcs11-register.desktop
diff --git a/src/tools/Makefile.mak b/src/tools/Makefile.mak
index ddc32894..4637a44d 100644
--- a/src/tools/Makefile.mak
+++ b/src/tools/Makefile.mak
@@ -7,7 +7,7 @@ default: all
TARGETS = opensc-tool.exe opensc-explorer.exe pkcs15-tool.exe pkcs15-crypt.exe \
pkcs11-tool.exe cardos-tool.exe eidenv.exe openpgp-tool.exe iasecc-tool.exe \
opensc-notify.exe egk-tool.exe goid-tool.exe paccess-tool.exe opensc-asn1.exe \
- $(PROGRAMS_OPENSSL)
+ pkcs11-register.exe $(PROGRAMS_OPENSSL)
OBJECTS = util.obj versioninfo-tools.res
@@ -27,24 +27,29 @@ opensc-notify.exe: opensc-notify-cmdline.obj versioninfo-opensc-notify.res $(LIB
link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj opensc-notify-cmdline.obj versioninfo-opensc-notify.res $(LIBS) gdi32.lib shell32.lib User32.lib ws2_32.lib
mt -manifest exe.manifest -outputresource:$@;1
-npa-tool.exe: npa-tool-cmdline.obj fread_to_eof.obj util.obj $(LIBS)
+npa-tool.exe: npa-tool-cmdline.obj fread_to_eof.obj $(OBJECTS) $(LIBS)
cl $(COPTS) /c $*.c
- link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj npa-tool-cmdline.obj fread_to_eof.obj util.obj $(LIBS) $(OPENPACE_LIB) $(OPENSSL_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib
+ link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj npa-tool-cmdline.obj fread_to_eof.obj $(OBJECTS) $(LIBS) $(OPENPACE_LIB) $(OPENSSL_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib
mt -manifest exe.manifest -outputresource:$@;1
-egk-tool.exe: egk-tool-cmdline.obj util.obj $(LIBS)
+egk-tool.exe: egk-tool-cmdline.obj $(OBJECTS) $(LIBS)
cl $(COPTS) /c $*.c
- link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj egk-tool-cmdline.obj util.obj $(LIBS) $(ZLIB_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib
+ link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj egk-tool-cmdline.obj $(OBJECTS) $(LIBS) $(ZLIB_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib
mt -manifest exe.manifest -outputresource:$@;1
-goid-tool.exe: goid-tool-cmdline.obj fread_to_eof.obj util.obj $(LIBS)
+goid-tool.exe: goid-tool-cmdline.obj fread_to_eof.obj $(OBJECTS) $(LIBS)
cl $(COPTS) /c $*.c
- link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj goid-tool-cmdline.obj fread_to_eof.obj util.obj $(LIBS) $(OPENPACE_LIB) $(OPENSSL_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib
+ link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj goid-tool-cmdline.obj fread_to_eof.obj $(OBJECTS) $(LIBS) $(OPENPACE_LIB) $(OPENSSL_LIB) gdi32.lib shell32.lib User32.lib ws2_32.lib
mt -manifest exe.manifest -outputresource:$@;1
-opensc-asn1.exe: opensc-asn1-cmdline.obj fread_to_eof.obj $(LIBS)
+opensc-asn1.exe: opensc-asn1-cmdline.obj fread_to_eof.obj versioninfo-tools.res $(LIBS)
cl $(COPTS) /c $*.c
- link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj opensc-asn1-cmdline.obj fread_to_eof.obj $(LIBS) gdi32.lib shell32.lib User32.lib ws2_32.lib
+ link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj opensc-asn1-cmdline.obj fread_to_eof.obj versioninfo-tools.res $(LIBS) gdi32.lib shell32.lib User32.lib ws2_32.lib
+ mt -manifest exe.manifest -outputresource:$@;1
+
+pkcs11-register.exe: pkcs11-register-cmdline.obj fread_to_eof.obj $(LIBS)
+ cl $(COPTS) /c $*.c
+ link $(LINKFLAGS) /pdb:$*.pdb /out:$@ $*.obj pkcs11-register-cmdline.obj fread_to_eof.obj versioninfo-tools.res $(LIBS) gdi32.lib shell32.lib User32.lib ws2_32.lib
mt -manifest exe.manifest -outputresource:$@;1
.c.exe:
diff --git a/src/tools/pkcs11-register-cmdline.c b/src/tools/pkcs11-register-cmdline.c
new file mode 100644
index 00000000..f7f0b001
--- /dev/null
+++ b/src/tools/pkcs11-register-cmdline.c
@@ -0,0 +1,586 @@
+/*
+ File autogenerated by gengetopt version 2.22.6
+ generated with the following command:
+ /usr/bin/gengetopt --file-name=pkcs11-register-cmdline --output-dir=.
+
+ The developers of gengetopt consider the fixed text that goes in all
+ gengetopt output files to be in the public domain:
+ we make no copyright claims on it.
+*/
+
+/* If we use autoconf. */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include
+#include
+#include
+
+#ifndef FIX_UNUSED
+#define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */
+#endif
+
+#include
+
+#include "pkcs11-register-cmdline.h"
+
+const char *gengetopt_args_info_purpose = "";
+
+const char *gengetopt_args_info_usage = "Usage: pkcs11-register [OPTIONS]...";
+
+const char *gengetopt_args_info_versiontext = "";
+
+const char *gengetopt_args_info_description = "Install a PKCS#11 module to known applications.";
+
+const char *gengetopt_args_info_help[] = {
+ " -h, --help Print help and exit",
+ " -V, --version Print version and exit",
+ " -m, --module=FILENAME Specify the module to load (default=`OpenSC's\n PKCS#11 module')",
+ " --skip-chrome Don't install module to Chrome (default=off)",
+ " --skip-firefox Don't install module to Firefox (default=off)",
+ " --skip-thunderbird Don't install module to Thunderbird (default=off)",
+ " --skip-seamonkey Don't install module to SeaMonkey (default=off)",
+ "\nReport bugs to https://github.com/OpenSC/OpenSC/issues\n\nWritten by Frank Morgner ",
+ 0
+};
+
+typedef enum {ARG_NO
+ , ARG_FLAG
+ , ARG_STRING
+} cmdline_parser_arg_type;
+
+static
+void clear_given (struct gengetopt_args_info *args_info);
+static
+void clear_args (struct gengetopt_args_info *args_info);
+
+static int
+cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info,
+ struct cmdline_parser_params *params, const char *additional_error);
+
+
+static char *
+gengetopt_strdup (const char *s);
+
+static
+void clear_given (struct gengetopt_args_info *args_info)
+{
+ args_info->help_given = 0 ;
+ args_info->version_given = 0 ;
+ args_info->module_given = 0 ;
+ args_info->skip_chrome_given = 0 ;
+ args_info->skip_firefox_given = 0 ;
+ args_info->skip_thunderbird_given = 0 ;
+ args_info->skip_seamonkey_given = 0 ;
+}
+
+static
+void clear_args (struct gengetopt_args_info *args_info)
+{
+ FIX_UNUSED (args_info);
+ args_info->module_arg = gengetopt_strdup ("OpenSC's PKCS#11 module");
+ args_info->module_orig = NULL;
+ args_info->skip_chrome_flag = 0;
+ args_info->skip_firefox_flag = 0;
+ args_info->skip_thunderbird_flag = 0;
+ args_info->skip_seamonkey_flag = 0;
+
+}
+
+static
+void init_args_info(struct gengetopt_args_info *args_info)
+{
+
+
+ args_info->help_help = gengetopt_args_info_help[0] ;
+ args_info->version_help = gengetopt_args_info_help[1] ;
+ args_info->module_help = gengetopt_args_info_help[2] ;
+ args_info->skip_chrome_help = gengetopt_args_info_help[3] ;
+ args_info->skip_firefox_help = gengetopt_args_info_help[4] ;
+ args_info->skip_thunderbird_help = gengetopt_args_info_help[5] ;
+ args_info->skip_seamonkey_help = gengetopt_args_info_help[6] ;
+
+}
+
+void
+cmdline_parser_print_version (void)
+{
+ printf ("%s %s\n",
+ (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE),
+ CMDLINE_PARSER_VERSION);
+
+ if (strlen(gengetopt_args_info_versiontext) > 0)
+ printf("\n%s\n", gengetopt_args_info_versiontext);
+}
+
+static void print_help_common(void) {
+ cmdline_parser_print_version ();
+
+ if (strlen(gengetopt_args_info_purpose) > 0)
+ printf("\n%s\n", gengetopt_args_info_purpose);
+
+ if (strlen(gengetopt_args_info_usage) > 0)
+ printf("\n%s\n", gengetopt_args_info_usage);
+
+ printf("\n");
+
+ if (strlen(gengetopt_args_info_description) > 0)
+ printf("%s\n\n", gengetopt_args_info_description);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+ int i = 0;
+ print_help_common();
+ while (gengetopt_args_info_help[i])
+ printf("%s\n", gengetopt_args_info_help[i++]);
+}
+
+void
+cmdline_parser_init (struct gengetopt_args_info *args_info)
+{
+ clear_given (args_info);
+ clear_args (args_info);
+ init_args_info (args_info);
+}
+
+void
+cmdline_parser_params_init(struct cmdline_parser_params *params)
+{
+ if (params)
+ {
+ params->override = 0;
+ params->initialize = 1;
+ params->check_required = 1;
+ params->check_ambiguity = 0;
+ params->print_errors = 1;
+ }
+}
+
+struct cmdline_parser_params *
+cmdline_parser_params_create(void)
+{
+ struct cmdline_parser_params *params =
+ (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params));
+ cmdline_parser_params_init(params);
+ return params;
+}
+
+static void
+free_string_field (char **s)
+{
+ if (*s)
+ {
+ free (*s);
+ *s = 0;
+ }
+}
+
+
+static void
+cmdline_parser_release (struct gengetopt_args_info *args_info)
+{
+
+ free_string_field (&(args_info->module_arg));
+ free_string_field (&(args_info->module_orig));
+
+
+
+ clear_given (args_info);
+}
+
+
+static void
+write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[])
+{
+ FIX_UNUSED (values);
+ if (arg) {
+ fprintf(outfile, "%s=\"%s\"\n", opt, arg);
+ } else {
+ fprintf(outfile, "%s\n", opt);
+ }
+}
+
+
+int
+cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
+{
+ int i = 0;
+
+ if (!outfile)
+ {
+ fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE);
+ return EXIT_FAILURE;
+ }
+
+ if (args_info->help_given)
+ write_into_file(outfile, "help", 0, 0 );
+ if (args_info->version_given)
+ write_into_file(outfile, "version", 0, 0 );
+ if (args_info->module_given)
+ write_into_file(outfile, "module", args_info->module_orig, 0);
+ if (args_info->skip_chrome_given)
+ write_into_file(outfile, "skip-chrome", 0, 0 );
+ if (args_info->skip_firefox_given)
+ write_into_file(outfile, "skip-firefox", 0, 0 );
+ if (args_info->skip_thunderbird_given)
+ write_into_file(outfile, "skip-thunderbird", 0, 0 );
+ if (args_info->skip_seamonkey_given)
+ write_into_file(outfile, "skip-seamonkey", 0, 0 );
+
+
+ i = EXIT_SUCCESS;
+ return i;
+}
+
+int
+cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)
+{
+ FILE *outfile;
+ int i = 0;
+
+ outfile = fopen(filename, "w");
+
+ if (!outfile)
+ {
+ fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename);
+ return EXIT_FAILURE;
+ }
+
+ i = cmdline_parser_dump(outfile, args_info);
+ fclose (outfile);
+
+ return i;
+}
+
+void
+cmdline_parser_free (struct gengetopt_args_info *args_info)
+{
+ cmdline_parser_release (args_info);
+}
+
+/** @brief replacement of strdup, which is not standard */
+char *
+gengetopt_strdup (const char *s)
+{
+ char *result = 0;
+ if (!s)
+ return result;
+
+ result = (char*)malloc(strlen(s) + 1);
+ if (result == (char*)0)
+ return (char*)0;
+ strcpy(result, s);
+ return result;
+}
+
+int
+cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info)
+{
+ return cmdline_parser2 (argc, argv, args_info, 0, 1, 1);
+}
+
+int
+cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info,
+ struct cmdline_parser_params *params)
+{
+ int result;
+ result = cmdline_parser_internal (argc, argv, args_info, params, 0);
+
+ if (result == EXIT_FAILURE)
+ {
+ cmdline_parser_free (args_info);
+ exit (EXIT_FAILURE);
+ }
+
+ return result;
+}
+
+int
+cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
+{
+ int result;
+ struct cmdline_parser_params params;
+
+ params.override = override;
+ params.initialize = initialize;
+ params.check_required = check_required;
+ params.check_ambiguity = 0;
+ params.print_errors = 1;
+
+ result = cmdline_parser_internal (argc, argv, args_info, ¶ms, 0);
+
+ if (result == EXIT_FAILURE)
+ {
+ cmdline_parser_free (args_info);
+ exit (EXIT_FAILURE);
+ }
+
+ return result;
+}
+
+int
+cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)
+{
+ FIX_UNUSED (args_info);
+ FIX_UNUSED (prog_name);
+ return EXIT_SUCCESS;
+}
+
+
+static char *package_name = 0;
+
+/**
+ * @brief updates an option
+ * @param field the generic pointer to the field to update
+ * @param orig_field the pointer to the orig field
+ * @param field_given the pointer to the number of occurrence of this option
+ * @param prev_given the pointer to the number of occurrence already seen
+ * @param value the argument for this option (if null no arg was specified)
+ * @param possible_values the possible values for this option (if specified)
+ * @param default_value the default value (in case the option only accepts fixed values)
+ * @param arg_type the type of this option
+ * @param check_ambiguity @see cmdline_parser_params.check_ambiguity
+ * @param override @see cmdline_parser_params.override
+ * @param no_free whether to free a possible previous value
+ * @param multiple_option whether this is a multiple option
+ * @param long_opt the corresponding long option
+ * @param short_opt the corresponding short option (or '-' if none)
+ * @param additional_error possible further error specification
+ */
+static
+int update_arg(void *field, char **orig_field,
+ unsigned int *field_given, unsigned int *prev_given,
+ char *value, const char *possible_values[],
+ const char *default_value,
+ cmdline_parser_arg_type arg_type,
+ int check_ambiguity, int override,
+ int no_free, int multiple_option,
+ const char *long_opt, char short_opt,
+ const char *additional_error)
+{
+ char *stop_char = 0;
+ const char *val = value;
+ int found;
+ char **string_field;
+ FIX_UNUSED (field);
+
+ stop_char = 0;
+ found = 0;
+
+ if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
+ {
+ if (short_opt != '-')
+ fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n",
+ package_name, long_opt, short_opt,
+ (additional_error ? additional_error : ""));
+ else
+ fprintf (stderr, "%s: `--%s' option given more than once%s\n",
+ package_name, long_opt,
+ (additional_error ? additional_error : ""));
+ return 1; /* failure */
+ }
+
+ FIX_UNUSED (default_value);
+
+ if (field_given && *field_given && ! override)
+ return 0;
+ if (prev_given)
+ (*prev_given)++;
+ if (field_given)
+ (*field_given)++;
+ if (possible_values)
+ val = possible_values[found];
+
+ switch(arg_type) {
+ case ARG_FLAG:
+ *((int *)field) = !*((int *)field);
+ break;
+ case ARG_STRING:
+ if (val) {
+ string_field = (char **)field;
+ if (!no_free && *string_field)
+ free (*string_field); /* free previous string */
+ *string_field = gengetopt_strdup (val);
+ }
+ break;
+ default:
+ break;
+ };
+
+
+ /* store the original value */
+ switch(arg_type) {
+ case ARG_NO:
+ case ARG_FLAG:
+ break;
+ default:
+ if (value && orig_field) {
+ if (no_free) {
+ *orig_field = value;
+ } else {
+ if (*orig_field)
+ free (*orig_field); /* free previous string */
+ *orig_field = gengetopt_strdup (value);
+ }
+ }
+ };
+
+ return 0; /* OK */
+}
+
+
+int
+cmdline_parser_internal (
+ int argc, char **argv, struct gengetopt_args_info *args_info,
+ struct cmdline_parser_params *params, const char *additional_error)
+{
+ int c; /* Character of the parsed option. */
+
+ int error_occurred = 0;
+ struct gengetopt_args_info local_args_info;
+
+ int override;
+ int initialize;
+ int check_required;
+ int check_ambiguity;
+
+ package_name = argv[0];
+
+ override = params->override;
+ initialize = params->initialize;
+ check_required = params->check_required;
+ check_ambiguity = params->check_ambiguity;
+
+ if (initialize)
+ cmdline_parser_init (args_info);
+
+ cmdline_parser_init (&local_args_info);
+
+ optarg = 0;
+ optind = 0;
+ opterr = params->print_errors;
+ optopt = '?';
+
+ while (1)
+ {
+ int option_index = 0;
+
+ static struct option long_options[] = {
+ { "help", 0, NULL, 'h' },
+ { "version", 0, NULL, 'V' },
+ { "module", 1, NULL, 'm' },
+ { "skip-chrome", 0, NULL, 0 },
+ { "skip-firefox", 0, NULL, 0 },
+ { "skip-thunderbird", 0, NULL, 0 },
+ { "skip-seamonkey", 0, NULL, 0 },
+ { 0, 0, 0, 0 }
+ };
+
+ c = getopt_long (argc, argv, "hVm:", long_options, &option_index);
+
+ if (c == -1) break; /* Exit from `while (1)' loop. */
+
+ switch (c)
+ {
+ case 'h': /* Print help and exit. */
+ cmdline_parser_print_help ();
+ cmdline_parser_free (&local_args_info);
+ exit (EXIT_SUCCESS);
+
+ case 'V': /* Print version and exit. */
+ cmdline_parser_print_version ();
+ cmdline_parser_free (&local_args_info);
+ exit (EXIT_SUCCESS);
+
+ case 'm': /* Specify the module to load. */
+
+
+ if (update_arg( (void *)&(args_info->module_arg),
+ &(args_info->module_orig), &(args_info->module_given),
+ &(local_args_info.module_given), optarg, 0, "OpenSC's PKCS#11 module", ARG_STRING,
+ check_ambiguity, override, 0, 0,
+ "module", 'm',
+ additional_error))
+ goto failure;
+
+ break;
+
+ case 0: /* Long option with no short option */
+ /* Don't install module to Chrome. */
+ if (strcmp (long_options[option_index].name, "skip-chrome") == 0)
+ {
+
+
+ if (update_arg((void *)&(args_info->skip_chrome_flag), 0, &(args_info->skip_chrome_given),
+ &(local_args_info.skip_chrome_given), optarg, 0, 0, ARG_FLAG,
+ check_ambiguity, override, 1, 0, "skip-chrome", '-',
+ additional_error))
+ goto failure;
+
+ }
+ /* Don't install module to Firefox. */
+ else if (strcmp (long_options[option_index].name, "skip-firefox") == 0)
+ {
+
+
+ if (update_arg((void *)&(args_info->skip_firefox_flag), 0, &(args_info->skip_firefox_given),
+ &(local_args_info.skip_firefox_given), optarg, 0, 0, ARG_FLAG,
+ check_ambiguity, override, 1, 0, "skip-firefox", '-',
+ additional_error))
+ goto failure;
+
+ }
+ /* Don't install module to Thunderbird. */
+ else if (strcmp (long_options[option_index].name, "skip-thunderbird") == 0)
+ {
+
+
+ if (update_arg((void *)&(args_info->skip_thunderbird_flag), 0, &(args_info->skip_thunderbird_given),
+ &(local_args_info.skip_thunderbird_given), optarg, 0, 0, ARG_FLAG,
+ check_ambiguity, override, 1, 0, "skip-thunderbird", '-',
+ additional_error))
+ goto failure;
+
+ }
+ /* Don't install module to SeaMonkey. */
+ else if (strcmp (long_options[option_index].name, "skip-seamonkey") == 0)
+ {
+
+
+ if (update_arg((void *)&(args_info->skip_seamonkey_flag), 0, &(args_info->skip_seamonkey_given),
+ &(local_args_info.skip_seamonkey_given), optarg, 0, 0, ARG_FLAG,
+ check_ambiguity, override, 1, 0, "skip-seamonkey", '-',
+ additional_error))
+ goto failure;
+
+ }
+
+ break;
+ case '?': /* Invalid option. */
+ /* `getopt_long' already printed an error message. */
+ goto failure;
+
+ default: /* bug: option not considered. */
+ fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
+ abort ();
+ } /* switch */
+ } /* while */
+
+
+
+
+ cmdline_parser_release (&local_args_info);
+
+ if ( error_occurred )
+ return (EXIT_FAILURE);
+
+ return 0;
+
+failure:
+
+ cmdline_parser_release (&local_args_info);
+ return (EXIT_FAILURE);
+}
diff --git a/src/tools/pkcs11-register-cmdline.h b/src/tools/pkcs11-register-cmdline.h
new file mode 100644
index 00000000..8b38526a
--- /dev/null
+++ b/src/tools/pkcs11-register-cmdline.h
@@ -0,0 +1,189 @@
+/** @file pkcs11-register-cmdline.h
+ * @brief The header file for the command line option parser
+ * generated by GNU Gengetopt version 2.22.6
+ * http://www.gnu.org/software/gengetopt.
+ * DO NOT modify this file, since it can be overwritten
+ * @author GNU Gengetopt by Lorenzo Bettini */
+
+#ifndef PKCS11_REGISTER_CMDLINE_H
+#define PKCS11_REGISTER_CMDLINE_H
+
+/* If we use autoconf. */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include /* for FILE */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifndef CMDLINE_PARSER_PACKAGE
+/** @brief the program name (used for printing errors) */
+#define CMDLINE_PARSER_PACKAGE "pkcs11-register"
+#endif
+
+#ifndef CMDLINE_PARSER_PACKAGE_NAME
+/** @brief the complete program name (used for help and version) */
+#define CMDLINE_PARSER_PACKAGE_NAME "pkcs11-register"
+#endif
+
+#ifndef CMDLINE_PARSER_VERSION
+/** @brief the program version */
+#define CMDLINE_PARSER_VERSION VERSION
+#endif
+
+/** @brief Where the command line options are stored */
+struct gengetopt_args_info
+{
+ const char *help_help; /**< @brief Print help and exit help description. */
+ const char *version_help; /**< @brief Print version and exit help description. */
+ char * module_arg; /**< @brief Specify the module to load (default='OpenSC's PKCS#11 module'). */
+ char * module_orig; /**< @brief Specify the module to load original value given at command line. */
+ const char *module_help; /**< @brief Specify the module to load help description. */
+ int skip_chrome_flag; /**< @brief Don't install module to Chrome (default=off). */
+ const char *skip_chrome_help; /**< @brief Don't install module to Chrome help description. */
+ int skip_firefox_flag; /**< @brief Don't install module to Firefox (default=off). */
+ const char *skip_firefox_help; /**< @brief Don't install module to Firefox help description. */
+ int skip_thunderbird_flag; /**< @brief Don't install module to Thunderbird (default=off). */
+ const char *skip_thunderbird_help; /**< @brief Don't install module to Thunderbird help description. */
+ int skip_seamonkey_flag; /**< @brief Don't install module to SeaMonkey (default=off). */
+ const char *skip_seamonkey_help; /**< @brief Don't install module to SeaMonkey help description. */
+
+ unsigned int help_given ; /**< @brief Whether help was given. */
+ unsigned int version_given ; /**< @brief Whether version was given. */
+ unsigned int module_given ; /**< @brief Whether module was given. */
+ unsigned int skip_chrome_given ; /**< @brief Whether skip-chrome was given. */
+ unsigned int skip_firefox_given ; /**< @brief Whether skip-firefox was given. */
+ unsigned int skip_thunderbird_given ; /**< @brief Whether skip-thunderbird was given. */
+ unsigned int skip_seamonkey_given ; /**< @brief Whether skip-seamonkey was given. */
+
+} ;
+
+/** @brief The additional parameters to pass to parser functions */
+struct cmdline_parser_params
+{
+ int override; /**< @brief whether to override possibly already present options (default 0) */
+ int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */
+ int check_required; /**< @brief whether to check that all required options were provided (default 1) */
+ int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */
+ int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */
+} ;
+
+/** @brief the purpose string of the program */
+extern const char *gengetopt_args_info_purpose;
+/** @brief the usage string of the program */
+extern const char *gengetopt_args_info_usage;
+/** @brief the description string of the program */
+extern const char *gengetopt_args_info_description;
+/** @brief all the lines making the help output */
+extern const char *gengetopt_args_info_help[];
+
+/**
+ * The command line parser
+ * @param argc the number of command line options
+ * @param argv the command line options
+ * @param args_info the structure where option information will be stored
+ * @return 0 if everything went fine, NON 0 if an error took place
+ */
+int cmdline_parser (int argc, char **argv,
+ struct gengetopt_args_info *args_info);
+
+/**
+ * The command line parser (version with additional parameters - deprecated)
+ * @param argc the number of command line options
+ * @param argv the command line options
+ * @param args_info the structure where option information will be stored
+ * @param override whether to override possibly already present options
+ * @param initialize whether to initialize the option structure my_args_info
+ * @param check_required whether to check that all required options were provided
+ * @return 0 if everything went fine, NON 0 if an error took place
+ * @deprecated use cmdline_parser_ext() instead
+ */
+int cmdline_parser2 (int argc, char **argv,
+ struct gengetopt_args_info *args_info,
+ int override, int initialize, int check_required);
+
+/**
+ * The command line parser (version with additional parameters)
+ * @param argc the number of command line options
+ * @param argv the command line options
+ * @param args_info the structure where option information will be stored
+ * @param params additional parameters for the parser
+ * @return 0 if everything went fine, NON 0 if an error took place
+ */
+int cmdline_parser_ext (int argc, char **argv,
+ struct gengetopt_args_info *args_info,
+ struct cmdline_parser_params *params);
+
+/**
+ * Save the contents of the option struct into an already open FILE stream.
+ * @param outfile the stream where to dump options
+ * @param args_info the option struct to dump
+ * @return 0 if everything went fine, NON 0 if an error took place
+ */
+int cmdline_parser_dump(FILE *outfile,
+ struct gengetopt_args_info *args_info);
+
+/**
+ * Save the contents of the option struct into a (text) file.
+ * This file can be read by the config file parser (if generated by gengetopt)
+ * @param filename the file where to save
+ * @param args_info the option struct to save
+ * @return 0 if everything went fine, NON 0 if an error took place
+ */
+int cmdline_parser_file_save(const char *filename,
+ struct gengetopt_args_info *args_info);
+
+/**
+ * Print the help
+ */
+void cmdline_parser_print_help(void);
+/**
+ * Print the version
+ */
+void cmdline_parser_print_version(void);
+
+/**
+ * Initializes all the fields a cmdline_parser_params structure
+ * to their default values
+ * @param params the structure to initialize
+ */
+void cmdline_parser_params_init(struct cmdline_parser_params *params);
+
+/**
+ * Allocates dynamically a cmdline_parser_params structure and initializes
+ * all its fields to their default values
+ * @return the created and initialized cmdline_parser_params structure
+ */
+struct cmdline_parser_params *cmdline_parser_params_create(void);
+
+/**
+ * Initializes the passed gengetopt_args_info structure's fields
+ * (also set default values for options that have a default)
+ * @param args_info the structure to initialize
+ */
+void cmdline_parser_init (struct gengetopt_args_info *args_info);
+/**
+ * Deallocates the string fields of the gengetopt_args_info structure
+ * (but does not deallocate the structure itself)
+ * @param args_info the structure to deallocate
+ */
+void cmdline_parser_free (struct gengetopt_args_info *args_info);
+
+/**
+ * Checks that all the required options were specified
+ * @param args_info the structure to check
+ * @param prog_name the name of the program that will be used to print
+ * possible errors
+ * @return
+ */
+int cmdline_parser_required (struct gengetopt_args_info *args_info,
+ const char *prog_name);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* PKCS11_REGISTER_CMDLINE_H */
diff --git a/src/tools/pkcs11-register.c b/src/tools/pkcs11-register.c
new file mode 100644
index 00000000..0df3a399
--- /dev/null
+++ b/src/tools/pkcs11-register.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2019 Frank Morgner
+ *
+ * This file is part of OpenSC.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "fread_to_eof.h"
+#include "pkcs11-register-cmdline.h"
+#include
+#include
+#include
+
+#ifdef _WIN32
+#include
+const char path_sep = '\\';
+#else
+const char path_sep = '/';
+#endif
+
+const char *default_pkcs11_provider = DEFAULT_PKCS11_PROVIDER;
+const char *default_onepin_pkcs11_provider = DEFAULT_ONEPIN_PKCS11_PROVIDER;
+
+int
+get_profiles_ini(const char *home, const char *basedir, char **profiles_ini)
+{
+ size_t profiles_ini_len = 0;
+ char profiles_ini_path[PATH_MAX];
+ if (home && basedir
+ && 0 <= snprintf(profiles_ini_path, sizeof profiles_ini_path,
+ "%s%c%s%c%s", home, path_sep, basedir, path_sep, "profiles.ini")
+ && fread_to_eof(profiles_ini_path,
+ (unsigned char **) profiles_ini, &profiles_ini_len)) {
+ char *p = realloc(*profiles_ini, profiles_ini_len+1);
+ if (p) {
+ p[profiles_ini_len] = '\0';
+ *profiles_ini = p;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+const char *
+get_next_profile_path(const char **profiles_ini, const char *home, const char *basedir)
+{
+ static char profile_path[PATH_MAX];
+
+ if (!home || !profiles_ini)
+ return NULL;
+
+ while (*profiles_ini) {
+ const char *this_profile = strstr(*profiles_ini, "[");
+ if (!this_profile) {
+ return NULL;
+ }
+
+ const char *next_profile = strstr(this_profile + 1, "[");
+ const char *is_relative = strstr(this_profile, "IsRelative=1");
+ const char *path = strstr(this_profile, "Path=");
+
+ /* advance profile_ini for the next iteration */
+ if (next_profile) {
+ *profiles_ini = next_profile;
+
+ if (next_profile < path) {
+ /* path belongs to the next profile */
+ path = NULL;
+ }
+ if (next_profile < is_relative) {
+ /* IsRelative belongs to the next profile */
+ is_relative = NULL;
+ }
+ } else {
+ *profiles_ini = NULL;
+ }
+
+ if (!path)
+ continue;
+
+ /* build the path to the profile */
+ char *p = profile_path;
+ size_t p_len = sizeof profile_path;
+ if (is_relative) {
+ size_t l = strlen(home) + sizeof path_sep + strlen(basedir) + sizeof path_sep;
+ if (0 > snprintf(p, p_len, "%s%c%s%c", home, path_sep, basedir, path_sep))
+ continue;
+ p_len -= l;
+ p += l;
+ }
+ /* adjust format to respect the maximum length of profile_path */
+ char format[32];
+ if (0 > snprintf(format, sizeof(format), "Path=%%%ds", (int)(p_len-1))
+ || 1 != sscanf(path, format, p))
+ continue;
+
+ return profile_path;
+ }
+
+ return NULL;
+}
+
+void
+add_module_pkcs11_txt(const char *profile_dir,
+ const char *module_path, const char *module_name)
+{
+ char pkcs11_txt_path[PATH_MAX];
+ char *pkcs11_txt = NULL;
+ size_t pkcs11_txt_len = 0;
+ if (!profile_dir
+ || snprintf(pkcs11_txt_path, sizeof pkcs11_txt_path,
+ "%s%c%s", profile_dir, path_sep, "pkcs11.txt") < 0
+ || !fread_to_eof(pkcs11_txt_path,
+ (unsigned char **) &pkcs11_txt, &pkcs11_txt_len)) {
+ goto err;
+ }
+ char *p = realloc(pkcs11_txt, pkcs11_txt_len+1);
+ if (!p)
+ goto err;
+ p[pkcs11_txt_len] = '\0';
+ pkcs11_txt = p;
+
+ if (!strstr(pkcs11_txt, module_path)) {
+ /* module is not yet present */
+ FILE *f = fopen(pkcs11_txt_path, "a");
+ if (f) {
+ if (fprintf(f,
+ "library=%s\n"
+ "name=%s\n"
+ "\n", module_path, module_name) >= 0) {
+ printf("Added %s to %s\n", module_name, pkcs11_txt_path);
+ }
+ fclose(f);
+ }
+ }
+err:
+ free(pkcs11_txt);
+}
+
+struct location {
+ const char *var;
+ const char *dir;
+};
+
+void
+add_module_mozilla(const struct location *locations, size_t locations_len,
+ const char *module_path, const char *module_name)
+{
+ size_t i;
+
+ for (i = 0; i < locations_len; i++) {
+ char *profiles_ini = NULL;
+ const char *home = getenv(locations[i].var);
+ if (!home)
+ continue;
+
+ if (get_profiles_ini(home, locations[i].dir, &profiles_ini)) {
+ const char *p = profiles_ini;
+
+ while (1) {
+ const char *profile_path = get_next_profile_path(&p, home, locations[i].dir);
+ if (!profile_path)
+ break;
+ add_module_pkcs11_txt(profile_path, module_path, module_name);
+ }
+ }
+ free(profiles_ini);
+ }
+}
+
+#include "pkcs11/pkcs11.h"
+#include "common/libpkcs11.h"
+
+const char *
+get_module_name(const char *module_path)
+{
+ const char *name = NULL;
+ CK_FUNCTION_LIST_PTR p11 = NULL;
+ void *module = C_LoadModule(module_path, &p11);
+ if (module) {
+ CK_INFO info;
+ if (CKR_OK == p11->C_Initialize(NULL)
+ && CKR_OK == p11->C_GetInfo(&info)) {
+ static char module_name[32+sizeof " (255.255)"];
+ int libraryDescription_len = 32;
+
+ while (libraryDescription_len > 0
+ && info.libraryDescription[libraryDescription_len-1] == ' ')
+ libraryDescription_len--;
+
+ snprintf(module_name, sizeof module_name,
+ "%.*s (%d.%d)",
+ libraryDescription_len, info.libraryDescription,
+ info.libraryVersion.major, info.libraryVersion.minor);
+
+ name = module_name;
+ }
+ p11->C_Finalize(NULL);
+ C_UnloadModule(module);
+ }
+ return name;
+}
+
+void
+add_module_firefox(const char *module_path, const char *module_name)
+{
+ struct location locations[] = {
+#if defined(__APPLE__)
+ {"HOME", "Library/Application Support/Firefox"},
+ {"HOME", "Library/Mozilla/Firefox"},
+#elif defined(_WIN32)
+ {"APPDATA", "Mozilla\\Firefox"},
+#else
+ {"HOME", ".mozilla/firefox"},
+#endif
+ };
+
+ if (0 == strcmp(module_path, default_pkcs11_provider))
+ module_path = default_onepin_pkcs11_provider;
+
+ add_module_mozilla(locations, sizeof locations/sizeof *locations,
+ module_path, module_name);
+}
+
+void
+add_module_thunderbird(const char *module_path, const char *module_name)
+{
+ struct location locations[] = {
+#if defined(__APPLE__)
+ {"HOME", "Library/Application Support/Thunderbird"},
+ {"HOME", "Library/Mozilla/Thunderbird"},
+#elif defined(_WIN32)
+ {"APPDATA", "Mozilla\\Thunderbird"},
+#else
+ {"HOME", ".thunderbird"},
+ {"HOME", ".mozilla-thunderbird"},
+#endif
+ };
+
+ add_module_mozilla(locations, sizeof locations/sizeof *locations,
+ module_path, module_name);
+}
+
+void
+add_module_seamonkey(const char *module_path, const char *module_name)
+{
+ struct location locations[] = {
+#if defined(__APPLE__)
+ {"HOME", "Library/Application Support/SeaMonkey"},
+ {"HOME", "Library/Mozilla/SeaMonkey"},
+#elif defined(_WIN32)
+ {"APPDATA", "Mozilla\\SeaMonkey"},
+#else
+ {"HOME", ".mozilla/seamonkey"},
+#endif
+ };
+
+ add_module_mozilla(locations, sizeof locations/sizeof *locations,
+ module_path, module_name);
+}
+
+void
+add_module_chrome(const char *module_path, const char *module_name)
+{
+#if defined(__APPLE__) || defined(_WIN32)
+ /* OS specific framework will be used by Chrome instead of PKCS#11 */
+#else
+ char profile_path[PATH_MAX];
+ const char *home = getenv("HOME");
+ if (home && 0 <= snprintf(profile_path, sizeof profile_path,
+ "%s%c%s", home, path_sep, ".pki/nssdb")) {
+ add_module_pkcs11_txt(profile_path, module_path, module_name);
+ }
+#endif
+}
+
+#define expand(path, expanded, len) \
+ len = ExpandEnvironmentStringsA(path, \
+ expanded, sizeof expanded); \
+ if (0 < len && len < sizeof expanded) \
+ path = expanded;
+
+int
+main(int argc, char **argv)
+{
+ struct gengetopt_args_info cmdline;
+
+ if (cmdline_parser(argc, argv, &cmdline) != 0)
+ return 1;
+
+ const char *module_path = cmdline.module_arg;
+ if (!cmdline.module_given)
+ module_path = default_pkcs11_provider;
+#ifdef _WIN32
+ DWORD expanded_len;
+ char module_path_expanded[PATH_MAX], default_expanded[PATH_MAX], onepin_expanded[PATH_MAX];
+ expand(module_path, module_path_expanded, expanded_len);
+ expand(default_pkcs11_provider, default_expanded, expanded_len);
+ expand(default_onepin_pkcs11_provider, onepin_expanded, expanded_len);
+#endif
+
+ const char *module_name = get_module_name(module_path);
+ if (!module_name) {
+ fprintf(stderr, "Could not load initialize %s\n", module_path);
+ return 1;
+ }
+
+ if (!cmdline.skip_chrome_flag)
+ add_module_chrome(module_path, module_name);
+ if (!cmdline.skip_firefox_flag)
+ add_module_firefox(module_path, module_name);
+ if (!cmdline.skip_thunderbird_flag)
+ add_module_thunderbird(module_path, module_name);
+ if (!cmdline.skip_seamonkey_flag)
+ add_module_seamonkey(module_path, module_name);
+
+ cmdline_parser_free (&cmdline);
+
+ return 0;
+}
diff --git a/src/tools/pkcs11-register.desktop.in b/src/tools/pkcs11-register.desktop.in
new file mode 100644
index 00000000..ea6a5140
--- /dev/null
+++ b/src/tools/pkcs11-register.desktop.in
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Name=Install OpenSC PKCS#11 module
+Type=Application
+Exec=@bindir@/pkcs11-register
+Categories=Security;System;
+X-GNOME-AutoRestart=true
+X-GNOME-Autostart-Phase=Initialization
+NoDisplay=true
diff --git a/src/tools/pkcs11-register.ggo.in b/src/tools/pkcs11-register.ggo.in
new file mode 100644
index 00000000..30c771bc
--- /dev/null
+++ b/src/tools/pkcs11-register.ggo.in
@@ -0,0 +1,28 @@
+package "pkcs11-register"
+purpose "@PACKAGE_SUMMARY@"
+description "Install a PKCS#11 module to known applications."
+
+option "module" m
+ "Specify the module to load"
+ string optional default="OpenSC's PKCS#11 module" typestr="FILENAME"
+
+option "skip-chrome" -
+ "Don't install module to Chrome"
+ flag off
+
+option "skip-firefox" -
+ "Don't install module to Firefox"
+ flag off
+
+option "skip-thunderbird" -
+ "Don't install module to Thunderbird"
+ flag off
+
+option "skip-seamonkey" -
+ "Don't install module to SeaMonkey"
+ flag off
+
+text "
+Report bugs to @PACKAGE_BUGREPORT@
+
+Written by Frank Morgner "
diff --git a/src/tools/pkcs11-register.plist.in b/src/tools/pkcs11-register.plist.in
new file mode 100644
index 00000000..1582ee56
--- /dev/null
+++ b/src/tools/pkcs11-register.plist.in
@@ -0,0 +1,14 @@
+
+
+
+
+ Label
+ pkcs11-register
+ ProgramArguments
+
+ @bindir@/pkcs11-register
+
+ RunAtLoad
+
+
+
diff --git a/win32/OpenSC.wxs.in b/win32/OpenSC.wxs.in
index 6154e85a..7cbda4c1 100644
--- a/win32/OpenSC.wxs.in
+++ b/win32/OpenSC.wxs.in
@@ -52,6 +52,7 @@
+
@@ -145,6 +146,9 @@
+
+
+
@@ -201,6 +205,11 @@
+
+
+
+
+
@@ -367,6 +376,7 @@
+
@@ -421,6 +431,9 @@
+
+
+
@@ -443,6 +456,11 @@
+
+
+
+
+
diff --git a/win32/winconfig.h.in b/win32/winconfig.h.in
index 9f44251e..94ed9b54 100644
--- a/win32/winconfig.h.in
+++ b/win32/winconfig.h.in
@@ -99,6 +99,9 @@
#ifndef DEFAULT_PKCS11_PROVIDER
#define DEFAULT_PKCS11_PROVIDER "@DEFAULT_PKCS11_PROVIDER@"
#endif
+#ifndef DEFAULT_ONEPIN_PKCS11_PROVIDER
+#define DEFAULT_ONEPIN_PKCS11_PROVIDER "@DEFAULT_ONEPIN_PKCS11_PROVIDER@"
+#endif
#ifndef DEFAULT_SM_MODULE
#define DEFAULT_SM_MODULE "@DEFAULT_SM_MODULE@"