sm: Do not expect X.509 keyids to be unique
[gnupg.git] / sm / gpgsm.c
index 93e9076..0feda90 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.
  *
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <gcrypt.h>
 #include <assuan.h> /* malloc hooks */
 
+#include "passphrase.h"
+#include "../common/shareddefs.h"
 #include "../kbx/keybox.h" /* malloc hooks */
-#include "i18n.h"
+#include "../common/i18n.h"
 #include "keydb.h"
-#include "sysutils.h"
-#include "gc-opt-flags.h"
+#include "../common/sysutils.h"
+#include "../common/gc-opt-flags.h"
+#include "../common/asshelp.h"
+#include "../common/init.h"
+#include "../common/compliance.h"
 
 
 #ifndef O_BINARY
@@ -72,7 +77,9 @@ enum cmd_and_opt_values {
   aRecvKeys,
   aExport,
   aExportSecretKeyP12,
-  aServer,                        
+  aExportSecretKeyP8,
+  aExportSecretKeyRaw,
+  aServer,
   aLearnCard,
   aCallDirmngr,
   aCallProtectTool,
@@ -95,10 +102,10 @@ enum cmd_and_opt_values {
   oDebugAllowCoreDump,
   oDebugNoChainValidation,
   oDebugIgnoreExpiration,
-  oFixedPassphrase,
   oLogFile,
   oNoLogFile,
   oAuditLog,
+  oHtmlAuditLog,
 
   oEnableSpecialFilenames,
 
@@ -116,6 +123,8 @@ enum cmd_and_opt_values {
   oProtectToolProgram,
   oFakedSystemTime,
 
+  oPassphraseFD,
+  oPinentryMode,
 
   oAssumeArmor,
   oAssumeBase64,
@@ -125,6 +134,8 @@ enum cmd_and_opt_values {
   oNoArmor,
   oP12Charset,
 
+  oCompliance,
+
   oDisableCRLChecks,
   oEnableCRLChecks,
   oDisableTrustedCertCRLCheck,
@@ -139,9 +150,11 @@ enum cmd_and_opt_values {
   oDisablePolicyChecks,
   oEnablePolicyChecks,
   oAutoIssuerKeyRetrieve,
-  
+
   oWithFingerprint,
   oWithMD5Fingerprint,
+  oWithKeygrip,
+  oWithSecret,
   oAnswerYes,
   oAnswerNo,
   oKeyring,
@@ -175,7 +188,9 @@ enum cmd_and_opt_values {
   oDisablePubkeyAlgo,
   oIgnoreTimeConflict,
   oNoRandomSeedFile,
-  oNoCommonCertsImport
+  oNoCommonCertsImport,
+  oIgnoreCertExtension,
+  oNoAutostart
  };
 
 
@@ -184,33 +199,41 @@ static ARGPARSE_OPTS opts[] = {
   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 (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 (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")),
-  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 (aKeygen, "gen-key", N_("generate a new key pair")),
-  ARGPARSE_c (aDeleteKey, "delete-keys", 
+  ARGPARSE_c (aKeygen, "generate-key", N_("generate a new key pair")),
+  ARGPARSE_c (aKeygen, "gen-key", "@"),
+  ARGPARSE_c (aDeleteKey, "delete-keys",
               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 keyserver")),*/
+/*ARGPARSE_c (aRecvKeys, "recv-keys", N_("import keys from a keyserver")),*/
   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 accidentally 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 (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")),
-  ARGPARSE_c (aPasswd, "passwd", N_("change a passphrase")),
+  ARGPARSE_c (aPasswd, "change-passphrase", N_("change a passphrase")),
+  ARGPARSE_c (aPasswd, "passwd", "@"),
   ARGPARSE_c (aGPGConfList, "gpgconf-list", "@"),
   ARGPARSE_c (aGPGConfTest, "gpgconf-test", "@"),
 
@@ -229,24 +252,26 @@ static ARGPARSE_OPTS opts[] = {
 
   ARGPARSE_s_s (oP12Charset, "p12-charset", "@"),
 
-  ARGPARSE_s_n (oAssumeArmor, "assume-armor", 
+  ARGPARSE_s_i (oPassphraseFD,    "passphrase-fd", "@"),
+  ARGPARSE_s_s (oPinentryMode,    "pinentry-mode", "@"),
+
+  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")),
-  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")),
 
-  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", "@"),
-  ARGPARSE_s_n (oEnableTrustedCertCRLCheck, 
+  ARGPARSE_s_n (oEnableTrustedCertCRLCheck,
                 "enable-trusted-cert-crl-check", "@"),
 
   ARGPARSE_s_n (oForceCRLRefresh, "force-crl-refresh", "@"),
@@ -256,7 +281,7 @@ static ARGPARSE_OPTS opts[] = {
 
   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",
@@ -284,8 +309,9 @@ static ARGPARSE_OPTS opts[] = {
   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")),
+  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")),
@@ -308,7 +334,7 @@ static ARGPARSE_OPTS opts[] = {
                 N_("|SPEC|use this keyserver to lookup keys")),
   ARGPARSE_s_s (oOptions, "options", N_("|FILE|read options from FILE")),
 
-  ARGPARSE_p_u (oDebug, "debug", "@"),
+  ARGPARSE_s_s (oDebug, "debug", "@"),
   ARGPARSE_s_s (oDebugLevel, "debug-level",
                 N_("|LEVEL|set the debugging level to LEVEL")),
   ARGPARSE_s_n (oDebugAll, "debug-all", "@"),
@@ -317,39 +343,33 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oDebugAllowCoreDump, "debug-allow-core-dump", "@"),
   ARGPARSE_s_n (oDebugNoChainValidation, "debug-no-chain-validation", "@"),
   ARGPARSE_s_n (oDebugIgnoreExpiration,  "debug-ignore-expiration", "@"),
-  ARGPARSE_s_s (oFixedPassphrase, "fixed-passphrase", "@"),
 
   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", "@"),
-    
+
 
   ARGPARSE_group (302, N_(
   "@\n(See the man page for a complete listing of all commands and options)\n"
   )),
 
-  ARGPARSE_group (303, N_("@\nExamples:\n\n"
-    " -se -r Bob [file]          sign and encrypt for user Bob\n"
-    " --clearsign [file]         make a clear text signature\n"
-    " --detach-sign [file]       make a detached signature\n"
-    " --list-keys [names]        show keys\n"
-    " --fingerprint [names]      show fingerprints\n"  )),
 
   /* Hidden options. */
+  ARGPARSE_s_s (oCompliance, "compliance",   "@"),
   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_s (oHomedir, "homedir", "@"),   
+  ARGPARSE_s_s (oHomedir, "homedir", "@"),
   ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
   ARGPARSE_s_s (oDisplay,    "display", "@"),
   ARGPARSE_s_s (oTTYname,    "ttyname", "@"),
@@ -369,24 +389,41 @@ 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 (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 (oIgnoreCertExtension, "ignore-cert-extension", "@"),
+  ARGPARSE_s_n (oNoAutostart, "no-autostart", "@"),
 
   /* 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-signatures", "@"),
+  ARGPARSE_c (aListChain, "list-sigs", "@"),
+  ARGPARSE_c (aListChain, "check-signatures", "@"),
+  ARGPARSE_c (aListChain, "check-sigs", "@"),
   ARGPARSE_c (aDeleteKey, "delete-key", "@"),
 
   ARGPARSE_end ()
 };
 
 
+/* The list of supported debug flags.  */
+static struct debug_flags_s debug_flags [] =
+  {
+    { DBG_X509_VALUE   , "x509"    },
+    { DBG_MPI_VALUE    , "mpi"     },
+    { DBG_CRYPTO_VALUE , "crypto"  },
+    { DBG_MEMORY_VALUE , "memory"  },
+    { DBG_CACHE_VALUE  , "cache"   },
+    { DBG_MEMSTAT_VALUE, "memstat" },
+    { DBG_HASHING_VALUE, "hashing" },
+    { DBG_IPC_VALUE    , "ipc"     },
+    { 0, NULL }
+  };
 
 
 /* Global variable to keep an error count. */
@@ -399,15 +436,25 @@ static int maybe_setuid = 1;
 static const char *debug_level;
 static unsigned int debug_value;
 
-/* Option --enable-special-filenames */
-static int allow_special_filenames;
+/* Default value for include-certs.  We need an extra macro for
+   gpgconf-list because the variable will be changed by the command
+   line option.
 
-/* Default value for include-certs. */
-static int default_include_certs = 1; /* Only include the signer's cert. */
+   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;
 
+/* The default cipher algo.  */
+#define DEFAULT_CIPHER_ALGO "AES"
+
 
 static char *build_list (const char *text,
                         const char *(*mapf)(int), int (*chkf)(int));
@@ -415,10 +462,8 @@ static void set_cmd (enum cmd_and_opt_values *ret_cmd,
                      enum cmd_and_opt_values new_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 estream_t open_es_fread (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);
 
@@ -483,7 +528,7 @@ make_libversion (const char *libname, const char *(*getfnc)(const char*))
 {
   const char *s;
   char *result;
-  
+
   if (maybe_setuid)
     {
       gcry_control (GCRYCTL_INIT_SECMEM, 0, 0);  /* Drop setuid. */
@@ -505,19 +550,19 @@ my_strusage( int 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;
     case 19: p = _("Please report bugs to <@EMAIL@>.\n"); break;
 
     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:
-      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:
@@ -532,11 +577,11 @@ my_strusage( int level )
       break;
 
     case 31: p = "\nHome: "; break;
-    case 32: p = opt.homedir; break;
+    case 32: p = gnupg_homedir (); break;
     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;
@@ -551,7 +596,7 @@ my_strusage( int level )
         digests = build_list("Hash: ", gcry_md_algo_name, our_md_test_algo );
       p = digests;
       break;
-     
+
     default: p = NULL; break;
     }
   return p;
@@ -564,7 +609,7 @@ build_list (const char *text, const char * (*mapf)(int), int (*chkf)(int))
   int i;
   size_t n=strlen(text)+2;
   char *list, *p;
-  
+
   if (maybe_setuid) {
     gcry_control (GCRYCTL_DROP_PRIVS); /* drop setuid */
   }
@@ -586,7 +631,7 @@ build_list (const char *text, const char * (*mapf)(int), int (*chkf)(int))
        }
     }
   if (p)
-    p = stpcpy(p, "\n" );
+    strcpy (p, "\n" );
   return list;
 }
 
@@ -607,9 +652,7 @@ set_binary (FILE *fp)
 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);
 }
 
@@ -618,7 +661,7 @@ 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",
@@ -633,23 +676,34 @@ set_opt_session_env (const char *name, const char *value)
 static void
 set_debug (void)
 {
+  int numok = (debug_level && digitp (debug_level));
+  int numlvl = numok? atoi (debug_level) : 0;
+
   if (!debug_level)
     ;
-  else if (!strcmp (debug_level, "none"))
+  else if (!strcmp (debug_level, "none") || (numok && numlvl < 1))
     opt.debug = 0;
-  else if (!strcmp (debug_level, "basic"))
-    opt.debug = DBG_ASSUAN_VALUE;
-  else if (!strcmp (debug_level, "advanced"))
-    opt.debug = DBG_ASSUAN_VALUE|DBG_X509_VALUE;
-  else if (!strcmp (debug_level, "expert"))
-    opt.debug = (DBG_ASSUAN_VALUE|DBG_X509_VALUE
+  else if (!strcmp (debug_level, "basic") || (numok && numlvl <= 2))
+    opt.debug = DBG_IPC_VALUE;
+  else if (!strcmp (debug_level, "advanced") || (numok && numlvl <= 5))
+    opt.debug = DBG_IPC_VALUE|DBG_X509_VALUE;
+  else if (!strcmp (debug_level, "expert")  || (numok && numlvl <= 8))
+    opt.debug = (DBG_IPC_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
     {
-      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;
@@ -664,8 +718,11 @@ 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)
+    parse_debug_flag (NULL, &opt.debug, debug_flags);
 }
+
 
 
 static void
@@ -682,7 +739,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 
+  else
     {
       log_error(_("conflicting commands\n"));
       gpgsm_exit(2);
@@ -702,22 +759,12 @@ do_add_recipient (ctrl_t ctrl, const char *name,
     {
       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,
-                     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
-        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));
     }
 }
@@ -728,7 +775,7 @@ parse_validation_model (const char *model)
 {
   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;
 }
@@ -784,43 +831,44 @@ parse_keyserver_line (char *line,
              fail = 1;
            }
          break;
-          
+
        case 2:
          if (*p)
            server->port = atoi (p);
          break;
-         
+
        case 3:
          if (*p)
            server->user = xstrdup (p);
          break;
-         
+
        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;
-         
+
        case 5:
          if (*p)
            server->base = xstrdup (p);
          break;
-         
+
        default:
          /* (We silently ignore extra fields.) */
          break;
        }
     }
-  
+
   if (fail)
     {
       log_info (_("%s:%u: skipping this line\n"), filename, lineno);
       keyserver_list_free (server);
+      server = NULL;
     }
 
   return server;
@@ -833,7 +881,6 @@ main ( int argc, char **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;
@@ -848,6 +895,7 @@ main ( int argc, char **argv)
   int default_keyring = 1;
   char *logfile = NULL;
   char *auditlog = NULL;
+  char *htmlauditlog = NULL;
   int greeting = 0;
   int nogreeting = 0;
   int debug_wait = 0;
@@ -863,32 +911,29 @@ main ( int argc, char **argv)
   int do_not_setup_keys = 0;
   int recp_required = 0;
   estream_t auditfp = NULL;
-
+  estream_t htmlauditfp = NULL;
+  struct assuan_malloc_hooks malloc_hooks;
+  int pwfd = -1;
   /*mtrace();*/
 
-  gnupg_reopen_std ("gpgsm");
+  early_system_init ();
+  gnupg_reopen_std (GPGSM_NAME);
   /* 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 */
-  log_set_prefix ("gpgsm", 1);
+  log_set_prefix (GPGSM_NAME, GPGRT_LOG_WITH_PREFIX);
 
   /* 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) )
-    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_KSBA_VERSION, ksba_check_version (NULL) );
@@ -897,11 +942,15 @@ main ( int argc, char **argv)
   gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);
 
   may_coredump = disable_core_dumps ();
-  
+
   gnupg_init_signals (0, emergency_cleanup);
-  
-  create_dotlock (NULL); /* register locking cleanup */
 
+  dotlock_create (NULL, 0); /* Register lockfile cleanup.  */
+
+  /* Tell the compliance module who we are.  */
+  gnupg_initialize_compliance (GNUPG_MODULE_NAME_GPGSM);
+
+  opt.autostart = 1;
   opt.session_env = session_env_new ();
   if (!opt.session_env)
     log_fatal ("error allocating session environment block: %s\n",
@@ -909,9 +958,8 @@ main ( int argc, char **argv)
 
   /* 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 ();
 
   /* First check whether we have a config file on the commandline */
   orig_argc = argc;
@@ -930,29 +978,34 @@ main ( int argc, char **argv)
           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;
+        gnupg_set_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;
 
-  /* 
-     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 );
 
-  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, NULL);
 
   keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
 
@@ -965,10 +1018,11 @@ main ( int argc, char **argv)
 
   /* Set the default option file */
   if (default_config )
-    configname = make_filename (opt.homedir, "gpgsm.conf", NULL);
+    configname = make_filename (gnupg_homedir (),
+                                GPGSM_NAME EXTSEP_S "conf", NULL);
   /* Set the default policy file */
-  opt.policy_file = make_filename (opt.homedir, "policies.txt", NULL);
-  
+  opt.policy_file = make_filename (gnupg_homedir (), "policies.txt", NULL);
+
   argc        = orig_argc;
   argv        = orig_argv;
   pargs.argc  = &argc;
@@ -984,34 +1038,34 @@ main ( int argc, char **argv)
         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)
-      log_info (_("reading options from `%s'\n"), configname);
+      log_info (_("reading options from '%s'\n"), configname);
     default_config = 0;
   }
 
-  while (!no_more_options 
+  while (!no_more_options
          && 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;
 
-        case aServer: 
+        case aServer:
           opt.batch = 1;
           set_cmd (&cmd, aServer);
           break;
@@ -1028,7 +1082,7 @@ main ( int argc, char **argv)
           no_more_options = 1; /* Stop parsing. */
           do_not_setup_keys = 1;
           break;
-        
+
         case aDeleteKey:
           set_cmd (&cmd, aDeleteKey);
           /*greeting=1;*/
@@ -1037,45 +1091,47 @@ main ( int argc, char **argv)
 
         case aDetachedSign:
           detached_sig = 1;
-          set_cmd (&cmd, aSign ); 
+          set_cmd (&cmd, aSign );
           break;
 
         case aKeygen:
           set_cmd (&cmd, aKeygen);
-          greeting=1; 
+          greeting=1;
           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 aDumpExternalKeys: 
-        case aDumpSecretKeys: 
+        case aDumpExternalKeys:
+        case aDumpSecretKeys:
         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 aEncr: 
+        case aEncr:
           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;
 
@@ -1083,19 +1139,29 @@ main ( int argc, char **argv)
         case oArmor:
           ctrl.create_pem = 1;
           break;
-        case oBase64: 
+        case oBase64:
           ctrl.create_pem = 0;
           ctrl.create_base64 = 1;
           break;
-        case oNoArmor: 
+        case oNoArmor:
           ctrl.create_pem = 0;
           ctrl.create_base64 = 0;
           break;
-          
+
         case oP12Charset:
           opt.p12_charset = pargs.r.ret_str;
           break;
 
+        case oPassphraseFD:
+         pwfd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
+         break;
+
+        case oPinentryMode:
+         opt.pinentry_mode = parse_pinentry_mode (pargs.r.ret_str);
+         if (opt.pinentry_mode == -1)
+            log_error (_("invalid pinentry mode '%s'\n"), pargs.r.ret_str);
+         break;
+
           /* Input encoding selection.  */
         case oAssumeArmor:
           ctrl.autodetect_encoding = 0;
@@ -1136,8 +1202,8 @@ main ( int argc, char **argv)
           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:
@@ -1154,14 +1220,14 @@ main ( int argc, char **argv)
         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 oQuiet: opt.quiet = 1; break;
         case oNoTTY: /* fixme:tty_no_terminal(1);*/ break;
         case oDryRun: opt.dry_run = 1; break;
@@ -1176,22 +1242,29 @@ main ( int argc, char **argv)
           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 oHtmlAuditLog: htmlauditlog = pargs.r.ret_str; break;
 
-        case oBatch: 
+        case oBatch:
           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 oKeyring: append_to_strlist (&nrings, pargs.r.ret_str); break;
 
-        case oDebug: debug_value |= pargs.r.ret_ulong; break;
+        case oDebug:
+          if (parse_debug_flag (pargs.r.ret_str, &debug_value, debug_flags))
+            {
+              pargs.r_opt = ARGPARSE_INVALID_ARG;
+              pargs.err = ARGPARSE_PRINT_ERROR;
+            }
+          break;
         case oDebugAll: debug_value = ~0; break;
         case oDebugNone: debug_value = 0; break;
         case oDebugLevel: debug_level = pargs.r.ret_str; break;
@@ -1201,18 +1274,21 @@ main ( int argc, char **argv)
           break;
         case oDebugNoChainValidation: opt.no_chain_validation = 1; break;
         case oDebugIgnoreExpiration: opt.ignore_expiration = 1; break;
-        case oFixedPassphrase: opt.fixed_passphrase = pargs.r.ret_str; break;
 
         case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
         case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;
         case oWithMD5Fingerprint:
-          opt.with_md5_fingerprint=1; /*fall thru*/
+          opt.with_md5_fingerprint=1; /*fall through*/
         case oWithFingerprint:
-          with_fpr=1; /*fall thru*/
+          with_fpr=1; /*fall through*/
         case aFingerprint:
           opt.fingerprint++;
           break;
 
+        case oWithKeygrip:
+          opt.with_keygrip = 1;
+          break;
+
         case oOptions:
           /* config files may not be nested (silently ignore them) */
           if (!configfp)
@@ -1222,8 +1298,8 @@ main ( int argc, char **argv)
               goto next_pass;
            }
           break;
-        case oNoOptions: break; /* no-options */
-        case oHomedir: opt.homedir = pargs.r.ret_str; break;
+        case oNoOptions: opt.no_homedir_creation = 1; break; /* no-options */
+        case oHomedir: gnupg_set_homedir (pargs.r.ret_str); break;
         case oAgentProgram: opt.agent_program = pargs.r.ret_str;  break;
 
         case oDisplay:
@@ -1244,14 +1320,14 @@ main ( int argc, char **argv)
 
         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:
-          opt.protect_tool_program = pargs.r.ret_str; 
+          opt.protect_tool_program = pargs.r.ret_str;
           break;
-          
+
         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);
@@ -1283,8 +1359,9 @@ main ( int argc, char **argv)
           opt.def_recipient_self = 0;
           break;
 
-        case oWithKeyData: opt.with_key_data=1; /* fall thru */
+        case oWithKeyData: opt.with_key_data=1; /* fall through */
         case oWithColons: ctrl.with_colons = 1; break;
+        case oWithSecret: ctrl.with_secret = 1; break;
         case oWithValidation: ctrl.with_validation=1; break;
         case oWithEphemeralKeys: ctrl.with_ephemeral_keys=1; break;
 
@@ -1307,20 +1384,20 @@ main ( int argc, char **argv)
           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;
 
-        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;
-        case oDisablePubkeyAlgo: 
+        case oDisablePubkeyAlgo:
           {
             int algo = gcry_pk_map_name (pargs.r.ret_str);
             gcry_pk_ctl (GCRYCTL_DISABLE_ALGO,&algo, sizeof algo );
@@ -1331,7 +1408,7 @@ main ( int argc, char **argv)
           forced_digest_algo = pargs.r.ret_str;
           break;
 
-        case oExtraDigestAlgo: 
+        case oExtraDigestAlgo:
           extra_digest_algo = pargs.r.ret_str;
           break;
 
@@ -1339,7 +1416,9 @@ main ( int argc, char **argv)
         case oNoRandomSeedFile: use_random_seed = 0; break;
         case oNoCommonCertsImport: no_common_certs_import = 1; break;
 
-        case oEnableSpecialFilenames: allow_special_filenames =1; break;
+        case oEnableSpecialFilenames:
+          enable_special_filenames ();
+          break;
 
         case oValidationModel: parse_validation_model (pargs.r.ret_str); break;
 
@@ -1361,8 +1440,30 @@ main ( int argc, char **argv)
          }
          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;
+
+        case oCompliance:
+          {
+            struct gnupg_compliance_option compliance_options[] =
+              {
+                { "de-vs", CO_DE_VS }
+              };
+            int compliance = gnupg_parse_compliance_option (pargs.r.ret_str,
+                                                            compliance_options,
+                                                            DIM (compliance_options),
+                                                            opt.quiet);
+            if (compliance < 0)
+              gpgsm_exit (1);
+            opt.compliance = compliance;
+          }
+          break;
+
+        default:
+          pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
           break;
        }
     }
@@ -1380,23 +1481,28 @@ main ( int argc, char **argv)
   configname = NULL;
 
   if (!opt.config_filename)
-    opt.config_filename = make_filename (opt.homedir, "gpgsm.conf", NULL);
+    opt.config_filename = make_filename (gnupg_homedir (),
+                                         GPGSM_NAME EXTSEP_S "conf",
+                                         NULL);
 
   if (log_get_errorcount(0))
     gpgsm_exit(2);
 
+  if (pwfd != -1)      /* Read the passphrase now.  */
+    read_passphrase_from_fd (pwfd);
+
   /* Now that we have the options parsed we need to update the default
      control structure.  */
   gpgsm_init_default_ctrl (&ctrl);
 
   if (nogreeting)
     greeting = 0;
-  
+
   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)
@@ -1407,23 +1513,18 @@ main ( int argc, char **argv)
     }
 #  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 (opt.qualsig_approval && !opt.quiet) */
-/*     log_info (_("This software has offically been approved to " */
+/*     log_info (_("This software has officially been approved to " */
 /*                 "create and verify\n" */
 /*                 "qualified signatures according to German law.\n")); */
 
   if (logfile && cmd == aServer)
     {
       log_set_file (logfile);
-      log_set_prefix (NULL, 1|2|4);
+      log_set_prefix (NULL, GPGRT_LOG_WITH_PREFIX | GPGRT_LOG_WITH_TIME | GPGRT_LOG_WITH_PID);
     }
 
   if (gnupg_faked_time_p ())
@@ -1435,7 +1536,17 @@ main ( int argc, char **argv)
       dump_isotime (tbuf);
       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); */
 
@@ -1443,7 +1554,7 @@ main ( int argc, char **argv)
 
   set_debug ();
 
-  /* Although we alwasy use gpgsm_exit, we better install a regualr
+  /* Although we always use gpgsm_exit, we better install a regualr
      exit handler so that at least the secure memory gets wiped
      out. */
   if (atexit (emergency_cleanup))
@@ -1462,6 +1573,8 @@ main ( int argc, char **argv)
   else if (!strcmp (opt.def_cipher_algoid, "AES")
            || !strcmp (opt.def_cipher_algoid, "AES128"))
     opt.def_cipher_algoid = "2.16.840.1.101.3.4.1.2";
+  else if (!strcmp (opt.def_cipher_algoid, "AES192") )
+    opt.def_cipher_algoid = "2.16.840.1.101.3.4.1.22";
   else if (!strcmp (opt.def_cipher_algoid, "AES256") )
     opt.def_cipher_algoid = "2.16.840.1.101.3.4.1.42";
   else if (!strcmp (opt.def_cipher_algoid, "SERPENT")
@@ -1469,11 +1582,11 @@ main ( int argc, char **argv)
     opt.def_cipher_algoid = "1.3.6.1.4.1.11591.13.2.2";
   else if (!strcmp (opt.def_cipher_algoid, "SERPENT192") )
     opt.def_cipher_algoid = "1.3.6.1.4.1.11591.13.2.22";
-  else if (!strcmp (opt.def_cipher_algoid, "SERPENT192") )
+  else if (!strcmp (opt.def_cipher_algoid, "SERPENT256") )
     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") )
@@ -1501,36 +1614,74 @@ main ( int argc, char **argv)
         }
     }
 
+  /* Check our chosen algorithms against the list of allowed
+   * algorithms in the current compliance mode, and fail hard if it is
+   * not.  This is us being nice to the user informing her early that
+   * the chosen algorithms are not available.  We also check and
+   * enforce this right before the actual operation.  */
+  if (! gnupg_cipher_is_allowed (opt.compliance,
+                                 cmd == aEncr || cmd == aSignEncr,
+                                 gcry_cipher_map_name (opt.def_cipher_algoid),
+                                 GCRY_CIPHER_MODE_NONE)
+      && ! gnupg_cipher_is_allowed (opt.compliance,
+                                    cmd == aEncr || cmd == aSignEncr,
+                                    gcry_cipher_mode_from_oid
+                                    (opt.def_cipher_algoid),
+                                    GCRY_CIPHER_MODE_NONE))
+    log_error (_("cipher algorithm '%s' may not be used in %s mode\n"),
+               opt.def_cipher_algoid,
+               gnupg_compliance_option_string (opt.compliance));
+
+  if (forced_digest_algo
+      && ! gnupg_digest_is_allowed (opt.compliance,
+                                     cmd == aSign
+                                     || cmd == aSignEncr
+                                     || cmd == aClearsign,
+                                     opt.forced_digest_algo))
+    log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
+               forced_digest_algo,
+               gnupg_compliance_option_string (opt.compliance));
+
+  if (extra_digest_algo
+      && ! gnupg_digest_is_allowed (opt.compliance,
+                                     cmd == aSign
+                                     || cmd == aSignEncr
+                                     || cmd == aClearsign,
+                                     opt.extra_digest_algo))
+    log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
+               forced_digest_algo,
+               gnupg_compliance_option_string (opt.compliance));
+
   if (log_get_errorcount(0))
     gpgsm_exit(2);
-  
+
   /* Set the random seed file. */
-  if (use_random_seed) 
+  if (use_random_seed)
     {
-      char *p = make_filename (opt.homedir, "random_seed", NULL);
+      char *p = make_filename (gnupg_homedir (), "random_seed", NULL);
       gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
       xfree(p);
     }
-  
+
   if (!cmd && opt.fingerprint && !with_fpr)
     set_cmd (&cmd, aListKeys);
-  
+
   /* Add default keybox. */
   if (!nrings && default_keyring)
     {
       int created;
 
-      keydb_add_resource ("pubring.kbx", 0, 0, &created);
+      keydb_add_resource (&ctrl, "pubring.kbx", 0, &created);
       if (created && !no_common_certs_import)
         {
           /* 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))
             {
-              log_info (_("importing common certificates `%s'\n"),
+              log_info (_("importing common certificates '%s'\n"),
                         filelist[0]);
               gpgsm_import_files (&ctrl, 1, filelist, open_read);
             }
@@ -1538,22 +1689,25 @@ main ( int argc, char **argv)
         }
     }
   for (sl = nrings; sl; sl = sl->next)
-    keydb_add_resource (sl->d, 0, 0, NULL);
+    keydb_add_resource (&ctrl, sl->d, 0, NULL);
   FREE_STRLIST(nrings);
 
 
   /* Prepare the audit log feature for certain commands.  */
-  if (auditlog)
+  if (auditlog || htmlauditlog)
     {
       switch (cmd)
         {
-        case aEncr: 
+        case aEncr:
         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;
@@ -1568,27 +1722,18 @@ main ( int argc, char **argv)
           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));
+              gpgsm_status2 (&ctrl, STATUS_INV_SGNR,
+                             get_inv_recpsgnr_code (rc), sl->d, NULL);
               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
+         ignore duplicates and we can't allow keeping a duplicate which is
          flagged as encrypt-to as the actually encrypt function would then
          complain about no (regular) recipients. */
       for (sl = remusr; sl; sl = sl->next)
@@ -1604,39 +1749,43 @@ main ( int argc, char **argv)
 
   if (log_get_errorcount(0))
     gpgsm_exit(1); /* Must stop for invalid recipients. */
-  
-  fname = argc? *argv : NULL;
-  
+
   /* 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);
 
-        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);
 
-        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 ("enable-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;
@@ -1670,42 +1819,40 @@ main ( int argc, char **argv)
 
     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. */
-          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]");
 
-        if (fp != stdout)
-          fclose (fp);
+        es_fclose (fp);
       }
       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
+        /* Fixme: We should also allow concatenation of 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,
-                      open_read (*argv), detached_sig, fp); 
+                      open_read (*argv), detached_sig, fp);
         else
           wrong_args ("--sign [datafile]");
 
-        if (fp != stdout)
-          fclose (fp);
+        es_fclose (fp);
       }
       break;
-        
+
     case aSignEncr: /* sign and encrypt the given file */
       log_error ("this command has not yet been implemented\n");
       break;
@@ -1716,31 +1863,30 @@ main ( int argc, char **argv)
 
     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)
-          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) */
-          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]]");
 
-        if (fp && fp != stdout)
-          fclose (fp);
+        es_fclose (fp);
       }
       break;
 
     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)
