gpg: Add experimental AKL method "wkd" and option --with-wkd-hash.
[gnupg.git] / g10 / gpg.c
index 7338ac9..2f687fc 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-2014 Werner Koch
- * Copyright (C) 2015 g10 Code GmbH
+ * Copyright (C) 1997-2016 Werner Koch
+ * Copyright (C) 2015-2016 g10 Code GmbH
  *
  * This file is part of GnuPG.
  *
@@ -141,6 +141,7 @@ enum cmd_and_opt_values
     aExport,
     aExportSecret,
     aExportSecretSub,
+    aExportSshKey,
     aCheckKeys,
     aGenRevoke,
     aDesigRevoke,
@@ -184,6 +185,7 @@ enum cmd_and_opt_values
     oWithICAOSpelling,
     oWithKeygrip,
     oWithSecret,
+    oWithWKDHash,
     oAnswerYes,
     oAnswerNo,
     oKeyring,
@@ -391,6 +393,8 @@ enum cmd_and_opt_values
     oTOFUDefaultPolicy,
     oTOFUDBFormat,
     oWeakDigest,
+    oUnwrap,
+    oOnlySignTextIDs,
 
     oNoop
   };
@@ -451,6 +455,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_c (aFetchKeys, "fetch-keys" , "@" ),
   ARGPARSE_c (aExportSecret, "export-secret-keys" , "@" ),
   ARGPARSE_c (aExportSecretSub, "export-secret-subkeys" , "@" ),
+  ARGPARSE_c (aExportSshKey, "export-ssh-key", "@" ),
   ARGPARSE_c (aImport, "import", N_("import/merge keys")),
   ARGPARSE_c (aFastImport, "fast-import", "@"),
 #ifdef ENABLE_CARD_SUPPORT
@@ -482,7 +487,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_c (aGenRandom,"gen-random", "@" ),
   ARGPARSE_c (aServer,   "server",  N_("run in server mode")),
   ARGPARSE_c (aTOFUPolicy, "tofu-policy",
-             N_("|VALUE|set the TOFU policy for a key (good, unknown, bad, ask, auto)")),
+             N_("|VALUE|set the TOFU policy for a key")),
 
   ARGPARSE_group (301, N_("@\nOptions:\n ")),
 
@@ -677,7 +682,9 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oSkipHiddenRecipients, "skip-hidden-recipients", "@"),
   ARGPARSE_s_n (oNoSkipHiddenRecipients, "no-skip-hidden-recipients", "@"),
   ARGPARSE_s_i (oDefCertLevel, "default-cert-check-level", "@"), /* old */
+#ifndef NO_TRUST_MODELS
   ARGPARSE_s_n (oAlwaysTrust, "always-trust", "@"),
+#endif
   ARGPARSE_s_s (oTrustModel, "trust-model", "@"),
   ARGPARSE_s_s (oTOFUDefaultPolicy, "tofu-default-policy", "@"),
   ARGPARSE_s_s (oTOFUDBFormat, "tofu-db-format", "@"),
@@ -715,6 +722,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_n (oWithICAOSpelling, "with-icao-spelling", "@"),
   ARGPARSE_s_n (oWithKeygrip,     "with-keygrip", "@"),
   ARGPARSE_s_n (oWithSecret,      "with-secret", "@"),
+  ARGPARSE_s_n (oWithWKDHash,     "with-wkd-hash", "@"),
   ARGPARSE_s_s (oDisableCipherAlgo,  "disable-cipher-algo", "@"),
   ARGPARSE_s_s (oDisablePubkeyAlgo,  "disable-pubkey-algo", "@"),
   ARGPARSE_s_n (oAllowNonSelfsignedUID,      "allow-non-selfsigned-uid", "@"),
@@ -753,6 +761,8 @@ static ARGPARSE_OPTS opts[] = {
                                          "personal-compress-preferences", "@"),
   ARGPARSE_s_s (oFakedSystemTime, "faked-system-time", "@"),
   ARGPARSE_s_s (oWeakDigest, "weak-digest","@"),
+  ARGPARSE_s_n (oUnwrap, "unwrap", "@"),
+  ARGPARSE_s_n (oOnlySignTextIDs, "only-sign-text-ids", "@"),
 
   /* Aliases.  I constantly mistype these, and assume other people do
      as well. */
@@ -1039,7 +1049,7 @@ build_list (const char *text, char letter,
   if (maybe_setuid)
     gcry_control (GCRYCTL_INIT_SECMEM, 0, 0);  /* Drop setuid. */
 
-  indent = utf8_charcount (text);
+  indent = utf8_charcount (text, -1);
   len = 0;
   init_membuf (&mb, 512);
 
@@ -1964,26 +1974,37 @@ parse_trust_model(const char *model)
 }
 #endif /*NO_TRUST_MODELS*/
 
