Merge branch 'STABLE-BRANCH-2-2'
[gnupg.git] / g10 / gpg.c
index c54facb..61e39b8 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -1,7 +1,7 @@
 /* gpg.c - The GnuPG utility (main for gpg)
  * Copyright (C) 1998-2011 Free Software Foundation, Inc.
- * Copyright (C) 1997-2016 Werner Koch
- * Copyright (C) 2015-2016 g10 Code GmbH
+ * Copyright (C) 1997-2017 Werner Koch
+ * Copyright (C) 2015-2017 g10 Code GmbH
  *
  * This file is part of GnuPG.
  *
 #include "gpg.h"
 #include <assuan.h>
 #include "../common/iobuf.h"
-#include "util.h"
+#include "../common/util.h"
 #include "packet.h"
-#include "membuf.h"
+#include "../common/membuf.h"
 #include "main.h"
 #include "options.h"
 #include "keydb.h"
 #include "trustdb.h"
 #include "filter.h"
-#include "ttyio.h"
-#include "i18n.h"
-#include "sysutils.h"
-#include "status.h"
+#include "../common/ttyio.h"
+#include "../common/i18n.h"
+#include "../common/sysutils.h"
+#include "../common/status.h"
 #include "keyserver-internal.h"
 #include "exec.h"
-#include "gc-opt-flags.h"
-#include "asshelp.h"
+#include "../common/gc-opt-flags.h"
+#include "../common/asshelp.h"
 #include "call-dirmngr.h"
 #include "tofu.h"
 #include "../common/init.h"
 #include "../common/mbox-util.h"
 #include "../common/shareddefs.h"
+#include "../common/compliance.h"
 
 #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
 #define MY_O_BINARY  O_BINARY
@@ -73,6 +74,9 @@
 #define MY_O_BINARY  0
 #endif
 
+#ifdef __MINGW32__
+int _dowildcard = -1;
+#endif
 
 enum cmd_and_opt_values
   {
@@ -123,6 +127,8 @@ enum cmd_and_opt_values
     aQuickAddUid,
     aQuickAddKey,
     aQuickRevUid,
+    aQuickSetExpire,
+    aQuickSetPrimaryUid,
     aListConfig,
     aListGcryptConfig,
     aGPGConfList,
@@ -191,10 +197,12 @@ enum cmd_and_opt_values
     oWithSubkeyFingerprint,
     oWithICAOSpelling,
     oWithKeygrip,
+    oWithKeyScreening,
     oWithSecret,
     oWithWKDHash,
     oWithColons,
     oWithKeyData,
+    oWithKeyOrigin,
     oWithTofuInfo,
     oWithSigList,
     oWithSigCheck,
@@ -367,6 +375,7 @@ enum cmd_and_opt_values
     oPersonalCompressPreferences,
     oAgentProgram,
     oDirmngrProgram,
+    oDisableDirmngr,
     oDisplay,
     oTTYname,
     oTTYtype,
@@ -407,11 +416,13 @@ enum cmd_and_opt_values
     oPrintDANERecords,
     oTOFUDefaultPolicy,
     oTOFUDBFormat,
+    oDefaultNewKeyAlgo,
     oWeakDigest,
     oUnwrap,
     oOnlySignTextIDs,
     oDisableSignerUID,
     oSender,
+    oKeyOrigin,
 
     oNoop
   };
@@ -422,7 +433,8 @@ 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, "clear-sign", N_("make a clear text signature")),
+  ARGPARSE_c (aClearsign, "clearsign", "@"),
   ARGPARSE_c (aDetachedSign, "detach-sign", N_("make a detached signature")),
   ARGPARSE_c (aEncr, "encrypt",   N_("encrypt data")),
   ARGPARSE_c (aEncrFiles, "encrypt-files", "@"),
@@ -434,22 +446,36 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_c (aVerifyFiles, "verify-files" , "@" ),
   ARGPARSE_c (aListKeys, "list-keys", N_("list keys")),
   ARGPARSE_c (aListKeys, "list-public-keys", "@" ),
-  ARGPARSE_c (aListSigs, "list-sigs", N_("list keys and signatures")),
-  ARGPARSE_c (aCheckKeys, "check-sigs",N_("list and check key signatures")),
+  ARGPARSE_c (aListSigs, "list-signatures", N_("list keys and signatures")),
+  ARGPARSE_c (aListSigs, "list-sigs", "@"),
+  ARGPARSE_c (aCheckKeys, "check-signatures",
+             N_("list and check key signatures")),
+  ARGPARSE_c (aCheckKeys, "check-sigs", "@"),
   ARGPARSE_c (oFingerprint, "fingerprint", N_("list keys and fingerprints")),
   ARGPARSE_c (aListSecretKeys, "list-secret-keys", N_("list secret keys")),
-  ARGPARSE_c (aKeygen,     "gen-key",
+  ARGPARSE_c (aKeygen,     "generate-key",
               N_("generate a new key pair")),
-  ARGPARSE_c (aQuickKeygen, "quick-gen-key" ,
+  ARGPARSE_c (aKeygen,     "gen-key", "@"),
+  ARGPARSE_c (aQuickKeygen, "quick-generate-key" ,
               N_("quickly generate a new key pair")),
-  ARGPARSE_c (aQuickAddUid,  "quick-adduid",
+  ARGPARSE_c (aQuickKeygen, "quick-gen-key", "@"),
+  ARGPARSE_c (aQuickAddUid,  "quick-add-uid",
               N_("quickly add a new user-id")),
+  ARGPARSE_c (aQuickAddUid,  "quick-adduid", "@"),
+  ARGPARSE_c (aQuickAddKey,  "quick-add-key", "@"),
   ARGPARSE_c (aQuickAddKey,  "quick-addkey", "@"),
-  ARGPARSE_c (aQuickRevUid,  "quick-revuid",
+  ARGPARSE_c (aQuickRevUid,  "quick-revoke-uid",
               N_("quickly revoke a user-id")),
-  ARGPARSE_c (aFullKeygen,  "full-gen-key" ,
+  ARGPARSE_c (aQuickRevUid,  "quick-revuid", "@"),
+  ARGPARSE_c (aQuickSetExpire,  "quick-set-expire",
+              N_("quickly set a new expiration date")),
+  ARGPARSE_c (aQuickSetPrimaryUid,  "quick-set-primary-uid", "@"),
+  ARGPARSE_c (aFullKeygen,  "full-generate-key" ,
               N_("full featured key pair generation")),
-  ARGPARSE_c (aGenRevoke, "gen-revoke",N_("generate a revocation certificate")),
+  ARGPARSE_c (aFullKeygen,  "full-gen-key", "@"),
+  ARGPARSE_c (aGenRevoke, "generate-revocation",
+             N_("generate a revocation certificate")),
+  ARGPARSE_c (aGenRevoke, "gen-revoke", "@"),
   ARGPARSE_c (aDeleteKeys,"delete-keys",
               N_("remove keys from the public keyring")),
   ARGPARSE_c (aDeleteSecretKeys, "delete-secret-keys",
@@ -462,11 +488,14 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_c (aLSignKey, "lsign-key"  ,N_("sign a key locally")),
   ARGPARSE_c (aEditKey,  "edit-key"   ,N_("sign or edit a key")),
   ARGPARSE_c (aEditKey,  "key-edit"   ,"@"),
-  ARGPARSE_c (aPasswd,   "passwd",     N_("change a passphrase")),
+  ARGPARSE_c (aPasswd,   "change-passphrase", N_("change a passphrase")),
+  ARGPARSE_c (aPasswd,   "passwd", "@"),
+  ARGPARSE_c (aDesigRevoke, "generate-designated-revocation", "@"),
   ARGPARSE_c (aDesigRevoke, "desig-revoke","@" ),
   ARGPARSE_c (aExport, "export"           , N_("export keys") ),
   ARGPARSE_c (aSendKeys, "send-keys"     , N_("export keys to a keyserver") ),
-  ARGPARSE_c (aRecvKeys, "recv-keys"     , N_("import keys from a keyserver") ),
+  ARGPARSE_c (aRecvKeys, "receive-keys" , N_("import keys from a keyserver") ),
+  ARGPARSE_c (aRecvKeys, "recv-keys"     , "@"),
   ARGPARSE_c (aSearchKeys, "search-keys" ,
               N_("search for keys on a keyserver") ),
   ARGPARSE_c (aRefreshKeys, "refresh-keys",
@@ -480,7 +509,8 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_c (aFastImport, "fast-import", "@"),
 #ifdef ENABLE_CARD_SUPPORT
   ARGPARSE_c (aCardStatus,  "card-status", N_("print the card status")),
-  ARGPARSE_c (aCardEdit,   "card-edit",  N_("change data on a card")),
+  ARGPARSE_c (aCardEdit,   "edit-card",  N_("change data on a card")),
+  ARGPARSE_c (aCardEdit,   "card-edit", "@"),
   ARGPARSE_c (aChangePIN,  "change-pin", N_("change a card's PIN")),
 #endif
   ARGPARSE_c (aListConfig, "list-config", "@"),
@@ -589,6 +619,7 @@ static ARGPARSE_OPTS opts[] = {
 
   ARGPARSE_s_s (oKeyServer, "keyserver", "@"),
   ARGPARSE_s_s (oKeyServerOptions, "keyserver-options", "@"),
+  ARGPARSE_s_s (oKeyOrigin, "key-origin", "@"),
   ARGPARSE_s_s (oImportOptions, "import-options", "@"),
   ARGPARSE_s_s (oImportFilter,  "import-filter", "@"),
   ARGPARSE_s_s (oExportOptions, "export-options", "@"),
@@ -656,7 +687,7 @@ static ARGPARSE_OPTS opts[] = {
 
   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"
+    " --clear-sign [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")),
@@ -708,9 +739,9 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oWithKeyData,"with-key-data", "@"),
   ARGPARSE_s_n (oWithSigList,"with-sig-list", "@"),
   ARGPARSE_s_n (oWithSigCheck,"with-sig-check", "@"),
-  ARGPARSE_s_n (aListKeys, "list-key", "@"),   /* alias */
-  ARGPARSE_s_n (aListSigs, "list-sig", "@"),   /* alias */
-  ARGPARSE_s_n (aCheckKeys, "check-sig", "@"), /* alias */
+  ARGPARSE_c (aListKeys, "list-key", "@"),   /* alias */
+  ARGPARSE_c (aListSigs, "list-sig", "@"),   /* alias */
+  ARGPARSE_c (aCheckKeys, "check-sig", "@"), /* alias */
   ARGPARSE_s_n (oSkipVerify, "skip-verify", "@"),
   ARGPARSE_s_n (oSkipHiddenRecipients, "skip-hidden-recipients", "@"),
   ARGPARSE_s_n (oNoSkipHiddenRecipients, "no-skip-hidden-recipients", "@"),
