dirmngr,gpgsm: Return NULL on fail
[gnupg.git] / sm / gpgsm.c
index 94826ce..72bceb4 100644 (file)
@@ -1,6 +1,6 @@
-/* gpgsm.c - GnuPG for S/MIME 
- * Copyright (C) 2001, 2002, 2003, 2004, 2005,
- *               2006, 2007, 2008  Free Software Foundation, Inc.
+/* gpgsm.c - GnuPG for S/MIME
+ * Copyright (C) 2001-2008, 2010  Free Software Foundation, Inc.
+ * Copyright (C) 2001-2008, 2010  Werner Koch
  *
  * This file is part of GnuPG.
  *
  *
  * This file is part of GnuPG.
  *
@@ -37,6 +37,8 @@
 #include "keydb.h"
 #include "sysutils.h"
 #include "gc-opt-flags.h"
 #include "keydb.h"
 #include "sysutils.h"
 #include "gc-opt-flags.h"
+#include "asshelp.h"
+#include "../common/init.h"
 
 
 #ifndef O_BINARY
 
 
 #ifndef O_BINARY
@@ -66,14 +68,15 @@ enum cmd_and_opt_values {
   aDeleteKey,
   aImport,
   aVerify,
   aDeleteKey,
   aImport,
   aVerify,
-  aVerifyFiles,
   aListExternalKeys,
   aListChain,
   aSendKeys,
   aRecvKeys,
   aExport,
   aExportSecretKeyP12,
   aListExternalKeys,
   aListChain,
   aSendKeys,
   aRecvKeys,
   aExport,
   aExportSecretKeyP12,
-  aServer,                        
+  aExportSecretKeyP8,
+  aExportSecretKeyRaw,
+  aServer,
   aLearnCard,
   aCallDirmngr,
   aCallProtectTool,
   aLearnCard,
   aCallDirmngr,
   aCallProtectTool,
@@ -100,6 +103,7 @@ enum cmd_and_opt_values {
   oLogFile,
   oNoLogFile,
   oAuditLog,
   oLogFile,
   oNoLogFile,
   oAuditLog,
+  oHtmlAuditLog,
 
   oEnableSpecialFilenames,
 
 
   oEnableSpecialFilenames,
 
@@ -140,9 +144,11 @@ enum cmd_and_opt_values {
   oDisablePolicyChecks,
   oEnablePolicyChecks,
   oAutoIssuerKeyRetrieve,
   oDisablePolicyChecks,
   oEnablePolicyChecks,
   oAutoIssuerKeyRetrieve,
-  
+
   oWithFingerprint,
   oWithMD5Fingerprint,
   oWithFingerprint,
   oWithMD5Fingerprint,
+  oWithKeygrip,
+  oWithSecret,
   oAnswerYes,
   oAnswerNo,
   oKeyring,
   oAnswerYes,
   oAnswerNo,
   oKeyring,
@@ -176,7 +182,9 @@ enum cmd_and_opt_values {
   oDisablePubkeyAlgo,
   oIgnoreTimeConflict,
   oNoRandomSeedFile,
   oDisablePubkeyAlgo,
   oIgnoreTimeConflict,
   oNoRandomSeedFile,
-  oNoCommonCertsImport
+  oNoCommonCertsImport,
+  oIgnoreCertExtension,
+  oNoAutostart
  };
 
 
  };
 
 
@@ -185,30 +193,35 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_group (300, N_("@Commands:\n ")),
 
   ARGPARSE_c (aSign, "sign", N_("make a signature")),
   ARGPARSE_group (300, N_("@Commands:\n ")),
 
   ARGPARSE_c (aSign, "sign", N_("make a signature")),
-  ARGPARSE_c (aClearsign, "clearsign", N_("make a clear text signature") ),
+/*ARGPARSE_c (aClearsign, "clearsign", N_("make a clear text signature") ),*/
   ARGPARSE_c (aDetachedSign, "detach-sign", N_("make a detached signature")),
   ARGPARSE_c (aEncr, "encrypt", N_("encrypt data")),
   ARGPARSE_c (aDetachedSign, "detach-sign", N_("make a detached signature")),
   ARGPARSE_c (aEncr, "encrypt", N_("encrypt data")),
-  ARGPARSE_c (aSym, "symmetric", N_("encryption only with symmetric cipher")),
+/*ARGPARSE_c (aSym, "symmetric", N_("encryption only with symmetric cipher")),*/
   ARGPARSE_c (aDecrypt, "decrypt", N_("decrypt data (default)")),
   ARGPARSE_c (aVerify, "verify",  N_("verify a signature")),
   ARGPARSE_c (aDecrypt, "decrypt", N_("decrypt data (default)")),
   ARGPARSE_c (aVerify, "verify",  N_("verify a signature")),
-  ARGPARSE_c (aVerifyFiles, "verify-files", "@"),
   ARGPARSE_c (aListKeys, "list-keys", N_("list keys")),
   ARGPARSE_c (aListKeys, "list-keys", N_("list keys")),
-  ARGPARSE_c (aListExternalKeys, "list-external-keys", 
+  ARGPARSE_c (aListExternalKeys, "list-external-keys",
               N_("list external keys")),
   ARGPARSE_c (aListSecretKeys, "list-secret-keys", N_("list secret keys")),
               N_("list external keys")),
   ARGPARSE_c (aListSecretKeys, "list-secret-keys", N_("list secret keys")),
-  ARGPARSE_c (aListChain,   "list-chain",  N_("list certificate chain")), 
+  ARGPARSE_c (aListChain,   "list-chain",  N_("list certificate chain")),
   ARGPARSE_c (aFingerprint, "fingerprint", N_("list keys and fingerprints")),
   ARGPARSE_c (aFingerprint, "fingerprint", N_("list keys and fingerprints")),
-  ARGPARSE_c (aKeygen, "gen-key", "@"),
-  ARGPARSE_c (aDeleteKey, "delete-keys", 
+  ARGPARSE_c (aKeygen, "gen-key", N_("generate a new key pair")),
+  ARGPARSE_c (aDeleteKey, "delete-keys",
               N_("remove keys from the public keyring")),
               N_("remove keys from the public keyring")),
-  ARGPARSE_c (aSendKeys, "send-keys", N_("export keys to a key server")),
-  ARGPARSE_c (aRecvKeys, "recv-keys", N_("import keys from a key server")),
+/*ARGPARSE_c (aSendKeys, "send-keys", N_("export keys to a key server")),*/
+/*ARGPARSE_c (aRecvKeys, "recv-keys", N_("import keys from a key server")),*/
   ARGPARSE_c (aImport, "import", N_("import certificates")),
   ARGPARSE_c (aExport, "export", N_("export certificates")),
   ARGPARSE_c (aImport, "import", N_("import certificates")),
   ARGPARSE_c (aExport, "export", N_("export certificates")),
-  ARGPARSE_c (aExportSecretKeyP12, "export-secret-key-p12", "@"), 
+
+  /* We use -raw and not -p1 for pkcs#1 secret key export so that it
+     won't accidently be used in case -p12 was intended.  */
+  ARGPARSE_c (aExportSecretKeyP12, "export-secret-key-p12", "@"),
+  ARGPARSE_c (aExportSecretKeyP8,  "export-secret-key-p8", "@"),
+  ARGPARSE_c (aExportSecretKeyRaw, "export-secret-key-raw", "@"),
+
   ARGPARSE_c (aLearnCard, "learn-card", N_("register a smartcard")),
   ARGPARSE_c (aServer, "server", N_("run in server mode")),
   ARGPARSE_c (aLearnCard, "learn-card", N_("register a smartcard")),
   ARGPARSE_c (aServer, "server", N_("run in server mode")),
-  ARGPARSE_c (aCallDirmngr, "call-dirmngr", 
+  ARGPARSE_c (aCallDirmngr, "call-dirmngr",
               N_("pass a command to the dirmngr")),
   ARGPARSE_c (aCallProtectTool, "call-protect-tool",
               N_("invoke gpg-protect-tool")),
               N_("pass a command to the dirmngr")),
   ARGPARSE_c (aCallProtectTool, "call-protect-tool",
               N_("invoke gpg-protect-tool")),