+
 static int
-parse_tofu_policy (const char *policy)
+parse_tofu_policy (const char *policystr)
 {
 #ifdef USE_TOFU
-  if (ascii_strcasecmp (policy, "auto") == 0)
-    return TOFU_POLICY_AUTO;
-  else if (ascii_strcasecmp (policy, "good") == 0)
-    return TOFU_POLICY_GOOD;
-  else if (ascii_strcasecmp (policy, "unknown") == 0)
-    return TOFU_POLICY_UNKNOWN;
-  else if (ascii_strcasecmp (policy, "bad") == 0)
-    return TOFU_POLICY_BAD;
-  else if (ascii_strcasecmp (policy, "ask") == 0)
-    return TOFU_POLICY_ASK;
-  else
-#endif /*USE_TOFU*/
+  struct { const char *keyword; int policy; } list[] = {
+    { "auto",    TOFU_POLICY_AUTO },
+    { "good",    TOFU_POLICY_GOOD },
+    { "unknown", TOFU_POLICY_UNKNOWN },
+    { "bad",     TOFU_POLICY_BAD },
+    { "ask",     TOFU_POLICY_ASK }
+  };
+  int i;
+
+  if (!ascii_strcasecmp (policystr, "help"))
     {
-      log_error (_("unknown TOFU policy '%s'\n"), policy);
+      log_info (_("available TOFU policies:\n"));
+      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 (policystr, list[i].keyword))
+      return list[i].policy;
+#endif /*USE_TOFU*/
+
+  log_error (_("unknown TOFU policy '%s'\n"), policystr);
+  if (!opt.quiet)
+    log_info (_("(use \"help\" to list choices)\n"));
+  g10_exit (1);
 }
 
 static int
@@ -1996,15 +2017,22 @@ parse_tofu_db_format (const char *db_format)
     return TOFU_DB_SPLIT;
   else if (ascii_strcasecmp (db_format, "flat") == 0)
     return TOFU_DB_FLAT;
+  else if (ascii_strcasecmp (db_format, "help") == 0)
+    {
+      log_info ("available TOFU DB fomats: auto, split, flat\n");
+      g10_exit (1);
+    }
   else
 #endif /*USE_TOFU*/
     {
       log_error (_("unknown TOFU DB format '%s'\n"), db_format);
+      if (!opt.quiet)
+        log_info (_("(use \"help\" to list choices)\n"));
       g10_exit (1);
     }
 }
 
-/* This fucntion called to initialized a new control object.  It is
+/* This function called to initialized a new control object.  It is
    assumed that this object has been zeroed out before calling this
    function. */
 static void
@@ -2079,7 +2107,6 @@ get_default_configname (void)
   return configname;
 }
 
-
 int
 main (int argc, char **argv)
 {
@@ -2091,7 +2118,9 @@ main (int argc, char **argv)
     const char *fname;
     char *username;
     int may_coredump;
-    strlist_t sl, remusr= NULL, locusr=NULL;
+    strlist_t sl;
+    strlist_t remusr = NULL;
+    strlist_t locusr = NULL;
     strlist_t nrings = NULL;
     armor_filter_context_t *afx = NULL;
     int detached_sig = 0;
@@ -2201,7 +2230,8 @@ main (int argc, char **argv)
                           | VERIFY_SHOW_POLICY_URLS
                           | VERIFY_SHOW_STD_NOTATIONS
                           | VERIFY_SHOW_KEYSERVER_URLS);
-    opt.list_options   = LIST_SHOW_UID_VALIDITY;
+    opt.list_options   = (LIST_SHOW_UID_VALIDITY
+                          | LIST_SHOW_USAGE);
 #ifdef NO_TRUST_MODELS
     opt.trust_model = TM_ALWAYS;
 #else
@@ -2377,6 +2407,7 @@ main (int argc, char **argv)
          case aListSigs:
          case aExportSecret:
          case aExportSecretSub:
+         case aExportSshKey:
          case aSym:
          case aClearsign:
          case aGenRevoke:
@@ -2546,6 +2577,10 @@ main (int argc, char **argv)
             opt.with_secret = 1;
             break;
 
+         case oWithWKDHash:
+            opt.with_wkd_hash = 1;
+            break;
+
          case oSecretKeyring:
             /* Ignore this old option.  */
             break;