@@ -1749,8 +1895,8 @@ main ( int argc, char **argv)
           gpgsm_decrypt (&ctrl, open_read (*argv), fp); /* from file */
         else
           wrong_args ("--decrypt [filename]");
-        if (fp != stdout)
-          fclose (fp);
+
+        es_fclose (fp);
       }
       break;
 
@@ -1763,7 +1909,7 @@ main ( int argc, char **argv)
 
     case aListChain:
     case aDumpChain:
-       ctrl.with_chain = 1;
+       ctrl.with_chain = 1; /* fall through */
     case aListKeys:
     case aDumpKeys:
     case aListExternalKeys:
@@ -1778,7 +1924,7 @@ main ( int argc, char **argv)
           {
           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;
@@ -1800,27 +1946,26 @@ main ( int argc, char **argv)
     case aKeygen: /* Generate a key; well kind of. */
       {
         estream_t fpin = NULL;
-        FILE *fpout;
+        estream_t fpout;
 
         if (opt.batch)
           {
             if (!argc) /* Create from stdin. */
-              fpin = open_es_fread ("-"); 
+              fpin = open_es_fread ("-", "r");
             else if (argc == 1) /* From file. */
-              fpin = open_es_fread (*argv); 
+              fpin = open_es_fread (*argv, "r");
             else
-              wrong_args ("--gen-key --batch [parmfile]");
+              wrong_args ("--generate-key --batch [parmfile]");
           }
-        
-        fpout = open_fwrite (opt.outfile?opt.outfile:"-");
+
+        fpout = open_es_fwrite (opt.outfile?opt.outfile:"-");
 
         if (fpin)
           gpgsm_genkey (&ctrl, fpin, fpout);
         else
           gpgsm_gencertreq_tty (&ctrl, fpout);
 
-        if (fpout != stdout)
-          fclose (fpout);
+        es_fclose (fpout);
       }
       break;
 
@@ -1831,30 +1976,56 @@ main ( int argc, char **argv)
 
     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);