@@ -231,24 +244,23 @@ static ARGPARSE_OPTS opts[] = {
 
   ARGPARSE_s_s (oP12Charset, "p12-charset", "@"),
 
 
   ARGPARSE_s_s (oP12Charset, "p12-charset", "@"),
 
-  ARGPARSE_s_n (oAssumeArmor, "assume-armor", 
+  ARGPARSE_s_n (oAssumeArmor, "assume-armor",
                 N_("assume input is in PEM format")),
   ARGPARSE_s_n (oAssumeBase64, "assume-base64",
                 N_("assume input is in base-64 format")),
                 N_("assume input is in PEM format")),
   ARGPARSE_s_n (oAssumeBase64, "assume-base64",
                 N_("assume input is in base-64 format")),
-  ARGPARSE_s_n (oAssumeBinary, "assume-binary", 
+  ARGPARSE_s_n (oAssumeBinary, "assume-binary",
                 N_("assume input is in binary format")),
 
   ARGPARSE_s_s (oRecipient, "recipient", N_("|USER-ID|encrypt for USER-ID")),
 
                 N_("assume input is in binary format")),
 
   ARGPARSE_s_s (oRecipient, "recipient", N_("|USER-ID|encrypt for USER-ID")),
 
-  ARGPARSE_s_n (oPreferSystemDirmngr,"prefer-system-dirmngr",
-                N_("use system's dirmngr if available")),
+  ARGPARSE_s_n (oPreferSystemDirmngr,"prefer-system-dirmngr", "@"),
 
 
-  ARGPARSE_s_n (oDisableCRLChecks, "disable-crl-checks", 
+  ARGPARSE_s_n (oDisableCRLChecks, "disable-crl-checks",
                 N_("never consult a CRL")),
   ARGPARSE_s_n (oEnableCRLChecks, "enable-crl-checks", "@"),
   ARGPARSE_s_n (oDisableTrustedCertCRLCheck,
                 "disable-trusted-cert-crl-check", "@"),
                 N_("never consult a CRL")),
   ARGPARSE_s_n (oEnableCRLChecks, "enable-crl-checks", "@"),
   ARGPARSE_s_n (oDisableTrustedCertCRLCheck,
                 "disable-trusted-cert-crl-check", "@"),
-  ARGPARSE_s_n (oEnableTrustedCertCRLCheck, 
+  ARGPARSE_s_n (oEnableTrustedCertCRLCheck,
                 "enable-trusted-cert-crl-check", "@"),
 
   ARGPARSE_s_n (oForceCRLRefresh, "force-crl-refresh", "@"),
                 "enable-trusted-cert-crl-check", "@"),
 
   ARGPARSE_s_n (oForceCRLRefresh, "force-crl-refresh", "@"),
@@ -258,7 +270,7 @@ static ARGPARSE_OPTS opts[] = {
 
   ARGPARSE_s_s (oValidationModel, "validation-model", "@"),
 
 
   ARGPARSE_s_s (oValidationModel, "validation-model", "@"),
 
-  ARGPARSE_s_i (oIncludeCerts, "include-certs", 
+  ARGPARSE_s_i (oIncludeCerts, "include-certs",
                 N_("|N|number of certificates to include") ),
 
   ARGPARSE_s_s (oPolicyFile, "policy-file",
                 N_("|N|number of certificates to include") ),
 
   ARGPARSE_s_s (oPolicyFile, "policy-file",
@@ -286,8 +298,9 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oNoLogFile, "no-log-file", "@"),
   ARGPARSE_s_i (oLoggerFD, "logger-fd", "@"),
 
   ARGPARSE_s_n (oNoLogFile, "no-log-file", "@"),
   ARGPARSE_s_i (oLoggerFD, "logger-fd", "@"),
 
-  ARGPARSE_s_s (oAuditLog, "audit-log", 
+  ARGPARSE_s_s (oAuditLog, "audit-log",
                 N_("|FILE|write an audit log to FILE")),
                 N_("|FILE|write an audit log to FILE")),
+  ARGPARSE_s_s (oHtmlAuditLog, "html-audit-log", "@"),
   ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
   ARGPARSE_s_n (oBatch, "batch", N_("batch mode: never ask")),
   ARGPARSE_s_n (oAnswerYes, "yes", N_("assume yes on most questions")),
   ARGPARSE_s_n (oDryRun, "dry-run", N_("do not make any changes")),
   ARGPARSE_s_n (oBatch, "batch", N_("batch mode: never ask")),
   ARGPARSE_s_n (oAnswerYes, "yes", N_("assume yes on most questions")),
@@ -324,12 +337,12 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_i (oStatusFD, "status-fd",
                 N_("|FD|write status info to this FD")),
 
   ARGPARSE_s_i (oStatusFD, "status-fd",
                 N_("|FD|write status info to this FD")),
 
-  ARGPARSE_s_s (oCipherAlgo, "cipher-algo", 
+  ARGPARSE_s_s (oCipherAlgo, "cipher-algo",
                 N_("|NAME|use cipher algorithm NAME")),
   ARGPARSE_s_s (oDigestAlgo, "digest-algo",
                 N_("|NAME|use message digest algorithm NAME")),
   ARGPARSE_s_s (oExtraDigestAlgo, "extra-digest-algo", "@"),
                 N_("|NAME|use cipher algorithm NAME")),
   ARGPARSE_s_s (oDigestAlgo, "digest-algo",
                 N_("|NAME|use message digest algorithm NAME")),
   ARGPARSE_s_s (oExtraDigestAlgo, "extra-digest-algo", "@"),
-    
+
 
   ARGPARSE_group (302, N_(
   "@\n(See the man page for a complete listing of all commands and options)\n"
 
   ARGPARSE_group (302, N_(
   "@\n(See the man page for a complete listing of all commands and options)\n"
@@ -345,13 +358,13 @@ static ARGPARSE_OPTS opts[] = {
   /* Hidden options. */
   ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"),
   ARGPARSE_s_n (oEnableSpecialFilenames, "enable-special-filenames", "@"),
   /* Hidden options. */
   ARGPARSE_s_n (oNoVerbose, "no-verbose", "@"),
   ARGPARSE_s_n (oEnableSpecialFilenames, "enable-special-filenames", "@"),
-  ARGPARSE_s_n (oNoSecmemWarn, "no-secmem-warning", "@"), 
+  ARGPARSE_s_n (oNoSecmemWarn, "no-secmem-warning", "@"),
   ARGPARSE_s_n (oNoArmor, "no-armor", "@"),
   ARGPARSE_s_n (oNoArmor, "no-armour", "@"),
   ARGPARSE_s_n (oNoDefKeyring, "no-default-keyring", "@"),
   ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"),
   ARGPARSE_s_n (oNoOptions, "no-options", "@"),
   ARGPARSE_s_n (oNoArmor, "no-armor", "@"),
   ARGPARSE_s_n (oNoArmor, "no-armour", "@"),
   ARGPARSE_s_n (oNoDefKeyring, "no-default-keyring", "@"),
   ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"),
   ARGPARSE_s_n (oNoOptions, "no-options", "@"),
-  ARGPARSE_s_s (oHomedir, "homedir", "@"),   
+  ARGPARSE_s_s (oHomedir, "homedir", "@"),
   ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
   ARGPARSE_s_s (oDisplay,    "display", "@"),
   ARGPARSE_s_s (oTTYname,    "ttyname", "@"),
   ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
   ARGPARSE_s_s (oDisplay,    "display", "@"),
   ARGPARSE_s_s (oTTYname,    "ttyname", "@"),
@@ -371,18 +384,22 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oWithEphemeralKeys,  "with-ephemeral-keys", "@"),
   ARGPARSE_s_n (oSkipVerify, "skip-verify", "@"),
   ARGPARSE_s_n (oWithFingerprint, "with-fingerprint", "@"),
   ARGPARSE_s_n (oWithEphemeralKeys,  "with-ephemeral-keys", "@"),
   ARGPARSE_s_n (oSkipVerify, "skip-verify", "@"),
   ARGPARSE_s_n (oWithFingerprint, "with-fingerprint", "@"),
+  ARGPARSE_s_n (oWithKeygrip,     "with-keygrip", "@"),
+  ARGPARSE_s_n (oWithSecret,      "with-secret", "@"),
   ARGPARSE_s_s (oDisableCipherAlgo,  "disable-cipher-algo", "@"),
   ARGPARSE_s_s (oDisablePubkeyAlgo,  "disable-pubkey-algo", "@"),
   ARGPARSE_s_n (oIgnoreTimeConflict, "ignore-time-conflict", "@"),
   ARGPARSE_s_n (oNoRandomSeedFile,  "no-random-seed-file", "@"),
   ARGPARSE_s_n (oNoCommonCertsImport, "no-common-certs-import", "@"),
   ARGPARSE_s_s (oDisableCipherAlgo,  "disable-cipher-algo", "@"),
   ARGPARSE_s_s (oDisablePubkeyAlgo,  "disable-pubkey-algo", "@"),
   ARGPARSE_s_n (oIgnoreTimeConflict, "ignore-time-conflict", "@"),
   ARGPARSE_s_n (oNoRandomSeedFile,  "no-random-seed-file", "@"),
   ARGPARSE_s_n (oNoCommonCertsImport, "no-common-certs-import", "@"),
+  ARGPARSE_s_s (oIgnoreCertExtension, "ignore-cert-extension", "@"),
+  ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
 
   /* Command aliases.  */
 
   /* Command aliases.  */
-  ARGPARSE_c (aListKeys, "list-key", "@"),  
-  ARGPARSE_c (aListChain, "list-sig", "@"), 
-  ARGPARSE_c (aListChain, "list-sigs", "@"), 
-  ARGPARSE_c (aListChain, "check-sig", "@"), 
-  ARGPARSE_c (aListChain, "check-sigs", "@"), 
+  ARGPARSE_c (aListKeys, "list-key", "@"),
+  ARGPARSE_c (aListChain, "list-sig", "@"),
+  ARGPARSE_c (aListChain, "list-sigs", "@"),
+  ARGPARSE_c (aListChain, "check-sig", "@"),
+  ARGPARSE_c (aListChain, "check-sigs", "@"),
   ARGPARSE_c (aDeleteKey, "delete-key", "@"),
 
   ARGPARSE_end ()
   ARGPARSE_c (aDeleteKey, "delete-key", "@"),
 
   ARGPARSE_end ()
@@ -404,12 +421,25 @@ static unsigned int debug_value;
 /* Option --enable-special-filenames */
 static int allow_special_filenames;
 
 /* Option --enable-special-filenames */
 static int allow_special_filenames;
 
-/* Default value for include-certs. */
-static int default_include_certs = 1; /* Only include the signer's cert. */
+/* Default value for include-certs.  We need an extra macro for
+   gpgconf-list because the variable will be changed by the command
+   line option.
+
+   It is often cumbersome to locate intermediate certificates, thus by
+   default we include all certificates in the chain.  However we leave
+   out the root certificate because that would make it too easy for
+   the recipient to import that root certificate.  A root certificate
+   should be installed only after due checks and thus it won't help to
+   send it along with each message.  */
+#define DEFAULT_INCLUDE_CERTS -2 /* Include all certs but root. */
+static int default_include_certs = DEFAULT_INCLUDE_CERTS;
 
 /* Whether the chain mode shall be used for validation.  */
 static int default_validation_model;
 
 
 /* Whether the chain mode shall be used for validation.  */
 static int default_validation_model;
 
+/* The default cipher algo.  */
+#define DEFAULT_CIPHER_ALGO "3DES"  /*des-EDE3-CBC*/
+
 
 static char *build_list (const char *text,
                         const char *(*mapf)(int), int (*chkf)(int));
 
 static char *build_list (const char *text,
                         const char *(*mapf)(int), int (*chkf)(int));
@@ -419,7 +449,7 @@ static void set_cmd (enum cmd_and_opt_values *ret_cmd,
 static void emergency_cleanup (void);
 static int check_special_filename (const char *fname, int for_write);
 static int open_read (const char *filename);
 static void emergency_cleanup (void);
 static int check_special_filename (const char *fname, int for_write);
 static int open_read (const char *filename);
-static FILE *open_fwrite (const char *filename);
+static estream_t open_es_fread (const char *filename, const char *mode);
 static estream_t open_es_fwrite (const char *filename);
 static void run_protect_tool (int argc, char **argv);
 
 static estream_t open_es_fwrite (const char *filename);
 static void run_protect_tool (int argc, char **argv);
 
@@ -484,7 +514,7 @@ make_libversion (const char *libname, const char *(*getfnc)(const char*))
 {
   const char *s;
   char *result;
 {
   const char *s;
   char *result;
-  
+
   if (maybe_setuid)
     {
       gcry_control (GCRYCTL_INIT_SECMEM, 0, 0);  /* Drop setuid. */
   if (maybe_setuid)
     {
       gcry_control (GCRYCTL_INIT_SECMEM, 0, 0);  /* Drop setuid. */
@@ -506,19 +536,19 @@ my_strusage( int level )
 
   switch (level)
     {
 
   switch (level)
     {
-    case 11: p = "gpgsm (GnuPG)";
+    case 11: p = "@GPGSM@ (@GNUPG@)";
       break;
     case 13: p = VERSION; break;
     case 17: p = PRINTABLE_OS_NAME; break;
       break;
     case 13: p = VERSION; break;
     case 17: p = PRINTABLE_OS_NAME; break;
-    case 19: p = _("Please report bugs to <" PACKAGE_BUGREPORT ">.\n");
-      break;
+    case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
+
     case 1:
     case 1:
-    case 40: p = _("Usage: gpgsm [options] [files] (-h for help)");
+    case 40: p = _("Usage: @GPGSM@ [options] [files] (-h for help)");
       break;
     case 41:
       break;
     case 41:
-      p = _("Syntax: gpgsm [options] [files]\n"
-            "sign, check, encrypt or decrypt using the S/MIME protocol\n"
-            "default operation depends on the input data\n");
+      p = _("Syntax: @GPGSM@ [options] [files]\n"
+            "Sign, check, encrypt or decrypt using the S/MIME protocol\n"
+            "Default operation depends on the input data\n");
       break;
 
     case 20:
       break;
 
     case 20:
@@ -537,7 +567,7 @@ my_strusage( int level )
     case 33: p = _("\nSupported algorithms:\n"); break;
     case 34:
       if (!ciphers)
     case 33: p = _("\nSupported algorithms:\n"); break;
     case 34:
       if (!ciphers)
-        ciphers = build_list ("Cipher: ", gcry_cipher_algo_name,
+        ciphers = build_list ("Cipher: ", gnupg_cipher_algo_name,
                               our_cipher_test_algo );
       p = ciphers;
       break;
                               our_cipher_test_algo );
       p = ciphers;
       break;
@@ -552,7 +582,7 @@ my_strusage( int level )
         digests = build_list("Hash: ", gcry_md_algo_name, our_md_test_algo );
       p = digests;
       break;
         digests = build_list("Hash: ", gcry_md_algo_name, our_md_test_algo );
       p = digests;
       break;
-     
+
     default: p = NULL; break;
     }
   return p;
     default: p = NULL; break;
     }
   return p;
@@ -565,7 +595,7 @@ build_list (const char *text, const char * (*mapf)(int), int (*chkf)(int))
   int i;
   size_t n=strlen(text)+2;
   char *list, *p;
   int i;
   size_t n=strlen(text)+2;
   char *list, *p;
-  
+
   if (maybe_setuid) {
     gcry_control (GCRYCTL_DROP_PRIVS); /* drop setuid */
   }
   if (maybe_setuid) {
     gcry_control (GCRYCTL_DROP_PRIVS); /* drop setuid */
   }
@@ -608,13 +638,23 @@ set_binary (FILE *fp)
 static void
 wrong_args (const char *text)
 {
 static void
 wrong_args (const char *text)
 {
-  fputs (_("usage: gpgsm [options] "), stderr);
-  fputs (text, stderr);
-  putc ('\n', stderr);
+  fprintf (stderr, _("usage: %s [options] %s\n"), GPGSM_NAME, text);
   gpgsm_exit (2);
 }
 
 
   gpgsm_exit (2);
 }
 
 
+static void
+set_opt_session_env (const char *name, const char *value)
+{
+  gpg_error_t err;
+
+  err = session_env_setenv (opt.session_env, name, value);
+  if (err)
+    log_fatal ("error setting session environment: %s\n",
+               gpg_strerror (err));
+}
+
+
 /* Setup the debugging.  With a DEBUG_LEVEL of NULL only the active
    debug flags are propagated to the subsystems.  With DEBUG_LEVEL
    set, a specific set of debug flags is set; and individual debugging
 /* Setup the debugging.  With a DEBUG_LEVEL of NULL only the active
    debug flags are propagated to the subsystems.  With DEBUG_LEVEL
    set, a specific set of debug flags is set; and individual debugging
@@ -622,23 +662,34 @@ wrong_args (const char *text)
 static void
 set_debug (void)
 {
 static void
 set_debug (void)
 {
+  int numok = (debug_level && digitp (debug_level));
+  int numlvl = numok? atoi (debug_level) : 0;
+
   if (!debug_level)
     ;
   if (!debug_level)
     ;
-  else if (!strcmp (debug_level, "none"))
+  else if (!strcmp (debug_level, "none") || (numok && numlvl < 1))
     opt.debug = 0;
     opt.debug = 0;
-  else if (!strcmp (debug_level, "basic"))
+  else if (!strcmp (debug_level, "basic") || (numok && numlvl <= 2))
     opt.debug = DBG_ASSUAN_VALUE;
     opt.debug = DBG_ASSUAN_VALUE;
-  else if (!strcmp (debug_level, "advanced"))
+  else if (!strcmp (debug_level, "advanced") || (numok && numlvl <= 5))
     opt.debug = DBG_ASSUAN_VALUE|DBG_X509_VALUE;
     opt.debug = DBG_ASSUAN_VALUE|DBG_X509_VALUE;
-  else if (!strcmp (debug_level, "expert"))
+  else if (!strcmp (debug_level, "expert")  || (numok && numlvl <= 8))
     opt.debug = (DBG_ASSUAN_VALUE|DBG_X509_VALUE
                  |DBG_CACHE_VALUE|DBG_CRYPTO_VALUE);
     opt.debug = (DBG_ASSUAN_VALUE|DBG_X509_VALUE
                  |DBG_CACHE_VALUE|DBG_CRYPTO_VALUE);
-  else if (!strcmp (debug_level, "guru"))
-    opt.debug = ~0;
+  else if (!strcmp (debug_level, "guru") || numok)
+    {
+      opt.debug = ~0;
+      /* Unless the "guru" string has been used we don't want to allow
+         hashing debugging.  The rationale is that people tend to
+         select the highest debug value and would then clutter their
+         disk with debug files which may reveal confidential data.  */
+      if (numok)
+        opt.debug &= ~(DBG_HASHING_VALUE);
+    }
   else
     {
   else
     {
-      log_error (_("invalid debug-level `%s' given\n"), debug_level);
-      gpgsm_exit(2);
+      log_error (_("invalid debug-level '%s' given\n"), debug_level);
+      gpgsm_exit (2);
     }
 
   opt.debug |= debug_value;
     }
 
   opt.debug |= debug_value;
@@ -653,8 +704,19 @@ set_debug (void)
   if (opt.debug & DBG_CRYPTO_VALUE )
     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
   gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
   if (opt.debug & DBG_CRYPTO_VALUE )
     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
   gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
+
+  if (opt.debug)
+    log_info ("enabled debug flags:%s%s%s%s%s%s%s%s\n",
+              (opt.debug & DBG_X509_VALUE   )? " x509":"",
+              (opt.debug & DBG_MPI_VALUE    )? " mpi":"",
+              (opt.debug & DBG_CRYPTO_VALUE )? " crypto":"",
+              (opt.debug & DBG_MEMORY_VALUE )? " memory":"",
+              (opt.debug & DBG_CACHE_VALUE  )? " cache":"",
+              (opt.debug & DBG_MEMSTAT_VALUE)? " memstat":"",
+              (opt.debug & DBG_HASHING_VALUE)? " hashing":"",
+              (opt.debug & DBG_ASSUAN_VALUE )? " assuan":"" );
 }
 }
+
 
 
 static void
 
 
 static void
@@ -671,7 +733,7 @@ set_cmd (enum cmd_and_opt_values *ret_cmd, enum cmd_and_opt_values new_cmd)
   else if ( (cmd == aSign && new_cmd == aClearsign)
             || (cmd == aClearsign && new_cmd == aSign) )
     cmd = aClearsign;
   else if ( (cmd == aSign && new_cmd == aClearsign)
             || (cmd == aClearsign && new_cmd == aSign) )
     cmd = aClearsign;
-  else 
+  else
     {
       log_error(_("conflicting commands\n"));
       gpgsm_exit(2);
     {
       log_error(_("conflicting commands\n"));
       gpgsm_exit(2);
@@ -691,22 +753,12 @@ do_add_recipient (ctrl_t ctrl, const char *name,
     {
       if (recp_required)
         {
     {
       if (recp_required)
         {
-          log_error ("can't encrypt to `%s': %s\n", name, gpg_strerror (rc));
+          log_error ("can't encrypt to '%s': %s\n", name, gpg_strerror (rc));
           gpgsm_status2 (ctrl, STATUS_INV_RECP,
           gpgsm_status2 (ctrl, STATUS_INV_RECP,
-                     gpg_err_code (rc) == -1?                         "1":
-                     gpg_err_code (rc) == GPG_ERR_NO_PUBKEY?          "1":
-                     gpg_err_code (rc) == GPG_ERR_AMBIGUOUS_NAME?     "2":
-                     gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE?    "3":
-                     gpg_err_code (rc) == GPG_ERR_CERT_REVOKED?       "4":
-                     gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED?       "5":
-                     gpg_err_code (rc) == GPG_ERR_NO_CRL_KNOWN?       "6":
-                     gpg_err_code (rc) == GPG_ERR_CRL_TOO_OLD?        "7":
-                     gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH?    "8":
-                     "0",
-                     name, NULL);
+                         get_inv_recpsgnr_code (rc), name, NULL);
         }
       else
         }
       else
-        log_info (_("NOTE: won't be able to encrypt to `%s': %s\n"),
+        log_info (_("Note: won't be able to encrypt to '%s': %s\n"),
                   name, gpg_strerror (rc));
     }
 }
                   name, gpg_strerror (rc));
     }
 }
@@ -717,7 +769,7 @@ parse_validation_model (const char *model)
 {
   int i = gpgsm_parse_validation_model (model);
   if (i == -1)
 {
   int i = gpgsm_parse_validation_model (model);
   if (i == -1)
-    log_error (_("unknown validation model `%s'\n"), model);
+    log_error (_("unknown validation model '%s'\n"), model);
   else
     default_validation_model = i;
 }
   else
     default_validation_model = i;
 }
@@ -773,43 +825,44 @@ parse_keyserver_line (char *line,
              fail = 1;
            }
          break;
              fail = 1;
            }
          break;
-          
+
        case 2:
          if (*p)
            server->port = atoi (p);
          break;
        case 2:
          if (*p)
            server->port = atoi (p);
          break;
-         
+
        case 3:
          if (*p)
            server->user = xstrdup (p);
          break;
        case 3:
          if (*p)
            server->user = xstrdup (p);
          break;
-         
+
        case 4:
          if (*p && !server->user)
            {
        case 4:
          if (*p && !server->user)
            {
-             log_error (_("%s:%u: password given without user\n"), 
+             log_error (_("%s:%u: password given without user\n"),
                         filename, lineno);
              fail = 1;
            }
          else if (*p)
            server->pass = xstrdup (p);
          break;
                         filename, lineno);
              fail = 1;
            }
          else if (*p)
            server->pass = xstrdup (p);
          break;
-         
+
        case 5:
          if (*p)
            server->base = xstrdup (p);
          break;
        case 5:
          if (*p)
            server->base = xstrdup (p);
          break;
-         
+
        default:
          /* (We silently ignore extra fields.) */
          break;
        }
     }
        default:
          /* (We silently ignore extra fields.) */
          break;
        }
     }
-  
+
   if (fail)
     {
       log_info (_("%s:%u: skipping this line\n"), filename, lineno);
       keyserver_list_free (server);
   if (fail)
     {
       log_info (_("%s:%u: skipping this line\n"), filename, lineno);
       keyserver_list_free (server);
+      server = NULL;
     }
 
   return server;
     }
 
   return server;
@@ -822,7 +875,6 @@ main ( int argc, char **argv)
   ARGPARSE_ARGS pargs;
   int orig_argc;
   char **orig_argv;
   ARGPARSE_ARGS pargs;
   int orig_argc;
   char **orig_argv;
-  const char *fname;
   /*  char *username;*/
   int may_coredump;
   strlist_t sl, remusr= NULL, locusr=NULL;
   /*  char *username;*/
   int may_coredump;
   strlist_t sl, remusr= NULL, locusr=NULL;
@@ -837,14 +889,15 @@ main ( int argc, char **argv)
   int default_keyring = 1;
   char *logfile = NULL;
   char *auditlog = NULL;
   int default_keyring = 1;
   char *logfile = NULL;
   char *auditlog = NULL;
+  char *htmlauditlog = NULL;
   int greeting = 0;
   int nogreeting = 0;
   int debug_wait = 0;
   int use_random_seed = 1;
   int no_common_certs_import = 0;
   int with_fpr = 0;
   int greeting = 0;
   int nogreeting = 0;
   int debug_wait = 0;
   int use_random_seed = 1;
   int no_common_certs_import = 0;
   int with_fpr = 0;
-  char *def_digest_string = NULL;
-  char *extra_digest_algo = NULL;
+  const char *forced_digest_algo = NULL;
+  const char *extra_digest_algo = NULL;
   enum cmd_and_opt_values cmd = 0;
   struct server_control_s ctrl;
   certlist_t recplist = NULL;
   enum cmd_and_opt_values cmd = 0;
   struct server_control_s ctrl;
   certlist_t recplist = NULL;
@@ -852,31 +905,30 @@ main ( int argc, char **argv)
   int do_not_setup_keys = 0;
   int recp_required = 0;
   estream_t auditfp = NULL;
   int do_not_setup_keys = 0;
   int recp_required = 0;
   estream_t auditfp = NULL;
+  estream_t htmlauditfp = NULL;
+  struct assuan_malloc_hooks malloc_hooks;
 
   /*mtrace();*/
 
 
   /*mtrace();*/
 
-  gnupg_reopen_std ("gpgsm");
+  gnupg_reopen_std (GPGSM_NAME);
   /* trap_unaligned ();*/
   gnupg_rl_initialize ();
   set_strusage (my_strusage);
   gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
   /* trap_unaligned ();*/
   gnupg_rl_initialize ();
   set_strusage (my_strusage);
   gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
-  /* We don't need any locking in libgcrypt unless we use any kind of
-     threading. */
-  gcry_control (GCRYCTL_DISABLE_INTERNAL_LOCKING);
 
   /* Please note that we may running SUID(ROOT), so be very CAREFUL
      when adding any stuff between here and the call to secmem_init()
      somewhere after the option parsing */
 
   /* Please note that we may running SUID(ROOT), so be very CAREFUL
      when adding any stuff between here and the call to secmem_init()
      somewhere after the option parsing */
-  log_set_prefix ("gpgsm", 1);
+  log_set_prefix (GPGSM_NAME, 1);
 
   /* Make sure that our subsystems are ready.  */
 
   /* Make sure that our subsystems are ready.  */
-  i18n_init();
-  init_common_subsystems ();
+  i18n_init ();
+  init_common_subsystems (&argc, &argv);
 
   /* Check that the libraries are suitable.  Do it here because the
      option parse may need services of the library */
   if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
 
   /* Check that the libraries are suitable.  Do it here because the
      option parse may need services of the library */
   if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
-    log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt", 
+    log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
                NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
   if (!ksba_check_version (NEED_KSBA_VERSION) )
     log_fatal (_("%s is too old (need %s, have %s)\n"), "libksba",
                NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
   if (!ksba_check_version (NEED_KSBA_VERSION) )
     log_fatal (_("%s is too old (need %s, have %s)\n"), "libksba",
@@ -886,17 +938,24 @@ main ( int argc, char **argv)
   gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
 
   may_coredump = disable_core_dumps ();
   gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
 
   may_coredump = disable_core_dumps ();
-  
+
   gnupg_init_signals (0, emergency_cleanup);
   gnupg_init_signals (0, emergency_cleanup);
-  
-  create_dotlock (NULL); /* register locking cleanup */
+
+  dotlock_create (NULL, 0); /* Register lockfile cleanup.  */
+
+  opt.autostart = 1;
+  opt.session_env = session_env_new ();
+  if (!opt.session_env)
+    log_fatal ("error allocating session environment block: %s\n",
+               strerror (errno));
 
   /* Note: If you change this default cipher algorithm , please
      remember to update the Gpgconflist entry as well.  */
 
   /* Note: If you change this default cipher algorithm , please
      remember to update the Gpgconflist entry as well.  */
-  opt.def_cipher_algoid = "3DES";  /*des-EDE3-CBC*/
+  opt.def_cipher_algoid = DEFAULT_CIPHER_ALGO;
 
   opt.homedir = default_homedir ();
 
 
   opt.homedir = default_homedir ();
 
+
   /* First check whether we have a config file on the commandline */
   orig_argc = argc;
   orig_argv = argv;
   /* First check whether we have a config file on the commandline */
   orig_argc = argc;
   orig_argv = argv;
@@ -914,29 +973,34 @@ main ( int argc, char **argv)
           default_config = 0;
        }
       else if (pargs.r_opt == oNoOptions)
           default_config = 0;
        }
       else if (pargs.r_opt == oNoOptions)
-        default_config = 0; /* --no-options */
+        {
+          default_config = 0; /* --no-options */
+          opt.no_homedir_creation = 1;
+        }
       else if (pargs.r_opt == oHomedir)
         opt.homedir = pargs.r.ret_str;
       else if (pargs.r_opt == aCallProtectTool)
         break; /* This break makes sure that --version and --help are
                   passed to the protect-tool. */
     }
       else if (pargs.r_opt == oHomedir)
         opt.homedir = pargs.r.ret_str;
       else if (pargs.r_opt == aCallProtectTool)
         break; /* This break makes sure that --version and --help are
                   passed to the protect-tool. */
     }
-  
-  
+
+
   /* Initialize the secure memory. */
   gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
   maybe_setuid = 0;
 
   /* Initialize the secure memory. */
   gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
   maybe_setuid = 0;
 
-  /* 
-     Now we are now working under our real uid 
+  /*
+     Now we are now working under our real uid
   */
 
   ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
 
   */
 
   ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
 
-  assuan_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
-  assuan_set_assuan_log_stream (log_get_stream ());
-  assuan_set_assuan_log_prefix (log_get_prefix (NULL));
-  assuan_set_assuan_err_source (GPG_ERR_SOURCE_DEFAULT);
+  malloc_hooks.malloc = gcry_malloc;
+  malloc_hooks.realloc = gcry_realloc;
+  malloc_hooks.free = gcry_free;
+  assuan_set_malloc_hooks (&malloc_hooks);
+  assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
+  setup_libassuan_logging (&opt.debug);
 
   keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
 
 
   keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
 
@@ -944,15 +1008,15 @@ main ( int argc, char **argv)
   memset (&ctrl, 0, sizeof ctrl);
   gpgsm_init_default_ctrl (&ctrl);
   ctrl.no_server = 1;
   memset (&ctrl, 0, sizeof ctrl);
   gpgsm_init_default_ctrl (&ctrl);
   ctrl.no_server = 1;
-  ctrl.status_fd = -1; /* not status output */
+  ctrl.status_fd = -1; /* No status output. */
   ctrl.autodetect_encoding = 1;
 
   /* Set the default option file */
   if (default_config )
   ctrl.autodetect_encoding = 1;
 
   /* Set the default option file */
   if (default_config )
-    configname = make_filename (opt.homedir, "gpgsm.conf", NULL);
+    configname = make_filename (opt.homedir, GPGSM_NAME EXTSEP_S "conf", NULL);
   /* Set the default policy file */
   opt.policy_file = make_filename (opt.homedir, "policies.txt", NULL);
   /* Set the default policy file */
   opt.policy_file = make_filename (opt.homedir, "policies.txt", NULL);
-  
+
   argc        = orig_argc;
   argv        = orig_argv;
   pargs.argc  = &argc;
   argc        = orig_argc;
   argv        = orig_argv;
   pargs.argc  = &argc;
@@ -968,34 +1032,34 @@ main ( int argc, char **argv)
         if (default_config)
           {
             if (parse_debug)
         if (default_config)
           {
             if (parse_debug)
-              log_info (_("NOTE: no default option file `%s'\n"), configname);
+              log_info (_("Note: no default option file '%s'\n"), configname);
           }
           }
-        else 
+        else
           {
           {
-            log_error (_("option file `%s': %s\n"), configname, strerror(errno));
+            log_error (_("option file '%s': %s\n"), configname, strerror(errno));
             gpgsm_exit(2);
           }
         xfree(configname);
         configname = NULL;
       }
     if (parse_debug && configname)
             gpgsm_exit(2);
           }
         xfree(configname);
         configname = NULL;
       }
     if (parse_debug && configname)
-      log_info (_("reading options from `%s'\n"), configname);
+      log_info (_("reading options from '%s'\n"), configname);
     default_config = 0;
   }
 
     default_config = 0;
   }
 