@@ -755,8 +786,10 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oWithSubkeyFingerprint, "with-subkey-fingerprints", "@"),
   ARGPARSE_s_n (oWithICAOSpelling, "with-icao-spelling", "@"),
   ARGPARSE_s_n (oWithKeygrip,     "with-keygrip", "@"),
+  ARGPARSE_s_n (oWithKeyScreening,"with-key-screening", "@"),
   ARGPARSE_s_n (oWithSecret,      "with-secret", "@"),
   ARGPARSE_s_n (oWithWKDHash,     "with-wkd-hash", "@"),
+  ARGPARSE_s_n (oWithKeyOrigin,   "with-key-origin", "@"),
   ARGPARSE_s_s (oDisableCipherAlgo,  "disable-cipher-algo", "@"),
   ARGPARSE_s_s (oDisablePubkeyAlgo,  "disable-pubkey-algo", "@"),
   ARGPARSE_s_n (oAllowNonSelfsignedUID,      "allow-non-selfsigned-uid", "@"),
@@ -807,6 +840,7 @@ static ARGPARSE_OPTS opts[] = {
 
   ARGPARSE_s_s (oAgentProgram, "agent-program", "@"),
   ARGPARSE_s_s (oDirmngrProgram, "dirmngr-program", "@"),
+  ARGPARSE_s_n (oDisableDirmngr, "disable-dirmngr", "@"),
   ARGPARSE_s_s (oDisplay,    "display",    "@"),
   ARGPARSE_s_s (oTTYname,    "ttyname",    "@"),
   ARGPARSE_s_s (oTTYtype,    "ttytype",    "@"),
@@ -836,6 +870,8 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oNoAllowMultipleMessages, "no-allow-multiple-messages", "@"),
   ARGPARSE_s_n (oAllowWeakDigestAlgos, "allow-weak-digest-algos", "@"),
 