-        gpgsm_export (&ctrl, sl, fp, NULL);
+        gpgsm_export (&ctrl, sl, fp);
         free_strlist(sl);
-        if (fp != stdout)
-          fclose (fp);
+        es_fclose (fp);
       }
       break;
 
     case aExportSecretKeyP12:
       {
-        FILE *fp = open_fwrite (opt.outfile?opt.outfile:"-");
+        estream_t fp = open_es_fwrite (opt.outfile?opt.outfile:"-");
 
         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");
-        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;
-      
+
     case aSendKeys:
     case aRecvKeys:
       log_error ("this command has not yet been implemented\n");
@@ -1874,19 +2045,19 @@ main ( int argc, char **argv)
 
     case aPasswd:
       if (argc != 1)
-        wrong_args ("--passwd <key-Id>");
+        wrong_args ("--change-passphrase <key-Id>");
       else
         {
           int rc;
           ksba_cert_t cert = NULL;
           char *grip = NULL;
 
-          rc = gpgsm_find_cert (*argv, NULL, &cert);
+          rc = gpgsm_find_cert (&ctrl, *argv, NULL, &cert, 0);
           if (rc)
             ;
           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);
@@ -1913,14 +2084,18 @@ main ( int argc, char **argv)
     }
 
   /* 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);
+      es_fclose (htmlauditfp);
     }
-  
+
   /* cleanup */
   keyserver_list_free (opt.keyserver);
   opt.keyserver = NULL;