-  while (!no_more_options 
+  while (!no_more_options
          && optfile_parse (configfp, configname, &configlineno, &pargs, opts))
     {
       switch (pargs.r_opt)
         {
          && optfile_parse (configfp, configname, &configlineno, &pargs, opts))
     {
       switch (pargs.r_opt)
         {
-       case aGPGConfList: 
-       case aGPGConfTest: 
+       case aGPGConfList:
+       case aGPGConfTest:
           set_cmd (&cmd, pargs.r_opt);
           do_not_setup_keys = 1;
           nogreeting = 1;
           break;
 
           set_cmd (&cmd, pargs.r_opt);
           do_not_setup_keys = 1;
           nogreeting = 1;
           break;
 
-        case aServer: 
+        case aServer:
           opt.batch = 1;
           set_cmd (&cmd, aServer);
           break;
           opt.batch = 1;
           set_cmd (&cmd, aServer);
           break;
@@ -1012,7 +1076,7 @@ main ( int argc, char **argv)
           no_more_options = 1; /* Stop parsing. */
           do_not_setup_keys = 1;
           break;
           no_more_options = 1; /* Stop parsing. */
           do_not_setup_keys = 1;
           break;
-        
+
         case aDeleteKey:
           set_cmd (&cmd, aDeleteKey);
           /*greeting=1;*/
         case aDeleteKey:
           set_cmd (&cmd, aDeleteKey);
           /*greeting=1;*/
@@ -1021,45 +1085,47 @@ main ( int argc, char **argv)
 
         case aDetachedSign:
           detached_sig = 1;
 
         case aDetachedSign:
           detached_sig = 1;
-          set_cmd (&cmd, aSign ); 
+          set_cmd (&cmd, aSign );
           break;
 
         case aKeygen:
           set_cmd (&cmd, aKeygen);
           break;
 
         case aKeygen:
           set_cmd (&cmd, aKeygen);
-          greeting=1; 
+          greeting=1;
           do_not_setup_keys = 1;
           break;
 
           do_not_setup_keys = 1;
           break;
 
-        case aImport: 
-        case aSendKeys: 
-        case aRecvKeys: 
-        case aExport: 
-        case aExportSecretKeyP12: 
+        case aImport:
+        case aSendKeys:
+        case aRecvKeys:
+        case aExport:
+        case aExportSecretKeyP12:
+        case aExportSecretKeyP8:
+        case aExportSecretKeyRaw:
         case aDumpKeys:
         case aDumpChain:
         case aDumpKeys:
         case aDumpChain:
-        case aDumpExternalKeys: 
-        case aDumpSecretKeys: 
+        case aDumpExternalKeys:
+        case aDumpSecretKeys:
         case aListKeys:
         case aListKeys:
-        case aListExternalKeys: 
-        case aListSecretKeys: 
-        case aListChain: 
-        case aLearnCard: 
-        case aPasswd: 
+        case aListExternalKeys:
+        case aListSecretKeys:
+        case aListChain:
+        case aLearnCard:
+        case aPasswd:
         case aKeydbClearSomeCertFlags:
           do_not_setup_keys = 1;
           set_cmd (&cmd, pargs.r_opt);
           break;
 
         case aKeydbClearSomeCertFlags:
           do_not_setup_keys = 1;
           set_cmd (&cmd, pargs.r_opt);
           break;
 
-        case aEncr: 
+        case aEncr:
           recp_required = 1;
           set_cmd (&cmd, pargs.r_opt);
           break;
 
         case aSym:
           recp_required = 1;
           set_cmd (&cmd, pargs.r_opt);
           break;
 
         case aSym:
-        case aDecrypt: 
-        case aSign: 
-        case aClearsign: 
-        case aVerify: 
+        case aDecrypt:
+        case aSign:
+        case aClearsign:
+        case aVerify:
           set_cmd (&cmd, pargs.r_opt);
           break;
 
           set_cmd (&cmd, pargs.r_opt);
           break;
 
@@ -1067,15 +1133,15 @@ main ( int argc, char **argv)
         case oArmor:
           ctrl.create_pem = 1;
           break;
         case oArmor:
           ctrl.create_pem = 1;
           break;
-        case oBase64: 
+        case oBase64:
           ctrl.create_pem = 0;
           ctrl.create_base64 = 1;
           break;
           ctrl.create_pem = 0;
           ctrl.create_base64 = 1;
           break;
-        case oNoArmor: 
+        case oNoArmor:
           ctrl.create_pem = 0;
           ctrl.create_base64 = 0;
           break;
           ctrl.create_pem = 0;
           ctrl.create_base64 = 0;
           break;
-          
+
         case oP12Charset:
           opt.p12_charset = pargs.r.ret_str;
           break;
         case oP12Charset:
           opt.p12_charset = pargs.r.ret_str;
           break;
@@ -1120,8 +1186,8 @@ main ( int argc, char **argv)
           ctrl.use_ocsp = opt.enable_ocsp = 1;
           break;
 
           ctrl.use_ocsp = opt.enable_ocsp = 1;
           break;
 
-        case oIncludeCerts: 
-          ctrl.include_certs = default_include_certs = pargs.r.ret_int; 
+        case oIncludeCerts:
+          ctrl.include_certs = default_include_certs = pargs.r.ret_int;
           break;
 
         case oPolicyFile:
           break;
 
         case oPolicyFile:
@@ -1138,14 +1204,14 @@ main ( int argc, char **argv)
         case oEnablePolicyChecks:
           opt.no_policy_check = 0;
           break;
         case oEnablePolicyChecks:
           opt.no_policy_check = 0;
           break;
-          
+
         case oAutoIssuerKeyRetrieve:
           opt.auto_issuer_key_retrieve = 1;
           break;
 
         case oOutput: opt.outfile = pargs.r.ret_str; break;
 
         case oAutoIssuerKeyRetrieve:
           opt.auto_issuer_key_retrieve = 1;
           break;
 
         case oOutput: opt.outfile = pargs.r.ret_str; break;
 
-        
+
         case oQuiet: opt.quiet = 1; break;
         case oNoTTY: /* fixme:tty_no_terminal(1);*/ break;
         case oDryRun: opt.dry_run = 1; break;
         case oQuiet: opt.quiet = 1; break;
         case oNoTTY: /* fixme:tty_no_terminal(1);*/ break;
         case oDryRun: opt.dry_run = 1; break;
@@ -1160,16 +1226,17 @@ main ( int argc, char **argv)
           break;
 
         case oLogFile: logfile = pargs.r.ret_str; break;
           break;
 
         case oLogFile: logfile = pargs.r.ret_str; break;
-        case oNoLogFile: logfile = NULL; break;          
+        case oNoLogFile: logfile = NULL; break;
 
         case oAuditLog: auditlog = pargs.r.ret_str; break;
 
         case oAuditLog: auditlog = pargs.r.ret_str; break;
+        case oHtmlAuditLog: htmlauditlog = pargs.r.ret_str; break;
 
 
-        case oBatch: 
+        case oBatch:
           opt.batch = 1;
           greeting = 0;
           break;
         case oNoBatch: opt.batch = 0; break;
           opt.batch = 1;
           greeting = 0;
           break;
         case oNoBatch: opt.batch = 0; break;
-          
+
         case oAnswerYes: opt.answer_yes = 1; break;
         case oAnswerNo: opt.answer_no = 1; break;
 
         case oAnswerYes: opt.answer_yes = 1; break;
         case oAnswerNo: opt.answer_no = 1; break;
 
@@ -1197,6 +1264,10 @@ main ( int argc, char **argv)
           opt.fingerprint++;
           break;
 
           opt.fingerprint++;
           break;
 
+        case oWithKeygrip:
+          opt.with_keygrip = 1;
+          break;
+
         case oOptions:
           /* config files may not be nested (silently ignore them) */
           if (!configfp)
         case oOptions:
           /* config files may not be nested (silently ignore them) */
           if (!configfp)
@@ -1206,25 +1277,36 @@ main ( int argc, char **argv)
               goto next_pass;
            }
           break;
               goto next_pass;
            }
           break;
-        case oNoOptions: break; /* no-options */
+        case oNoOptions: opt.no_homedir_creation = 1; break; /* no-options */
         case oHomedir: opt.homedir = pargs.r.ret_str; break;
         case oAgentProgram: opt.agent_program = pargs.r.ret_str;  break;
         case oHomedir: opt.homedir = pargs.r.ret_str; break;
         case oAgentProgram: opt.agent_program = pargs.r.ret_str;  break;
-        case oDisplay: opt.display = xstrdup (pargs.r.ret_str); break;
-        case oTTYname: opt.ttyname = xstrdup (pargs.r.ret_str); break;
-        case oTTYtype: opt.ttytype = xstrdup (pargs.r.ret_str); break;
+
+        case oDisplay:
+          set_opt_session_env ("DISPLAY", pargs.r.ret_str);
+          break;
+        case oTTYname:
+          set_opt_session_env ("GPG_TTY", pargs.r.ret_str);
+          break;
+        case oTTYtype:
+          set_opt_session_env ("TERM", pargs.r.ret_str);
+          break;
+        case oXauthority:
+          set_opt_session_env ("XAUTHORITY", pargs.r.ret_str);
+          break;
+
         case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break;
         case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break;
         case oLCctype: opt.lc_ctype = xstrdup (pargs.r.ret_str); break;
         case oLCmessages: opt.lc_messages = xstrdup (pargs.r.ret_str); break;
-        case oXauthority: opt.xauthority = xstrdup (pargs.r.ret_str); break;
+
         case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str;  break;
         case oDisableDirmngr: opt.disable_dirmngr = 1;  break;
         case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str;  break;
         case oDisableDirmngr: opt.disable_dirmngr = 1;  break;
-        case oPreferSystemDirmngr: opt.prefer_system_dirmngr = 1; break;
+        case oPreferSystemDirmngr: /* Obsolete */; break;
         case oProtectToolProgram:
         case oProtectToolProgram:
-          opt.protect_tool_program = pargs.r.ret_str; 
+          opt.protect_tool_program = pargs.r.ret_str;
           break;
           break;
-          
+
         case oFakedSystemTime:
           {
         case oFakedSystemTime:
           {
-            time_t faked_time = isotime2epoch (pargs.r.ret_str); 
+            time_t faked_time = isotime2epoch (pargs.r.ret_str);
             if (faked_time == (time_t)(-1))
               faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10);
             gnupg_set_time (faked_time, 0);
             if (faked_time == (time_t)(-1))
               faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10);
             gnupg_set_time (faked_time, 0);
@@ -1258,8 +1340,9 @@ main ( int argc, char **argv)
 
         case oWithKeyData: opt.with_key_data=1; /* fall thru */
         case oWithColons: ctrl.with_colons = 1; break;
 
         case oWithKeyData: opt.with_key_data=1; /* fall thru */
         case oWithColons: ctrl.with_colons = 1; break;
+        case oWithSecret: ctrl.with_secret = 1; break;
         case oWithValidation: ctrl.with_validation=1; break;
         case oWithValidation: ctrl.with_validation=1; break;
-        case oWithEphemeralKeys: opt.with_ephemeral_keys=1; break;
+        case oWithEphemeralKeys: ctrl.with_ephemeral_keys=1; break;
 
         case oSkipVerify: opt.skip_verify=1; break;
 
 
         case oSkipVerify: opt.skip_verify=1; break;
 
@@ -1280,20 +1363,20 @@ main ( int argc, char **argv)
           break;
 
         case oNoSecmemWarn:
           break;
 
         case oNoSecmemWarn:
-          gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); 
+          gcry_control (GCRYCTL_DISABLE_SECMEM_WARN);
           break;
 
         case oCipherAlgo:
           opt.def_cipher_algoid = pargs.r.ret_str;
           break;
 
           break;
 
         case oCipherAlgo:
           opt.def_cipher_algoid = pargs.r.ret_str;
           break;
 
-        case oDisableCipherAlgo: 
+        case oDisableCipherAlgo:
           {
             int algo = gcry_cipher_map_name (pargs.r.ret_str);
             gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, &algo, sizeof algo);
           }
           break;
           {
             int algo = gcry_cipher_map_name (pargs.r.ret_str);
             gcry_cipher_ctl (NULL, GCRYCTL_DISABLE_ALGO, &algo, sizeof algo);
           }
           break;