+  ARGPARSE_s_s (oDefaultNewKeyAlgo, "default-new-key-algo", "@"),
+
   /* These two are aliases to help users of the PGP command line
      product use gpg with minimal pain.  Many commands are common
      already as they seem to have borrowed commands from us.  Now I'm
@@ -891,7 +927,6 @@ static struct debug_flags_s debug_flags [] =
     { DBG_MEMSTAT_VALUE, "memstat" },
     { DBG_TRUST_VALUE  , "trust"   },
     { DBG_HASHING_VALUE, "hashing" },
-    { DBG_CARD_IO_VALUE, "cardio"  },
     { DBG_IPC_VALUE    , "ipc"     },
     { DBG_CLOCK_VALUE  , "clock"   },
     { DBG_LOOKUP_VALUE , "lookup"  },
@@ -1751,6 +1786,15 @@ list_config(char *items)
          any=1;
        }
 
+      if(show_all || ascii_strcasecmp (name, "compressname") == 0)
+       {
+         es_printf ("cfg:compressname:");
+         print_algo_names (check_compress_algo,
+                           compress_algo_to_string);
+         es_printf ("\n");
+         any=1;
+       }
+
       if (show_all || !ascii_strcasecmp(name,"ccid-reader-id"))
        {
           /* We ignore this for GnuPG 1.4 backward compatibility.  */
@@ -1810,14 +1854,22 @@ gpgconf_list (const char *configfile)
   es_printf ("encrypt-to:%lu:\n", GC_OPT_FLAG_NONE);
   es_printf ("try-secret-key:%lu:\n", GC_OPT_FLAG_NONE);
   es_printf ("auto-key-locate:%lu:\n", GC_OPT_FLAG_NONE);
+  es_printf ("auto-key-retrieve:%lu:\n", GC_OPT_FLAG_NONE);
   es_printf ("log-file:%lu:\n", GC_OPT_FLAG_NONE);
   es_printf ("debug-level:%lu:\"none:\n", GC_OPT_FLAG_DEFAULT);
   es_printf ("group:%lu:\n", GC_OPT_FLAG_NONE);
+  es_printf ("compliance:%lu:\"%s:\n", GC_OPT_FLAG_DEFAULT, "gnupg");
+  es_printf ("default-new-key-algo:%lu:\n", GC_OPT_FLAG_NONE);
+  es_printf ("trust-model:%lu:\n", GC_OPT_FLAG_NONE);
+  es_printf ("disable-dirmngr:%lu:\n", GC_OPT_FLAG_NONE);
+  es_printf ("max-cert-depth:%lu:\n", GC_OPT_FLAG_NONE);
+  es_printf ("completes-needed:%lu:\n", GC_OPT_FLAG_NONE);
+  es_printf ("marginals-needed:%lu:\n", GC_OPT_FLAG_NONE);
 
   /* The next one is an info only item and should match the macros at
      the top of keygen.c  */
   es_printf ("default_pubkey_algo:%lu:\"%s:\n", GC_OPT_FLAG_DEFAULT,
-             "RSA-2048");
+             get_default_pubkey_algo ());
 
   xfree (configfile_esc);
 }
@@ -2034,11 +2086,8 @@ parse_tofu_policy (const char *policystr)
 }
 
 
-/* Parse the value of --compliance.  */
-static int
-parse_compliance_option (const char *string)
-{
-  struct { const char *keyword; enum cmd_and_opt_values option; } list[] = {
+static struct gnupg_compliance_option compliance_options[] =
+  {
     { "gnupg",      oGnuPG },
     { "openpgp",    oOpenPGP },
     { "rfc4880bis", oRFC4880bis },
@@ -2049,29 +2098,9 @@ parse_compliance_option (const char *string)
     { "pgp8",       oPGP8 },
     { "de-vs",      oDE_VS }
   };
-  int i;
-
-  if (!ascii_strcasecmp (string, "help"))
-    {
-      log_info (_("valid values for option '%s':\n"), "--compliance");
-      for (i=0; i < DIM (list); i++)
-        log_info ("  %s\n", list[i].keyword);
-      g10_exit (1);
-    }
-
-  for (i=0; i < DIM (list); i++)
-    if (!ascii_strcasecmp (string, list[i].keyword))
-      return list[i].option;
-
-  log_error (_("invalid value for option '%s'\n"), "--compliance");
-  if (!opt.quiet)
-    log_info (_("(use \"help\" to list choices)\n"));
-  g10_exit (1);
-}
-
 
 
-/* Helper to set compliance related options.  This is a separte
+/* Helper to set compliance related options.  This is a separate
  * function so that it can also be used by the --compliance option
  * parser.  */
 static void
@@ -2127,6 +2156,7 @@ set_compliance_option (enum cmd_and_opt_values option)
     case oDE_VS:
       set_compliance_option (oOpenPGP);
       opt.compliance = CO_DE_VS;
+      opt.force_mdc = 1;
       /* Fixme: Change other options.  */
       break;
 
@@ -2146,7 +2176,7 @@ set_compliance_option (enum cmd_and_opt_values option)
 static void
 gpg_init_default_ctrl (ctrl_t ctrl)
 {
-  (void)ctrl;
+  ctrl->magic = SERVER_CONTROL_MAGIC;
 }
 
 
@@ -2159,6 +2189,8 @@ gpg_deinit_default_ctrl (ctrl_t ctrl)
   tofu_closedbs (ctrl);
 #endif
   gpg_dirmngr_deinit_session_data (ctrl);
+
+  keydb_release (ctrl->cached_getkey_kdb);
 }
 
 