@@ -1963,45 +2138,29 @@ gpgsm_init_default_ctrl (struct server_control_s *ctrl)
   ctrl->include_certs = default_include_certs;
   ctrl->use_ocsp = opt.enable_ocsp;
   ctrl->validation_model = default_validation_model;
+  ctrl->offline = opt.disable_dirmngr;
 }
 
 
 int
 gpgsm_parse_validation_model (const char *model)
-{     
+{
   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;
 }
 
 
-/* Check whether the filename has the form "-&nnnn", where n is a
-   non-zero number.  Returns this number or -1 if it is not the case.  */
-static int
-check_special_filename (const char *fname, int for_write)
-{
-  if (allow_special_filenames
-      && fname && *fname == '-' && fname[1] == '&' ) {
-    int i;
-    
-    fname += 2;
-    for (i=0; isdigit (fname[i]); i++ )
-      ;
-    if ( !fname[i] ) 
-      return translate_sys2libc_fd_int (atoi (fname), for_write);
-  }
-  return -1;
-}
-
-
 
-/* 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
-   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;
@@ -2011,13 +2170,13 @@ open_read (const char *filename)
       set_binary (stdin);
       return 0; /* stdin */
     }
-  fd = check_special_filename (filename, 0);
+  fd = check_special_filename (filename, 0, 0);
   if (fd != -1)
     return fd;
   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;