-        case oDisablePubkeyAlgo: 
+        case oDisablePubkeyAlgo:
           {
             int algo = gcry_pk_map_name (pargs.r.ret_str);
             gcry_pk_ctl (GCRYCTL_DISABLE_ALGO,&algo, sizeof algo );
           {
             int algo = gcry_pk_map_name (pargs.r.ret_str);
             gcry_pk_ctl (GCRYCTL_DISABLE_ALGO,&algo, sizeof algo );
@@ -1301,10 +1384,10 @@ main ( int argc, char **argv)
           break;
 
         case oDigestAlgo:
           break;
 
         case oDigestAlgo:
-          /* Dummy for now. */
+          forced_digest_algo = pargs.r.ret_str;
           break;
 
           break;
 
-        case oExtraDigestAlgo: 
+        case oExtraDigestAlgo:
           extra_digest_algo = pargs.r.ret_str;
           break;
 
           extra_digest_algo = pargs.r.ret_str;
           break;
 
@@ -1334,8 +1417,14 @@ main ( int argc, char **argv)
          }
          break;
 
          }
          break;
 
-        default: 
-          pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR; 
+        case oIgnoreCertExtension:
+          add_to_strlist (&opt.ignored_cert_extensions, pargs.r.ret_str);
+          break;
+
+        case oNoAutostart: opt.autostart = 0; break;
+
+        default:
+          pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
           break;
        }
     }
           break;
        }
     }