@@ -2268,6 +2300,7 @@ main (int argc, char **argv)
     int ovrseskeyfd = -1;
     int fpr_maybe_cmd = 0; /* --fingerprint maybe a command.  */
     int any_explicit_recipient = 0;
+    int default_akl = 1;
     int require_secmem = 0;
     int got_secmem = 0;
     struct assuan_malloc_hooks malloc_hooks;
@@ -2308,6 +2341,9 @@ main (int argc, char **argv)
 
     dotlock_create (NULL, 0); /* Register lock file cleanup. */
 
+    /* Tell the compliance module who we are.  */
+    gnupg_initialize_compliance (GNUPG_MODULE_NAME_GPG);
+
     opt.autostart = 1;
     opt.session_env = session_env_new ();
     if (!opt.session_env)
@@ -2330,9 +2366,10 @@ main (int argc, char **argv)
     opt.max_cert_depth = 5;
     opt.escape_from = 1;
     opt.flags.require_cross_cert = 1;
-    opt.import_options = 0;
+    opt.import_options = IMPORT_REPAIR_KEYS;
     opt.export_options = EXPORT_ATTRIBUTES;
-    opt.keyserver_options.import_options = IMPORT_REPAIR_PKS_SUBKEY_BUG;
+    opt.keyserver_options.import_options = (IMPORT_REPAIR_KEYS
+                                           | IMPORT_REPAIR_PKS_SUBKEY_BUG);
     opt.keyserver_options.export_options = EXPORT_ATTRIBUTES;
     opt.keyserver_options.options = KEYSERVER_HONOR_PKA_RECORD;
     opt.verify_options = (LIST_SHOW_UID_VALIDITY
@@ -2357,7 +2394,6 @@ main (int argc, char **argv)
     opt.passphrase_repeat = 1;
     opt.emit_version = 0;
     opt.weak_digests = NULL;
-    additional_weak_digest("MD5");
 
     /* Check whether we have a config file on the command line.  */
     orig_argc = argc;
@@ -2433,6 +2469,10 @@ main (int argc, char **argv)
     assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
     setup_libassuan_logging (&opt.debug, NULL);
 
+    /* Set default options which require that malloc stuff is ready.  */
+    additional_weak_digest ("MD5");
+    parse_auto_key_locate ("local,wkd");
+
     /* Try for a version specific config file first */
     default_configname = get_default_configname ();
     if (default_config)
@@ -2546,6 +2586,8 @@ main (int argc, char **argv)
          case aQuickAddUid:
          case aQuickAddKey:
          case aQuickRevUid:
+         case aQuickSetExpire:
+         case aQuickSetPrimaryUid:
          case aExportOwnerTrust:
          case aImportOwnerTrust:
           case aRebuildKeydbCaches:
@@ -2697,6 +2739,10 @@ main (int argc, char **argv)
             opt.with_keygrip = 1;
             break;
 
+         case oWithKeyScreening:
+            opt.with_key_screening = 1;
+            break;
+
          case oWithSecret:
             opt.with_secret = 1;
             break;
@@ -2705,6 +2751,10 @@ main (int argc, char **argv)
             opt.with_wkd_hash = 1;
             break;
 
+         case oWithKeyOrigin:
+            opt.with_key_origin = 1;
+            break;
+
          case oSecretKeyring:
             /* Ignore this old option.  */
             break;
@@ -2818,7 +2868,15 @@ main (int argc, char **argv)
            break;
 
           case oCompliance:
-            set_compliance_option (parse_compliance_option (pargs.r.ret_str));
+           {
+             int compliance = gnupg_parse_compliance_option
+                (pargs.r.ret_str,
+                 compliance_options, DIM (compliance_options),
+                 opt.quiet);
+             if (compliance < 0)
+               g10_exit (1);
+             set_compliance_option (compliance);
+           }
             break;
           case oOpenPGP:
           case oRFC2440:
@@ -3046,6 +3104,8 @@ main (int argc, char **argv)
 
          case oCommandFD:
             opt.command_fd = translate_sys2libc_fd_int (pargs.r.ret_int, 0);
+           if (! gnupg_fd_valid (opt.command_fd))
+             log_fatal ("command-fd is invalid: %s\n", strerror (errno));
             break;
          case oCommandFile:
             opt.command_fd = open_info_file (pargs.r.ret_str, 0, 1);
@@ -3282,13 +3342,14 @@ main (int argc, char **argv)
          case oIgnoreCrcError: opt.ignore_crc_error = 1; break;
          case oIgnoreMDCError: opt.ignore_mdc_error = 1; break;
          case oNoRandomSeedFile: use_random_seed = 0; break;
+
          case oAutoKeyRetrieve:
+            opt.keyserver_options.options |= KEYSERVER_AUTO_KEY_RETRIEVE;
+            break;
          case oNoAutoKeyRetrieve:
-               if(pargs.r_opt==oAutoKeyRetrieve)
-                 opt.keyserver_options.options|=KEYSERVER_AUTO_KEY_RETRIEVE;
-               else
-                 opt.keyserver_options.options&=~KEYSERVER_AUTO_KEY_RETRIEVE;
-               break;
+            opt.keyserver_options.options &= ~KEYSERVER_AUTO_KEY_RETRIEVE;
+            break;
+
          case oShowSessionKey: opt.show_session_key = 1; break;
          case oOverrideSessionKey:
                opt.override_session_key = pargs.r.ret_str;
@@ -3304,9 +3365,11 @@ main (int argc, char **argv)
           case oAllowSecretKeyImport: /* obsolete */ break;
          case oTryAllSecrets: opt.try_all_secrets = 1; break;
           case oTrustedKey: register_trusted_key( pargs.r.ret_str ); break;
+
           case oEnableSpecialFilenames:
-            iobuf_enable_special_filenames (1);
+            enable_special_filenames ();
             break;
+
           case oNoExpensiveTrustChecks: opt.no_expensive_trust_checks=1; break;
           case oAutoCheckTrustDB: opt.no_auto_check_trustdb=0; break;
           case oNoAutoCheckTrustDB: opt.no_auto_check_trustdb=1; break;
@@ -3337,6 +3400,7 @@ main (int argc, char **argv)
            break;
           case oAgentProgram: opt.agent_program = pargs.r.ret_str;  break;
           case oDirmngrProgram: opt.dirmngr_program = pargs.r.ret_str; break;
+         case oDisableDirmngr: opt.disable_dirmngr = 1;  break;
           case oWeakDigest:
            additional_weak_digest(pargs.r.ret_str);
            break;
@@ -3411,6 +3475,13 @@ main (int argc, char **argv)
          case oNoRequireCrossCert: opt.flags.require_cross_cert=0; break;
 
          case oAutoKeyLocate:
+            if (default_akl)
+              {
+                /* This is the first time --aito-key-locate is seen.
+                 * We need to reset the default akl.  */
+                default_akl = 0;
+                release_akl();
+              }
            if(!parse_auto_key_locate(pargs.r.ret_str))
              {
                if(configname)
@@ -3424,6 +3495,12 @@ main (int argc, char **argv)
            release_akl();
            break;
 
+         case oKeyOrigin:
+           if(!parse_key_origin (pargs.r.ret_str))
+              log_error (_("invalid argument for option \"%.50s\"\n"),
+                         "--key-origin");
+           break;
+
          case oEnableLargeRSA:
 #if SECMEM_BUFFER_SIZE >= 65536
             opt.flags.large_rsa=1;
@@ -3458,15 +3535,29 @@ main (int argc, char **argv)
 
           case oFakedSystemTime:
             {
-              time_t faked_time = isotime2epoch (pargs.r.ret_str);
+              size_t len = strlen (pargs.r.ret_str);
+              int freeze = 0;
+              time_t faked_time;
+
+              if (len > 0 && pargs.r.ret_str[len-1] == '!')
+                {
+                  freeze = 1;
+                  pargs.r.ret_str[len-1] = '\0';
+                }
+
+              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);
+              gnupg_set_time (faked_time, freeze);
             }
             break;
 
           case oNoAutostart: opt.autostart = 0; break;
 
+         case oDefaultNewKeyAlgo:
+            opt.def_new_key_algo = pargs.r.ret_str;
+            break;
+
          case oNoop: break;
 
          default:
@@ -3727,7 +3818,7 @@ main (int argc, char **argv)
            cmdname="--sign --encrypt";
            break;
          case aClearsign:
-           cmdname="--clearsign";
+           cmdname="--clear-sign";
            break;
          case aDetachedSign:
            cmdname="--detach-sign";
@@ -3794,19 +3885,22 @@ main (int argc, char **argv)
            switch(badtype)
              {
              case PREFTYPE_SYM:
-               log_info(_("you may not use cipher algorithm '%s'"
-                          " while in %s mode\n"),
-                        badalg,compliance_option_string());
+               log_info (_("cipher algorithm '%s'"
+                            " may not be used in %s mode\n"),
+                        badalg,
+                          gnupg_compliance_option_string (opt.compliance));
                break;
              case PREFTYPE_HASH:
-               log_info(_("you may not use digest algorithm '%s'"
-                          " while in %s mode\n"),
-                        badalg,compliance_option_string());
+               log_info (_("digest algorithm '%s'"
+                            " may not be used in %s mode\n"),
+                          badalg,
+                          gnupg_compliance_option_string (opt.compliance));
                break;
              case PREFTYPE_ZIP:
-               log_info(_("you may not use compression algorithm '%s'"
-                          " while in %s mode\n"),
-                        badalg,compliance_option_string());
+               log_info (_("compression algorithm '%s'"
+                            " may not be used in %s mode\n"),
+                          badalg,
+                          gnupg_compliance_option_string (opt.compliance));
                break;
              default:
                BUG();
@@ -3816,6 +3910,41 @@ 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 (opt.def_cipher_algo
+       && ! gnupg_cipher_is_allowed (opt.compliance,
+                                     cmd == aEncr
+                                     || cmd == aSignEncr
+                                     || cmd == aEncrSym
+                                     || cmd == aSym
+                                     || cmd == aSignSym
+                                     || cmd == aSignEncrSym,
+                                     opt.def_cipher_algo,
+                                     GCRY_CIPHER_MODE_NONE))
+      log_error (_("cipher algorithm '%s' may not be used in %s mode\n"),
+                openpgp_cipher_algo_name (opt.def_cipher_algo),
+                gnupg_compliance_option_string (opt.compliance));
+
+    if (opt.def_digest_algo
+       && ! gnupg_digest_is_allowed (opt.compliance,
+                                     cmd == aSign
+                                     || cmd == aSignEncr
+                                     || cmd == aSignEncrSym
+                                     || cmd == aSignSym
+                                     || cmd == aClearsign,
+                                     opt.def_digest_algo))
+      log_error (_("digest algorithm '%s' may not be used in %s mode\n"),
+                gcry_md_algo_name (opt.def_digest_algo),
+                gnupg_compliance_option_string (opt.compliance));
+
+    /* Fail hard.  */
+    if (log_get_errorcount (0))
+       g10_exit (2);
+
     /* Set the random seed file. */
     if( use_random_seed ) {
       char *p = make_filename (gnupg_homedir (), "random_seed", NULL );
@@ -3896,6 +4025,11 @@ main (int argc, char **argv)
       case aListTrustDB:
         rc = setup_trustdb (argc? 1:0, trustdb_name);
         break;
+      case aKeygen:
+      case aFullKeygen:
+      case aQuickKeygen:
+        rc = setup_trustdb (1, trustdb_name);
+        break;
       default:
         /* If we are using TM_ALWAYS, we do not need to create the
            trustdb.  */
@@ -3944,6 +4078,7 @@ main (int argc, char **argv)
       case aQuickAddUid:
       case aQuickAddKey:
       case aQuickRevUid:
+      case aQuickSetPrimaryUid:
       case aFullKeygen:
       case aKeygen:
       case aImport:
@@ -3972,7 +4107,7 @@ main (int argc, char **argv)
 
       case aStore: /* only store the file */
        if( argc > 1 )
-           wrong_args(_("--store [filename]"));
+           wrong_args("--store [filename]");
        if( (rc = encrypt_store(fname)) )
           {
             write_status_failure ("store", rc);
@@ -3982,7 +4117,7 @@ main (int argc, char **argv)
        break;
       case aSym: /* encrypt the given file only with the symmetric cipher */
        if( argc > 1 )
-           wrong_args(_("--symmetric [filename]"));
+           wrong_args("--symmetric [filename]");
        if( (rc = encrypt_symmetric(fname)) )
           {
             write_status_failure ("symencrypt", rc);
@@ -3997,7 +4132,7 @@ main (int argc, char **argv)
        else
          {
            if( argc > 1 )
-             wrong_args(_("--encrypt [filename]"));
+             wrong_args("--encrypt [filename]");
            if( (rc = encrypt_crypt (ctrl, -1, fname, remusr, 0, NULL, -1)) )
               {
                 write_status_failure ("encrypt", rc);
@@ -4013,13 +4148,14 @@ main (int argc, char **argv)
           might work with 7, but alas, I don't have a copy to test
           with right now. */
        if( argc > 1 )
-         wrong_args(_("--symmetric --encrypt [filename]"));
+         wrong_args("--symmetric --encrypt [filename]");
        else if(opt.s2k_mode==0)
          log_error(_("you cannot use --symmetric --encrypt"
                      " with --s2k-mode 0\n"));
        else if(PGP6 || PGP7)
          log_error(_("you cannot use --symmetric --encrypt"
-                     " while in %s mode\n"),compliance_option_string());
+                     " in %s mode\n"),
+                   gnupg_compliance_option_string (opt.compliance));
        else
          {
            if( (rc = encrypt_crypt (ctrl, -1, fname, remusr, 1, NULL, -1)) )
@@ -4039,7 +4175,7 @@ main (int argc, char **argv)
        }
        else {
            if( argc > 1 )
-               wrong_args(_("--sign [filename]"));
+               wrong_args("--sign [filename]");
            if( argc ) {
                sl = xmalloc_clear( sizeof *sl + strlen(fname));
                strcpy(sl->d, fname);
@@ -4055,7 +4191,7 @@ main (int argc, char **argv)
 
       case aSignEncr: /* sign and encrypt the given file */
        if( argc > 1 )
-           wrong_args(_("--sign --encrypt [filename]"));
+           wrong_args("--sign --encrypt [filename]");
        if( argc ) {
            sl = xmalloc_clear( sizeof *sl + strlen(fname));
            strcpy(sl->d, fname);
@@ -4073,13 +4209,14 @@ main (int argc, char **argv)
 
       case aSignEncrSym: /* sign and encrypt the given file */
        if( argc > 1 )
-           wrong_args(_("--symmetric --sign --encrypt [filename]"));
+           wrong_args("--symmetric --sign --encrypt [filename]");
        else if(opt.s2k_mode==0)
          log_error(_("you cannot use --symmetric --sign --encrypt"
                      " with --s2k-mode 0\n"));
        else if(PGP6 || PGP7)
          log_error(_("you cannot use --symmetric --sign --encrypt"
-                     " while in %s mode\n"),compliance_option_string());
+                     " in %s mode\n"),
+                   gnupg_compliance_option_string (opt.compliance));
        else
          {
            if( argc )
@@ -4102,7 +4239,7 @@ main (int argc, char **argv)
 
       case aSignSym: /* sign and conventionally encrypt the given file */
        if (argc > 1)
-           wrong_args(_("--sign --symmetric [filename]"));
+           wrong_args("--sign --symmetric [filename]");
        rc = sign_symencrypt_file (ctrl, fname, locusr);
         if (rc)
           {
@@ -4114,11 +4251,11 @@ main (int argc, char **argv)
 
       case aClearsign: /* make a clearsig */
        if( argc > 1 )
-           wrong_args(_("--clearsign [filename]"));
+           wrong_args("--clear-sign [filename]");
        if( (rc = clearsign_file (ctrl, fname, locusr, NULL)) )
           {
             write_status_failure ("sign", rc);
-           log_error("%s: clearsign failed: %s\n",
+           log_error("%s: clear-sign failed: %s\n",
                       print_fname_stdin(fname), gpg_strerror (rc) );
           }
        break;
@@ -4144,7 +4281,7 @@ main (int argc, char **argv)
        else
          {
            if( argc > 1 )
-             wrong_args(_("--decrypt [filename]"));
+             wrong_args("--decrypt [filename]");
            if( (rc = decrypt_message (ctrl, fname) ))
               {
                 write_status_failure ("decrypt", rc);
@@ -4171,11 +4308,11 @@ main (int argc, char **argv)
 
       case aSignKey:
        if( argc != 1 )
-         wrong_args(_("--sign-key user-id"));
+         wrong_args("--sign-key user-id");
        /* fall through */
       case aLSignKey:
        if( argc != 1 )
-         wrong_args(_("--lsign-key user-id"));
+         wrong_args("--lsign-key user-id");
        /* fall through */
 
        sl=NULL;
@@ -4196,7 +4333,7 @@ main (int argc, char **argv)
 
       case aEditKey: /* Edit a key signature */
        if( !argc )
-           wrong_args(_("--edit-key user-id [commands]"));
+           wrong_args("--edit-key user-id [commands]");
        username = make_username( fname );
        if( argc > 1 ) {
            sl = NULL;
@@ -4212,7 +4349,7 @@ main (int argc, char **argv)
 
       case aPasswd:
         if (argc != 1)
-          wrong_args (_("--passwd <user-id>"));
+          wrong_args("--change-passphrase <user-id>");
         else
           {
             username = make_username (fname);
@@ -4230,14 +4367,15 @@ main (int argc, char **argv)
            proper order :) */
        for( ; argc; argc-- )
          add_to_strlist2( &sl, argv[argc-1], utf8_strings );
-       delete_keys(sl,cmd==aDeleteSecretKeys,cmd==aDeleteSecretAndPublicKeys);
+       delete_keys (ctrl, sl,
+                     cmd==aDeleteSecretKeys, cmd==aDeleteSecretAndPublicKeys);
        free_strlist(sl);
        break;
 
       case aCheckKeys:
-       opt.check_sigs = 1;
+       opt.check_sigs = 1; /* fall through */
       case aListSigs:
-       opt.list_sigs = 1;
+       opt.list_sigs = 1; /* fall through */
       case aListKeys:
        sl = NULL;
        for( ; argc; argc--, argv++ )
@@ -4265,7 +4403,7 @@ main (int argc, char **argv)
           const char *x_algo, *x_usage, *x_expire;
 
           if (argc < 1 || argc > 4)
-            wrong_args("--quick-gen-key USER-ID [ALGO [USAGE [EXPIRE]]]");
+            wrong_args("--quick-generate-key USER-ID [ALGO [USAGE [EXPIRE]]]");
           username = make_username (fname);
           argv++, argc--;
           x_algo = "";
@@ -4291,20 +4429,20 @@ main (int argc, char **argv)
       case aKeygen: /* generate a key */
        if( opt.batch ) {
            if( argc > 1 )
-               wrong_args("--gen-key [parameterfile]");
+               wrong_args("--generate-key [parameterfile]");
            generate_keypair (ctrl, 0, argc? *argv : NULL, NULL, 0);
        }
        else {
             if (opt.command_fd != -1 && argc)
               {
                 if( argc > 1 )
-                  wrong_args("--gen-key [parameterfile]");
+                  wrong_args("--generate-key [parameterfile]");
 
                 opt.batch = 1;
                 generate_keypair (ctrl, 0, argc? *argv : NULL, NULL, 0);
               }
             else if (argc)
-              wrong_args ("--gen-key");
+              wrong_args ("--generate-key");
             else
               generate_keypair (ctrl, 0, NULL, NULL, 0);
        }
@@ -4314,13 +4452,13 @@ main (int argc, char **argv)
        if (opt.batch)
           {
            if (argc > 1)
-              wrong_args ("--full-gen-key [parameterfile]");
+              wrong_args ("--full-generate-key [parameterfile]");
            generate_keypair (ctrl, 1, argc? *argv : NULL, NULL, 0);
           }
        else
           {
            if (argc)
-              wrong_args("--full-gen-key");
+              wrong_args("--full-generate-key");
            generate_keypair (ctrl, 1, NULL, NULL, 0);
        }
        break;
@@ -4330,7 +4468,7 @@ main (int argc, char **argv)
           const char *uid, *newuid;
 
           if (argc != 2)
-            wrong_args ("--quick-adduid USER-ID NEW-USER-ID");
+            wrong_args ("--quick-add-uid USER-ID NEW-USER-ID");
           uid = *argv++; argc--;
           newuid = *argv++; argc--;
           keyedit_quick_adduid (ctrl, uid, newuid);
@@ -4342,7 +4480,7 @@ main (int argc, char **argv)
           const char *x_fpr, *x_algo, *x_usage, *x_expire;
 
           if (argc < 1 || argc > 4)
-            wrong_args ("--quick-addkey FINGERPRINT [ALGO [USAGE [EXPIRE]]]");
+            wrong_args ("--quick-add-key FINGERPRINT [ALGO [USAGE [EXPIRE]]]");
           x_fpr = *argv++; argc--;
           x_algo = "";
           x_usage = "";
@@ -4368,17 +4506,42 @@ main (int argc, char **argv)
           const char *uid, *uidtorev;
 
           if (argc != 2)
-            wrong_args ("--quick-revuid USER-ID USER-ID-TO-REVOKE");
+            wrong_args ("--quick-revoke-uid USER-ID USER-ID-TO-REVOKE");
           uid = *argv++; argc--;
           uidtorev = *argv++; argc--;
           keyedit_quick_revuid (ctrl, uid, uidtorev);
         }
        break;
 
+      case aQuickSetExpire:
+        {
+          const char *x_fpr, *x_expire;
+
+          if (argc < 2)
+            wrong_args ("--quick-set-exipre FINGERPRINT EXPIRE [SUBKEY-FPRS]");
+          x_fpr = *argv++; argc--;
+          x_expire = *argv++; argc--;
+          keyedit_quick_set_expire (ctrl, x_fpr, x_expire, argv);
+        }
+       break;
+
+      case aQuickSetPrimaryUid:
+        {
+          const char *uid, *primaryuid;
+
+          if (argc != 2)
+            wrong_args ("--quick-set-primary-uid USER-ID PRIMARY-USER-ID");
+          uid = *argv++; argc--;
+          primaryuid = *argv++; argc--;
+          keyedit_quick_set_primary (ctrl, uid, primaryuid);
+        }
+       break;
+
       case aFastImport:
-        opt.import_options |= IMPORT_FAST;
+        opt.import_options |= IMPORT_FAST; /* fall through */
       case aImport:
-       import_keys (ctrl, argc? argv:NULL, argc, NULL, opt.import_options);
+       import_keys (ctrl, argc? argv:NULL, argc, NULL,
+                     opt.import_options, opt.key_origin, opt.key_origin_url);
        break;
 
        /* TODO: There are a number of command that use this same
@@ -4466,7 +4629,7 @@ main (int argc, char **argv)
        sl = NULL;
        for( ; argc; argc--, argv++ )
            append_to_strlist2( &sl, *argv, utf8_strings );
-       rc = keyserver_fetch (ctrl, sl);
+       rc = keyserver_fetch (ctrl, sl, opt.key_origin);
        if(rc)
           {
             write_status_failure ("fetch-keys", rc);
@@ -4481,7 +4644,7 @@ main (int argc, char **argv)
            add_to_strlist2( &sl, *argv, utf8_strings );
         {
           export_stats_t stats = export_new_stats ();
-          export_seckeys (ctrl, sl, stats);
+          export_seckeys (ctrl, sl, opt.export_options, stats);
           export_print_stats (stats);
           export_release_stats (stats);
         }
@@ -4494,7 +4657,7 @@ main (int argc, char **argv)
            add_to_strlist2( &sl, *argv, utf8_strings );
         {
           export_stats_t stats = export_new_stats ();
-          export_secsubkeys (ctrl, sl, stats);
+          export_secsubkeys (ctrl, sl, opt.export_options, stats);
           export_print_stats (stats);
           export_release_stats (stats);
         }
@@ -4503,15 +4666,15 @@ main (int argc, char **argv)
 
       case aGenRevoke:
        if( argc != 1 )
-           wrong_args("--gen-revoke user-id");
+           wrong_args("--generate-revocation user-id");
        username =  make_username(*argv);
-       gen_revoke( username );
+       gen_revoke (ctrl, username );
        xfree( username );
        break;
 
       case aDesigRevoke:
        if (argc != 1)
-           wrong_args ("--desig-revoke user-id");
+           wrong_args ("--generate-designated-revocation user-id");
        username = make_username (*argv);
        gen_desig_revoke (ctrl, username, locusr);
        xfree (username);
@@ -4652,10 +4815,10 @@ main (int argc, char **argv)
 #ifndef NO_TRUST_MODELS
       case aListTrustDB:
        if( !argc )
-          list_trustdb (es_stdout, NULL);
+          list_trustdb (ctrl, es_stdout, NULL);
        else {
            for( ; argc; argc--, argv++ )
-              list_trustdb (es_stdout, *argv );
+              list_trustdb (ctrl, es_stdout, *argv );
        }
        break;
 
@@ -4687,27 +4850,30 @@ main (int argc, char **argv)
       case aExportOwnerTrust:
        if( argc )
            wrong_args("--export-ownertrust");
-       export_ownertrust();
+       export_ownertrust (ctrl);
        break;
 
       case aImportOwnerTrust:
        if( argc > 1 )
            wrong_args("--import-ownertrust [file]");
-       import_ownertrust( argc? *argv:NULL );
+       import_ownertrust (ctrl, argc? *argv:NULL );
        break;
 #endif /*!NO_TRUST_MODELS*/
 
       case aRebuildKeydbCaches:
         if (argc)
             wrong_args ("--rebuild-keydb-caches");
-        keydb_rebuild_caches (1);
+        keydb_rebuild_caches (ctrl, 1);
         break;
 
 #ifdef ENABLE_CARD_SUPPORT
       case aCardStatus:
-        if (argc)
-            wrong_args ("--card-status");
-        card_status (es_stdout, NULL, 0);
+        if (argc == 0)
+            card_status (ctrl, es_stdout, NULL);
+        else if (argc == 1)
+            card_status (ctrl, es_stdout, *argv);
+        else
+            wrong_args ("--card-status [serialno]");
         break;
 
       case aCardEdit:
@@ -4817,9 +4983,11 @@ main (int argc, char **argv)
                  g10_exit (1);
                }
 
-             merge_keys_and_selfsig (kb);
+             merge_keys_and_selfsig (ctrl, kb);
              if (tofu_set_policy (ctrl, kb, policy))
                g10_exit (1);
+
+              release_kbnode (kb);
            }
 
           tofu_end_batch_update (ctrl);
@@ -4829,10 +4997,14 @@ main (int argc, char **argv)
 #endif /*USE_TOFU*/
        break;
 
-      case aListPackets:
       default:
+        if (!opt.quiet)
+          log_info (_("WARNING: no command supplied."
+                      "  Trying to guess what you mean ...\n"));
+        /*FALLTHRU*/
+      case aListPackets:
        if( argc > 1 )
-           wrong_args(_("[filename]"));
+           wrong_args("[filename]");
        /* Issue some output for the unix newbie */
        if (!fname && !opt.outfile
             && gnupg_isatty (fileno (stdin))
@@ -4902,6 +5074,7 @@ g10_exit( int rc )
   if ( (opt.debug & DBG_MEMSTAT_VALUE) )
     {
       keydb_dump_stats ();
+      sig_check_dump_stats ();
       gcry_control (GCRYCTL_DUMP_MEMORY_STATS);
       gcry_control (GCRYCTL_DUMP_RANDOM_STATS);
     }
@@ -5230,6 +5403,9 @@ read_sessionkey_from_fd (int fd)
   int i, len;
   char *line;
 
+  if (! gnupg_fd_valid (fd))
+    log_fatal ("override-session-key-fd is invalid: %s\n", strerror (errno));
+
   for (line = NULL, i = len = 100; ; i++ )
     {
       if (i >= len-1 )