@@ -2025,7 +2184,7 @@ open_read (const char *filename)
 
 /* Same as open_read but return an estream_t.  */
 static estream_t
-open_es_fread (const char *filename)
+open_es_fread (const char *filename, const char *mode)
 {
   int fd;
   estream_t fp;
@@ -2033,10 +2192,10 @@ open_es_fread (const char *filename)
   if (filename[0] == '-' && !filename[1])
     fd = fileno (stdin);
   else
-    fd = check_special_filename (filename, 0);
+    fd = check_special_filename (filename, 0, 0);
   if (fd != -1)
     {
-      fp = es_fdopen_nc (fd, "rb");
+      fp = es_fdopen_nc (fd, mode);
       if (!fp)
         {
           log_error ("es_fdopen(%d) failed: %s\n", fd, strerror (errno));
@@ -2044,48 +2203,10 @@ open_es_fread (const char *filename)
         }
       return fp;
     }
-  fp = es_fopen (filename, "rb");
+  fp = es_fopen (filename, mode);
   if (!fp)
     {
-      log_error (_("can't open `%s': %s\n"), filename, strerror (errno));
-      gpgsm_exit (2);
-    }
-  return fp;
-}
-
-
-/* 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)
-{
-  int fd;
-  FILE *fp;
-
-  if (filename[0] == '-' && !filename[1])
-    {
-      set_binary (stdout);
-      return stdout;
-    }
-
-  fd = check_special_filename (filename, 1);
-  if (fd != -1)
-    {
-      fp = fdopen (dup (fd), "wb");
-      if (!fp)
-        {
-          log_error ("fdopen(%d) failed: %s\n", fd, strerror (errno));
-          gpgsm_exit (2);
-        }
-      set_binary (fp);
-      return fp;
-    }
-  fp = 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;
@@ -2109,7 +2230,7 @@ open_es_fwrite (const char *filename)
       return fp;
     }
 
-  fd = check_special_filename (filename, 1);
+  fd = check_special_filename (filename, 1, 0);
   if (fd != -1)
     {
       fp = es_fdopen_nc (fd, "wb");
@@ -2123,7 +2244,7 @@ open_es_fwrite (const char *filename)
   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;
@@ -2133,7 +2254,10 @@ open_es_fwrite (const char *filename)
 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;
@@ -2150,8 +2274,8 @@ run_protect_tool (int argc, char **argv)
   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);
 }