@@ -1353,23 +1442,25 @@ main ( int argc, char **argv)
   configname = NULL;
 
   if (!opt.config_filename)
   configname = NULL;
 
   if (!opt.config_filename)
-    opt.config_filename = make_filename (opt.homedir, "gpgsm.conf", NULL);
+    opt.config_filename = make_filename (opt.homedir,
+                                         GPGSM_NAME EXTSEP_S "conf",
+                                         NULL);
 
   if (log_get_errorcount(0))
     gpgsm_exit(2);
 
 
   if (log_get_errorcount(0))
     gpgsm_exit(2);
 
-  /* Now that we have the optiosn parsed we need to update the default
+  /* Now that we have the options parsed we need to update the default
      control structure.  */
   gpgsm_init_default_ctrl (&ctrl);
 
   if (nogreeting)
     greeting = 0;
      control structure.  */
   gpgsm_init_default_ctrl (&ctrl);
 
   if (nogreeting)
     greeting = 0;
-  
+
   if (greeting)
     {
   if (greeting)
     {
-      fprintf(stderr, "%s %s; %s\n",
-              strusage(11), strusage(13), strusage(14) );
-      fprintf(stderr, "%s\n", strusage(15) );
+      es_fprintf (es_stderr, "%s %s; %s\n",
+                  strusage(11), strusage(13), strusage(14) );
+      es_fprintf (es_stderr, "%s\n", strusage(15) );
     }
 #  ifdef IS_DEVELOPMENT_VERSION
   if (!opt.batch)
     }
 #  ifdef IS_DEVELOPMENT_VERSION
   if (!opt.batch)