@@ -2580,7 +2615,10 @@ main (int argc, char **argv)
 
 #endif /*!NO_TRUST_MODELS*/
          case oDefaultKey:
-            add_to_strlist (&opt.def_secret_key, pargs.r.ret_str);
+            sl = add_to_strlist (&opt.def_secret_key, pargs.r.ret_str);
+            sl->flags = (pargs.r_opt << PK_LIST_SHIFT);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
             break;
          case oDefRecipient:
             if( *pargs.r.ret_str )
@@ -2772,22 +2810,32 @@ main (int argc, char **argv)
          case oNoEncryptTo: opt.no_encrypt_to = 1; break;
          case oEncryptTo: /* store the recipient in the second list */
            sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
-           sl->flags = 1;
+           sl->flags = ((pargs.r_opt << PK_LIST_SHIFT) | PK_LIST_ENCRYPT_TO);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
            break;
          case oHiddenEncryptTo: /* store the recipient in the second list */
            sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
-           sl->flags = 1|2;
+           sl->flags = ((pargs.r_opt << PK_LIST_SHIFT)
+                         | PK_LIST_ENCRYPT_TO|PK_LIST_HIDDEN);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
            break;
           case oEncryptToDefaultKey:
-            opt.encrypt_to_default_key = 1;
+            opt.encrypt_to_default_key = configfp ? 2 : 1;
             break;
          case oRecipient: /* store the recipient */
-           add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
+           sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
+           sl->flags = (pargs.r_opt << PK_LIST_SHIFT);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
             any_explicit_recipient = 1;
            break;
          case oHiddenRecipient: /* store the recipient with a flag */
            sl = add_to_strlist2( &remusr, pargs.r.ret_str, utf8_strings );
-           sl->flags = 2;
+           sl->flags = ((pargs.r_opt << PK_LIST_SHIFT) | PK_LIST_HIDDEN);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
             any_explicit_recipient = 1;
            break;
 
@@ -2830,7 +2878,10 @@ main (int argc, char **argv)
          case oAskCertLevel: opt.ask_cert_level = 1; break;
          case oNoAskCertLevel: opt.ask_cert_level = 0; break;
          case oLocalUser: /* store the local users */
-           add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings );
+           sl = add_to_strlist2( &locusr, pargs.r.ret_str, utf8_strings );
+            sl->flags = (pargs.r_opt << PK_LIST_SHIFT);
+            if (configfp)
+              sl->flags |= PK_LIST_CONFIG;
            break;
          case oCompress:
            /* this is the -z command line option */
@@ -3147,6 +3198,12 @@ main (int argc, char **argv)
           case oWeakDigest:
            additional_weak_digest(pargs.r.ret_str);
            break;
+          case oUnwrap:
+            opt.unwrap_encryption = 1;
+            break;
+          case oOnlySignTextIDs:
+            opt.only_sign_text_ids = 1;
+            break;
 
           case oDisplay:
             set_opt_session_env ("DISPLAY", pargs.r.ret_str);
@@ -3401,7 +3458,7 @@ main (int argc, char **argv)
     /* Do these after the switch(), so they can override settings. */
     if(PGP6)
       {
-        /* That does not anymore work becuase we have no more support
+        /* That does not anymore work because we have no more support
            for v3 signatures.  */
        opt.disable_mdc=1;
        opt.escape_from=1;
@@ -3503,6 +3560,9 @@ main (int argc, char **argv)
          case aSign:
            cmdname="--sign";
            break;
+         case aSignEncr:
+           cmdname="--sign --encrypt";
+           break;
          case aClearsign:
            cmdname="--clearsign";
            break;
@@ -3732,20 +3792,6 @@ main (int argc, char **argv)
         break;
       }
 