@@ -1380,11 +1471,6 @@ main ( int argc, char **argv)
     }
 #  endif
 
     }
 #  endif
 
-  if (auditlog)
-    log_info ("NOTE: The audit log feature (--audit-log) is "
-              "WORK IN PRORESS and not ready for use!\n");
-
-
   if (may_coredump && !opt.quiet)
     log_info (_("WARNING: program may create a core file!\n"));
 
   if (may_coredump && !opt.quiet)
     log_info (_("WARNING: program may create a core file!\n"));
 
@@ -1405,10 +1491,20 @@ main ( int argc, char **argv)
 
       log_info (_("WARNING: running with faked system time: "));
       gnupg_get_isotime (tbuf);
 
       log_info (_("WARNING: running with faked system time: "));
       gnupg_get_isotime (tbuf);
-      gpgsm_dump_time (tbuf);
+      dump_isotime (tbuf);
       log_printf ("\n");
     }
       log_printf ("\n");
     }
-  
+
+  /* Print a warning if an argument looks like an option.  */
+  if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
+    {
+      int i;
+
+      for (i=0; i < argc; i++)
+        if (argv[i][0] == '-' && argv[i][1] == '-')
+          log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
+    }
+
 /*FIXME    if (opt.batch) */
 /*      tty_batchmode (1); */
 
 /*FIXME    if (opt.batch) */
 /*      tty_batchmode (1); */
 
@@ -1446,7 +1542,7 @@ main ( int argc, char **argv)
     opt.def_cipher_algoid = "1.3.6.1.4.1.11591.13.2.42";
   else if (!strcmp (opt.def_cipher_algoid, "SEED") )
     opt.def_cipher_algoid = "1.2.410.200004.1.4";
     opt.def_cipher_algoid = "1.3.6.1.4.1.11591.13.2.42";
   else if (!strcmp (opt.def_cipher_algoid, "SEED") )
     opt.def_cipher_algoid = "1.2.410.200004.1.4";
-  else if (!strcmp (opt.def_cipher_algoid, "CAMELLIA") 
+  else if (!strcmp (opt.def_cipher_algoid, "CAMELLIA")
            || !strcmp (opt.def_cipher_algoid, "CAMELLIA128") )
     opt.def_cipher_algoid = "1.2.392.200011.61.1.1.1.2";
   else if (!strcmp (opt.def_cipher_algoid, "CAMELLIA192") )
            || !strcmp (opt.def_cipher_algoid, "CAMELLIA128") )
     opt.def_cipher_algoid = "1.2.392.200011.61.1.1.1.2";
   else if (!strcmp (opt.def_cipher_algoid, "CAMELLIA192") )
@@ -1460,12 +1556,10 @@ main ( int argc, char **argv)
            || !gcry_cipher_mode_from_oid (opt.def_cipher_algoid))
         log_error (_("selected cipher algorithm is invalid\n"));
 
            || !gcry_cipher_mode_from_oid (opt.def_cipher_algoid))
         log_error (_("selected cipher algorithm is invalid\n"));
 
-      if (def_digest_string)
+      if (forced_digest_algo)
         {
         {
-          opt.def_digest_algo = gcry_md_map_name (def_digest_string);
-          xfree (def_digest_string);
-          def_digest_string = NULL;
-          if (our_md_test_algo(opt.def_digest_algo) )
+          opt.forced_digest_algo = gcry_md_map_name (forced_digest_algo);
+          if (our_md_test_algo(opt.forced_digest_algo) )
             log_error (_("selected digest algorithm is invalid\n"));
         }
       if (extra_digest_algo)
             log_error (_("selected digest algorithm is invalid\n"));
         }
       if (extra_digest_algo)
@@ -1478,18 +1572,18 @@ main ( int argc, char **argv)
 
   if (log_get_errorcount(0))
     gpgsm_exit(2);
 
   if (log_get_errorcount(0))
     gpgsm_exit(2);
-  
+
   /* Set the random seed file. */
   /* Set the random seed file. */
-  if (use_random_seed) 
+  if (use_random_seed)
     {
       char *p = make_filename (opt.homedir, "random_seed", NULL);
       gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
       xfree(p);
     }
     {
       char *p = make_filename (opt.homedir, "random_seed", NULL);
       gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
       xfree(p);
     }
-  
+
   if (!cmd && opt.fingerprint && !with_fpr)
     set_cmd (&cmd, aListKeys);
   if (!cmd && opt.fingerprint && !with_fpr)
     set_cmd (&cmd, aListKeys);
-  
+
   /* Add default keybox. */
   if (!nrings && default_keyring)
     {
   /* Add default keybox. */
   if (!nrings && default_keyring)
     {
@@ -1500,12 +1594,12 @@ main ( int argc, char **argv)
         {
           /* Import the standard certificates for a new default keybox. */
           char *filelist[2];
         {
           /* Import the standard certificates for a new default keybox. */
           char *filelist[2];
-          
+
           filelist[0] = make_filename (gnupg_datadir (),"com-certs.pem", NULL);
           filelist[1] = NULL;
           if (!access (filelist[0], F_OK))
             {
           filelist[0] = make_filename (gnupg_datadir (),"com-certs.pem", NULL);
           filelist[1] = NULL;
           if (!access (filelist[0], F_OK))
             {
-              log_info (_("importing common certificates `%s'\n"),
+              log_info (_("importing common certificates '%s'\n"),
                         filelist[0]);
               gpgsm_import_files (&ctrl, 1, filelist, open_read);
             }
                         filelist[0]);
               gpgsm_import_files (&ctrl, 1, filelist, open_read);
             }
@@ -1518,17 +1612,20 @@ main ( int argc, char **argv)
 
 
   /* Prepare the audit log feature for certain commands.  */
 
 
   /* Prepare the audit log feature for certain commands.  */
-  if (auditlog)
+  if (auditlog || htmlauditlog)
     {
       switch (cmd)
         {
     {
       switch (cmd)
         {
-        case aEncr: 
+        case aEncr:
         case aSign:
         case aDecrypt:
         case aVerify:
           audit_release (ctrl.audit);
           ctrl.audit = audit_new ();
         case aSign:
         case aDecrypt:
         case aVerify:
           audit_release (ctrl.audit);
           ctrl.audit = audit_new ();
-          auditfp = open_es_fwrite (auditlog);
+          if (auditlog)
+            auditfp = open_es_fwrite (auditlog);
+          if (htmlauditlog)
+            htmlauditfp = open_es_fwrite (htmlauditlog);
           break;
         default:
           break;
           break;
         default:
           break;
@@ -1543,24 +1640,15 @@ main ( int argc, char **argv)
           int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist, 0);
           if (rc)
             {
           int rc = gpgsm_add_to_certlist (&ctrl, sl->d, 1, &signerlist, 0);
           if (rc)
             {
-              log_error (_("can't sign using `%s': %s\n"),
+              log_error (_("can't sign using '%s': %s\n"),
                          sl->d, gpg_strerror (rc));
                          sl->d, gpg_strerror (rc));
+              gpgsm_status2 (&ctrl, STATUS_INV_SGNR,
+                             get_inv_recpsgnr_code (rc), sl->d, NULL);
               gpgsm_status2 (&ctrl, STATUS_INV_RECP,
               gpgsm_status2 (&ctrl, STATUS_INV_RECP,
-                         gpg_err_code (rc) == -1?                      "1":
-                         gpg_err_code (rc) == GPG_ERR_NO_PUBKEY?       "1":
-                         gpg_err_code (rc) == GPG_ERR_AMBIGUOUS_NAME?  "2":
-                         gpg_err_code (rc) == GPG_ERR_WRONG_KEY_USAGE? "3":
-                         gpg_err_code (rc) == GPG_ERR_CERT_REVOKED?    "4":
-                         gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED?    "5":
-                         gpg_err_code (rc) == GPG_ERR_NO_CRL_KNOWN?    "6":
-                         gpg_err_code (rc) == GPG_ERR_CRL_TOO_OLD?     "7":
-                         gpg_err_code (rc) == GPG_ERR_NO_POLICY_MATCH? "8":
-                         gpg_err_code (rc) == GPG_ERR_NO_SECKEY?       "9":
-                         "0",
-                         sl->d, NULL);
+                             get_inv_recpsgnr_code (rc), sl->d, NULL);
             }
         }
             }
         }
-      
+
       /* Build the recipient list.  We first add the regular ones and then
          the encrypt-to ones because the underlying function will silently
          ignore duplicates and we can't allow to keep a duplicate which is
       /* Build the recipient list.  We first add the regular ones and then
          the encrypt-to ones because the underlying function will silently
          ignore duplicates and we can't allow to keep a duplicate which is
@@ -1579,39 +1667,42 @@ main ( int argc, char **argv)
 
   if (log_get_errorcount(0))
     gpgsm_exit(1); /* Must stop for invalid recipients. */
 
   if (log_get_errorcount(0))
     gpgsm_exit(1); /* Must stop for invalid recipients. */
-  
-  fname = argc? *argv : NULL;
-  
+
   /* Dispatch command.  */
   switch (cmd)
     {
   /* Dispatch command.  */
   switch (cmd)
     {
-    case aGPGConfList: 
+    case aGPGConfList:
       { /* List options and default values in the GPG Conf format.  */
        char *config_filename_esc = percent_escape (opt.config_filename, NULL);
 
       { /* List options and default values in the GPG Conf format.  */
        char *config_filename_esc = percent_escape (opt.config_filename, NULL);
 
-        printf ("gpgconf-gpgsm.conf:%lu:\"%s\n",
-                GC_OPT_FLAG_DEFAULT, config_filename_esc);
+        es_printf ("%s-%s.conf:%lu:\"%s\n",
+                   GPGCONF_NAME, GPGSM_NAME,
+                   GC_OPT_FLAG_DEFAULT, config_filename_esc);
         xfree (config_filename_esc);
 
         xfree (config_filename_esc);
 
-        printf ("verbose:%lu:\n", GC_OPT_FLAG_NONE);
-       printf ("quiet:%lu:\n", GC_OPT_FLAG_NONE);
-       printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
-       printf ("log-file:%lu:\n", GC_OPT_FLAG_NONE);
-        printf ("disable-crl-checks:%lu:\n", GC_OPT_FLAG_NONE);
-        printf ("disable-trusted-cert-crl-check:%lu:\n", GC_OPT_FLAG_NONE);
-        printf ("enable-ocsp:%lu:\n", GC_OPT_FLAG_NONE);
-        printf ("include-certs:%lu:1:\n", GC_OPT_FLAG_DEFAULT);
-        printf ("disable-policy-checks:%lu:\n", GC_OPT_FLAG_NONE);
-        printf ("auto-issuer-key-retrieve:%lu:\n", GC_OPT_FLAG_NONE);
-        printf ("disable-dirmngr:%lu:\n", GC_OPT_FLAG_NONE);
-#ifndef HAVE_W32_SYSTEM
-        printf ("prefer-system-dirmngr:%lu:\n", GC_OPT_FLAG_NONE);
-#endif
-        printf ("cipher-algo:%lu:\"3DES:\n", GC_OPT_FLAG_DEFAULT);
-        printf ("p12-charset:%lu:\n", GC_OPT_FLAG_DEFAULT);
-        printf ("default-key:%lu:\n", GC_OPT_FLAG_DEFAULT);
-        printf ("encrypt-to:%lu:\n", GC_OPT_FLAG_DEFAULT);
-       printf ("keyserver:%lu:\n", GC_OPT_FLAG_NONE);
+        es_printf ("verbose:%lu:\n", GC_OPT_FLAG_NONE);
+       es_printf ("quiet:%lu:\n", GC_OPT_FLAG_NONE);
+       es_printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
+       es_printf ("log-file:%lu:\n", GC_OPT_FLAG_NONE);
+        es_printf ("disable-crl-checks:%lu:\n", GC_OPT_FLAG_NONE);
+        es_printf ("disable-trusted-cert-crl-check:%lu:\n", GC_OPT_FLAG_NONE);
+        es_printf ("enable-ocsp:%lu:\n", GC_OPT_FLAG_NONE);
+        es_printf ("include-certs:%lu:%d:\n", GC_OPT_FLAG_DEFAULT,
+                   DEFAULT_INCLUDE_CERTS);
+        es_printf ("disable-policy-checks:%lu:\n", GC_OPT_FLAG_NONE);
+        es_printf ("auto-issuer-key-retrieve:%lu:\n", GC_OPT_FLAG_NONE);
+        es_printf ("disable-dirmngr:%lu:\n", GC_OPT_FLAG_NONE);
+        es_printf ("cipher-algo:%lu:\"%s:\n", GC_OPT_FLAG_DEFAULT,
+                   DEFAULT_CIPHER_ALGO);
+        es_printf ("p12-charset:%lu:\n", GC_OPT_FLAG_DEFAULT);
+        es_printf ("default-key:%lu:\n", GC_OPT_FLAG_DEFAULT);
+        es_printf ("encrypt-to:%lu:\n", GC_OPT_FLAG_DEFAULT);
+       es_printf ("keyserver:%lu:\n", GC_OPT_FLAG_NONE);
+
+        /* The next one is an info only item and should match what
+           proc_parameters actually implements.  */
+        es_printf ("default_pubkey_algo:%lu:\"%s:\n", GC_OPT_FLAG_DEFAULT,
+                   "RSA-2048");
 
       }
       break;
 
       }
       break;
@@ -1645,42 +1736,40 @@ main ( int argc, char **argv)
 
     case aEncr: /* Encrypt the given file. */
       {
 
     case aEncr: /* Encrypt the given file. */
       {
-        FILE *fp = open_fwrite (opt.outfile?opt.outfile:"-");
+        estream_t fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
 
         set_binary (stdin);
 
         if (!argc) /* Source is stdin. */
 
         set_binary (stdin);
 
         if (!argc) /* Source is stdin. */
-          gpgsm_encrypt (&ctrl, recplist, 0, fp); 
+          gpgsm_encrypt (&ctrl, recplist, 0, fp);
         else if (argc == 1)  /* Source is the given file. */
           gpgsm_encrypt (&ctrl, recplist, open_read (*argv), fp);
         else
           wrong_args ("--encrypt [datafile]");
 
         else if (argc == 1)  /* Source is the given file. */
           gpgsm_encrypt (&ctrl, recplist, open_read (*argv), fp);
         else
           wrong_args ("--encrypt [datafile]");
 
-        if (fp != stdout)
-          fclose (fp);
+        es_fclose (fp);
       }
       break;
 
     case aSign: /* Sign the given file. */
       {
       }
       break;
 
     case aSign: /* Sign the given file. */
       {
-        FILE *fp = open_fwrite (opt.outfile?opt.outfile:"-");
+        estream_t fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
 
         /* Fixme: We should also allow to concatenate multiple files for
            signing because that is what gpg does.*/
         set_binary (stdin);
         if (!argc) /* Create from stdin. */
 
         /* Fixme: We should also allow to concatenate multiple files for
            signing because that is what gpg does.*/
         set_binary (stdin);
         if (!argc) /* Create from stdin. */
-          gpgsm_sign (&ctrl, signerlist, 0, detached_sig, fp); 
+          gpgsm_sign (&ctrl, signerlist, 0, detached_sig, fp);
         else if (argc == 1) /* From file. */
           gpgsm_sign (&ctrl, signerlist,
         else if (argc == 1) /* From file. */
           gpgsm_sign (&ctrl, signerlist,
-                      open_read (*argv), detached_sig, fp); 
+                      open_read (*argv), detached_sig, fp);
         else
           wrong_args ("--sign [datafile]");
 
         else
           wrong_args ("--sign [datafile]");
 
-        if (fp != stdout)
-          fclose (fp);
+        es_fclose (fp);
       }
       break;
       }
       break;
-        
+
     case aSignEncr: /* sign and encrypt the given file */
       log_error ("this command has not yet been implemented\n");
       break;
     case aSignEncr: /* sign and encrypt the given file */
       log_error ("this command has not yet been implemented\n");
       break;
@@ -1691,35 +1780,30 @@ main ( int argc, char **argv)
 
     case aVerify:
       {
 
     case aVerify:
       {
-        FILE *fp = NULL;
+        estream_t fp = NULL;
 
         set_binary (stdin);
         if (argc == 2 && opt.outfile)
           log_info ("option --output ignored for a detached signature\n");
         else if (opt.outfile)
 
         set_binary (stdin);
         if (argc == 2 && opt.outfile)
           log_info ("option --output ignored for a detached signature\n");
         else if (opt.outfile)
-          fp = open_fwrite (opt.outfile);
+          fp = open_es_fwrite (opt.outfile);
 
         if (!argc)
           gpgsm_verify (&ctrl, 0, -1, fp); /* normal signature from stdin */
         else if (argc == 1)
           gpgsm_verify (&ctrl, open_read (*argv), -1, fp); /* std signature */
         else if (argc == 2) /* detached signature (sig, detached) */
 
         if (!argc)
           gpgsm_verify (&ctrl, 0, -1, fp); /* normal signature from stdin */
         else if (argc == 1)
           gpgsm_verify (&ctrl, open_read (*argv), -1, fp); /* std signature */
         else if (argc == 2) /* detached signature (sig, detached) */
-          gpgsm_verify (&ctrl, open_read (*argv), open_read (argv[1]), NULL); 
+          gpgsm_verify (&ctrl, open_read (*argv), open_read (argv[1]), NULL);
         else
           wrong_args ("--verify [signature [detached_data]]");
 
         else
           wrong_args ("--verify [signature [detached_data]]");
 
-        if (fp && fp != stdout)
-          fclose (fp);
+        es_fclose (fp);
       }
       break;
 
       }
       break;
 
-    case aVerifyFiles:
-      log_error (_("this command has not yet been implemented\n"));
-      break;
-
     case aDecrypt:
       {
     case aDecrypt:
       {
-        FILE *fp = open_fwrite (opt.outfile?opt.outfile:"-");
+        estream_t fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
 
         set_binary (stdin);
         if (!argc)
 
         set_binary (stdin);
         if (!argc)
@@ -1728,8 +1812,8 @@ main ( int argc, char **argv)
           gpgsm_decrypt (&ctrl, open_read (*argv), fp); /* from file */
         else
           wrong_args ("--decrypt [filename]");
           gpgsm_decrypt (&ctrl, open_read (*argv), fp); /* from file */
         else
           wrong_args ("--decrypt [filename]");
-        if (fp != stdout)
-          fclose (fp);
+
+        es_fclose (fp);
       }
       break;
 
       }
       break;
 
@@ -1757,7 +1841,7 @@ main ( int argc, char **argv)
           {
           case aListChain:
           case aListKeys:         mode = (0   | 0 | (1<<6)); break;
           {
           case aListChain:
           case aListKeys:         mode = (0   | 0 | (1<<6)); break;
-          case aDumpChain: 
+          case aDumpChain:
           case aDumpKeys:         mode = (256 | 0 | (1<<6)); break;
           case aListExternalKeys: mode = (0   | 0 | (1<<7)); break;
           case aDumpExternalKeys: mode = (256 | 0 | (1<<7)); break;
           case aDumpKeys:         mode = (256 | 0 | (1<<6)); break;
           case aListExternalKeys: mode = (0   | 0 | (1<<7)); break;
           case aDumpExternalKeys: mode = (256 | 0 | (1<<7)); break;
@@ -1778,10 +1862,27 @@ main ( int argc, char **argv)
 
     case aKeygen: /* Generate a key; well kind of. */
       {
 
     case aKeygen: /* Generate a key; well kind of. */
       {
-        FILE *fp = open_fwrite (opt.outfile?opt.outfile:"-");
-        gpgsm_gencertreq_tty (&ctrl, fp);
-        if (fp != stdout)
-          fclose (fp);
+        estream_t fpin = NULL;
+        estream_t fpout;
+
+        if (opt.batch)
+          {
+            if (!argc) /* Create from stdin. */
+              fpin = open_es_fread ("-", "r");
+            else if (argc == 1) /* From file. */
+              fpin = open_es_fread (*argv, "r");
+            else
+              wrong_args ("--gen-key --batch [parmfile]");
+          }
+
+        fpout = open_es_fwrite (opt.outfile?opt.outfile:"-");
+
+        if (fpin)
+          gpgsm_genkey (&ctrl, fpin, fpout);
+        else
+          gpgsm_gencertreq_tty (&ctrl, fpout);
+
+        es_fclose (fpout);
       }
       break;
 
       }
       break;
 
@@ -1792,30 +1893,56 @@ main ( int argc, char **argv)
 
     case aExport:
       {
 
     case aExport:
       {
-        FILE *fp = open_fwrite (opt.outfile?opt.outfile:"-");
+        estream_t fp;
 
 
+        fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
         for (sl=NULL; argc; argc--, argv++)
           add_to_strlist (&sl, *argv);
         for (sl=NULL; argc; argc--, argv++)
           add_to_strlist (&sl, *argv);
-        gpgsm_export (&ctrl, sl, fp, NULL);
+        gpgsm_export (&ctrl, sl, fp);
         free_strlist(sl);
         free_strlist(sl);
-        if (fp != stdout)
-          fclose (fp);
+        es_fclose (fp);
       }
       break;
 
     case aExportSecretKeyP12:
       {
       }
       break;
 
     case aExportSecretKeyP12:
       {
-        FILE *fp = open_fwrite (opt.outfile?opt.outfile:"-");
+        estream_t fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
 
         if (argc == 1)
 
         if (argc == 1)
-          gpgsm_p12_export (&ctrl, *argv, fp);
+          gpgsm_p12_export (&ctrl, *argv, fp, 0);
         else
           wrong_args ("--export-secret-key-p12 KEY-ID");
         else
           wrong_args ("--export-secret-key-p12 KEY-ID");
-        if (fp != stdout)
-          fclose (fp);
+        if (fp != es_stdout)
+          es_fclose (fp);
+      }
+      break;
+
+    case aExportSecretKeyP8:
+      {
+        estream_t fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
+
+        if (argc == 1)
+          gpgsm_p12_export (&ctrl, *argv, fp, 1);
+        else
+          wrong_args ("--export-secret-key-p8 KEY-ID");
+        if (fp != es_stdout)
+          es_fclose (fp);
+      }
+      break;
+
+    case aExportSecretKeyRaw:
+      {
+        estream_t fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
+
+        if (argc == 1)
+          gpgsm_p12_export (&ctrl, *argv, fp, 2);
+        else
+          wrong_args ("--export-secret-key-raw KEY-ID");
+        if (fp != es_stdout)
+          es_fclose (fp);
       }
       break;
       }
       break;
-      
+
     case aSendKeys:
     case aRecvKeys:
       log_error ("this command has not yet been implemented\n");
     case aSendKeys:
     case aRecvKeys:
       log_error ("this command has not yet been implemented\n");
@@ -1847,7 +1974,7 @@ main ( int argc, char **argv)
             ;
           else if (!(grip = gpgsm_get_keygrip_hexstring (cert)))
             rc = gpg_error (GPG_ERR_BUG);
             ;
           else if (!(grip = gpgsm_get_keygrip_hexstring (cert)))
             rc = gpg_error (GPG_ERR_BUG);
-          else 
+          else
             {
               char *desc = gpgsm_format_keydesc (cert);
               rc = gpgsm_agent_passwd (&ctrl, grip, desc);
             {
               char *desc = gpgsm_format_keydesc (cert);
               rc = gpgsm_agent_passwd (&ctrl, grip, desc);
@@ -1874,14 +2001,18 @@ main ( int argc, char **argv)
     }
 
   /* Print the audit result if needed.  */
     }
 
   /* Print the audit result if needed.  */
-  if (auditlog && auditfp)
+  if ((auditlog && auditfp) || (htmlauditlog && htmlauditfp))
     {
     {
-      audit_print_result (ctrl.audit, auditfp, 0);
+      if (auditlog && auditfp)
+        audit_print_result (ctrl.audit, auditfp, 0);
+      if (htmlauditlog && htmlauditfp)
+        audit_print_result (ctrl.audit, htmlauditfp, 1);
       audit_release (ctrl.audit);
       ctrl.audit = NULL;
       es_fclose (auditfp);
       audit_release (ctrl.audit);
       ctrl.audit = NULL;
       es_fclose (auditfp);
+      es_fclose (htmlauditfp);
     }
     }
-  
+
   /* cleanup */
   keyserver_list_free (opt.keyserver);
   opt.keyserver = NULL;
   /* cleanup */
   keyserver_list_free (opt.keyserver);
   opt.keyserver = NULL;
@@ -1929,11 +2060,13 @@ gpgsm_init_default_ctrl (struct server_control_s *ctrl)
 
 int
 gpgsm_parse_validation_model (const char *model)
 
 int
 gpgsm_parse_validation_model (const char *model)
-{     
+{
   if (!ascii_strcasecmp (model, "shell") )
     return 0;
   else if ( !ascii_strcasecmp (model, "chain") )
     return 1;
   if (!ascii_strcasecmp (model, "shell") )
     return 0;
   else if ( !ascii_strcasecmp (model, "chain") )
     return 1;
+  else if ( !ascii_strcasecmp (model, "steed") )
+    return 2;
   else
     return -1;
 }
   else
     return -1;
 }
@@ -1947,11 +2080,11 @@ check_special_filename (const char *fname, int for_write)
   if (allow_special_filenames
       && fname && *fname == '-' && fname[1] == '&' ) {
     int i;
   if (allow_special_filenames
       && fname && *fname == '-' && fname[1] == '&' ) {
     int i;
-    
+
     fname += 2;
     for (i=0; isdigit (fname[i]); i++ )
       ;
     fname += 2;
     for (i=0; isdigit (fname[i]); i++ )
       ;
-    if ( !fname[i] ) 
+    if ( !fname[i] )
       return translate_sys2libc_fd_int (atoi (fname), for_write);
   }
   return -1;
       return translate_sys2libc_fd_int (atoi (fname), for_write);
   }
   return -1;
@@ -1959,10 +2092,10 @@ check_special_filename (const char *fname, int for_write)
 
 
 
 
 
 
-/* Open the FILENAME for read and return the filedescriptor.  Stop
+/* Open the FILENAME for read and return the file descriptor.  Stop
    with an error message in case of problems.  "-" denotes stdin and
    with an error message in case of problems.  "-" denotes stdin and
-   if special filenames are allowed the given fd is opened instead. */
-static int 
+   if special filenames are allowed the given fd is opened instead.  */
+static int
 open_read (const char *filename)
 {
   int fd;
 open_read (const char *filename)
 {
   int fd;
@@ -1978,44 +2111,37 @@ open_read (const char *filename)
   fd = open (filename, O_RDONLY | O_BINARY);
   if (fd == -1)
     {
   fd = open (filename, O_RDONLY | O_BINARY);
   if (fd == -1)
     {
-      log_error (_("can't open `%s': %s\n"), filename, strerror (errno));
+      log_error (_("can't open '%s': %s\n"), filename, strerror (errno));
       gpgsm_exit (2);
     }
   return fd;
 }
 
       gpgsm_exit (2);
     }
   return fd;
 }
 
-/* Open FILENAME for fwrite and return the stream.  Stop with an error
-   message in case of problems.  "-" denotes stdout and if special
-   filenames are allowed the given fd is opened instead. Caller must
-   close the returned stream unless it is stdout. */
-static FILE *
-open_fwrite (const char *filename)
+/* Same as open_read but return an estream_t.  */
+static estream_t
+open_es_fread (const char *filename, const char *mode)
 {
   int fd;
 {
   int fd;
-  FILE *fp;
+  estream_t fp;
 
   if (filename[0] == '-' && !filename[1])
 
   if (filename[0] == '-' && !filename[1])
-    {
-      set_binary (stdout);
-      return stdout;
-    }
-
-  fd = check_special_filename (filename, 1);
+    fd = fileno (stdin);
+  else
+    fd = check_special_filename (filename, 0);
   if (fd != -1)
     {
   if (fd != -1)
     {
-      fp = fdopen (dup (fd), "wb");
+      fp = es_fdopen_nc (fd, mode);
       if (!fp)
         {
       if (!fp)
         {
-          log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
+          log_error ("es_fdopen(%d) failed: %s\n", fd, strerror (errno));
           gpgsm_exit (2);
         }
           gpgsm_exit (2);
         }
-      set_binary (fp);
       return fp;
     }
       return fp;
     }
-  fp = fopen (filename, "wb");
+  fp = es_fopen (filename, mode);
   if (!fp)
     {
   if (!fp)
     {
-      log_error (_("can't open `%s': %s\n"), filename, strerror (errno));
+      log_error (_("can't open '%s': %s\n"), filename, strerror (errno));
       gpgsm_exit (2);
     }
   return fp;
       gpgsm_exit (2);
     }
   return fp;
@@ -2053,7 +2179,7 @@ open_es_fwrite (const char *filename)
   fp = es_fopen (filename, "wb");
   if (!fp)
     {
   fp = es_fopen (filename, "wb");
   if (!fp)
     {
-      log_error (_("can't open `%s': %s\n"), filename, strerror (errno));
+      log_error (_("can't open '%s': %s\n"), filename, strerror (errno));
       gpgsm_exit (2);
     }
   return fp;
       gpgsm_exit (2);
     }
   return fp;
@@ -2063,7 +2189,10 @@ open_es_fwrite (const char *filename)
 static void
 run_protect_tool (int argc, char **argv)
 {
 static void
 run_protect_tool (int argc, char **argv)
 {
-#ifndef HAVE_W32_SYSTEM
+#ifdef HAVE_W32_SYSTEM
+  (void)argc;
+  (void)argv;
+#else
   const char *pgm;
   char **av;
   int i;
   const char *pgm;
   char **av;
   int i;
@@ -2080,8 +2209,8 @@ run_protect_tool (int argc, char **argv)
   for (i=1; argc; i++, argc--, argv++)
     av[i] = *argv;
   av[i] = NULL;
   for (i=1; argc; i++, argc--, argv++)
     av[i] = *argv;
   av[i] = NULL;
-  execv (pgm, av); 
-  log_error ("error executing `%s': %s\n", pgm, strerror (errno));
-#endif /*HAVE_W32_SYSTEM*/
+  execv (pgm, av);
+  log_error ("error executing '%s': %s\n", pgm, strerror (errno));
+#endif /*!HAVE_W32_SYSTEM*/
   gpgsm_exit (2);
 }
   gpgsm_exit (2);
 }