-    if (opt.encrypt_to_default_key)
-      {
-        const char *default_key = parse_def_secret_key (ctrl);
-        if (default_key)
-          {
-            sl = add_to_strlist2 (&remusr, default_key, utf8_strings);
-            sl->flags = 1;
-          }
-        else if (opt.def_secret_key)
-          log_info (_("--encrypt-to-default-key specified, but no valid default keys specified.\n"));
-        else
-          log_info (_("--encrypt-to-default-key specified, but --default-key not specified.\n"));
-      }
-
     /* The command dispatcher.  */
     switch( cmd )
       {
@@ -3907,7 +3953,6 @@ main (int argc, char **argv)
        break;
 
       case aVerify:
-        rc = 0;
        if (multifile)
          {
            if ((rc = verify_files (ctrl, argc, argv)))
@@ -4123,7 +4168,12 @@ main (int argc, char **argv)
        else if( cmd == aRecvKeys )
             rc = keyserver_import (ctrl, sl );
        else
-            rc = export_pubkeys (ctrl, sl, opt.export_options);
+          {
+            export_stats_t stats = export_new_stats ();
+            rc = export_pubkeys (ctrl, sl, opt.export_options, stats);
+            export_print_stats (stats);
+            export_release_stats (stats);
+          }
        if(rc)
          {
            if(cmd==aSendKeys)
@@ -4146,6 +4196,17 @@ main (int argc, char **argv)
        free_strlist(sl);
        break;
 
+      case aExportSshKey:
+        if (argc != 1)
+          wrong_args ("--export-ssh-key <user-id>");
+        rc = export_ssh_key (ctrl, argv[0]);
+        if (rc)
+          {
+            write_status_failure ("export-ssh-key", rc);
+            log_error (_("export as ssh key failed: %s\n"), gpg_strerror (rc));
+          }
+       break;
+
      case aSearchKeys:
        sl = NULL;
        for (; argc; argc--, argv++)
@@ -4189,7 +4250,12 @@ main (int argc, char **argv)
        sl = NULL;
        for( ; argc; argc--, argv++ )
            add_to_strlist2( &sl, *argv, utf8_strings );
-       export_seckeys (ctrl, sl);
+        {
+          export_stats_t stats = export_new_stats ();
+          export_seckeys (ctrl, sl, stats);
+          export_print_stats (stats);
+          export_release_stats (stats);
+        }
        free_strlist(sl);
        break;
 
@@ -4197,7 +4263,12 @@ main (int argc, char **argv)
        sl = NULL;
        for( ; argc; argc--, argv++ )
            add_to_strlist2( &sl, *argv, utf8_strings );
-       export_secsubkeys (ctrl, sl);
+        {
+          export_stats_t stats = export_new_stats ();
+          export_secsubkeys (ctrl, sl, stats);
+          export_print_stats (stats);
+          export_release_stats (stats);
+        }
        free_strlist(sl);
        break;
 
@@ -4455,16 +4526,13 @@ main (int argc, char **argv)
          KEYDB_HANDLE hd;
 
          if (argc < 2)
-           wrong_args("--tofu-policy POLICY KEYID [KEYID...]");
+           wrong_args ("--tofu-policy POLICY KEYID [KEYID...]");
 
          policy = parse_tofu_policy (argv[0]);
 
          hd = keydb_new ();
          if (! hd)
-           {
-             log_error (_("Failed to open the keyring DB.\n"));
-             g10_exit (1);
-           }
+            g10_exit (1);
 
          for (i = 1; i < argc; i ++)
            {
@@ -4474,7 +4542,8 @@ main (int argc, char **argv)
              rc = classify_user_id (argv[i], &desc, 0);
              if (rc)
                {
-                 log_error (_("Failed to parse '%s'.\n"), argv[i]);
+                 log_error (_("error parsing key specification '%s': %s\n"),
+                             argv[i], gpg_strerror (rc));
                  g10_exit (1);
                }
 
@@ -4486,7 +4555,7 @@ main (int argc, char **argv)
                     || desc.mode == KEYDB_SEARCH_MODE_KEYGRIP))
                {
                  log_error (_("'%s' does not appear to be a valid"
-                              " key id, fingerprint or key grip.\n"),
+                              " key ID, fingerprint or keygrip\n"),
                             argv[i]);
                  g10_exit (1);
                }
@@ -4494,27 +4563,26 @@ main (int argc, char **argv)
              rc = keydb_search_reset (hd);
              if (rc)
                {
-                 log_error (_("Failed to reset keyring handle.\n"));
+                  /* This should not happen, thus no need to tranalate
+                     the string.  */
+                  log_error ("keydb_search_reset failed: %s\n",
+                             gpg_strerror (rc));
                  g10_exit (1);
                }
 
              rc = keydb_search (hd, &desc, 1, NULL);
-             if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY)
-               {
-                 log_error (_("Key '%s' is not available\n"), argv[i]);
-                 g10_exit (1);
-               }
-             else if (rc)
+             if (rc)
                {
-                 log_error (_("Failed to find key '%s'\n"), argv[i]);
+                 log_error (_("key \"%s\" not found: %s\n"), argv[i],
+                             gpg_strerror (rc));
                  g10_exit (1);
                }
 
              rc = keydb_get_keyblock (hd, &kb);
              if (rc)
                {
-                 log_error (_("Failed to read key '%s' from the keyring\n"),
-                            argv[i]);
+                 log_error (_("error reading keyblock: %s\n"),
+                             gpg_strerror (rc));
                  g10_exit (1);
                }