Imported Upstream version 2.2.10 upstream/2.2.10
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 9 Feb 2021 07:00:38 +0000 (16:00 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 9 Feb 2021 07:00:38 +0000 (16:00 +0900)
26 files changed:
NEWS
common/asshelp.c
common/mbox-util.c
common/mbox-util.h
common/sysutils.c
common/t-mbox-util.c
configure.ac
dirmngr/dirmngr.c
dirmngr/server.c
doc/gpg.texi
g10/call-dirmngr.c
g10/getkey.c
g10/gpg.c
g10/import.c
g10/keydb.h
g10/keygen.c
g10/keylist.c
g10/packet.h
g10/parse-packet.c
g10/pkclist.c
po/de.po
po/ja.po
po/ru.po
scd/apdu.c
scd/ccid-driver.c
scd/ccid-driver.h

diff --git a/NEWS b/NEWS
index 85175b0..f446e43 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,22 @@
+Noteworthy changes in version 2.2.10 (2018-08-30)
+-------------------------------------------------
+
+  gpg: Refresh expired keys originating from the WKD.  [#2917]
+
+  gpg: Use a 256 KiB limit for a WKD imported key.
+
+  gpg: New option --known-notation.  [#4060]
+
+  scd: Add support for the Trustica Cryptoucan reader.
+
+  agent: Speed up starting during on-demand launching.  [#3490]
+
+  dirmngr: Validate SRV records in WKD queries.
+
+  Release-info: https://dev.gnupg.org/T4112
+  See-also: gnupg-announce/2018q3/000428.html
+
+
 Noteworthy changes in version 2.2.9 (2018-07-12)
 ------------------------------------------------
 
@@ -37,7 +56,6 @@ Noteworthy changes in version 2.2.9 (2018-07-12)
   * gpg: New "usage" property for the drop-subkey filters.  [#4019]
 
   Release-info: https://dev.gnupg.org/T4036
-
   See-also: gnupg-announce/2018q3/000427.html
 
 
index f3a92f9..d87017e 100644 (file)
@@ -307,6 +307,56 @@ unlock_spawning (lock_spawn_t *lock, const char *name)
     }
 }
 
+static gpg_error_t
+wait_for_sock (int secs, const char *name, const char *sockname, int verbose, assuan_context_t ctx, int *did_success_msg)
+{
+  gpg_error_t err = 0;
+  int target_us = secs * 1000000;
+  int elapsed_us = 0;
+  /*
+   * 977us * 1024 = just a little more than 1s.
+   * so we will double this timeout 10 times in the first
+   * second, and then switch over to 1s checkins.
+   */
+  int next_sleep_us = 977;
+  int lastalert = secs+1;
+  int secsleft;
+
+  while (elapsed_us < target_us)
+    {
+      if (verbose)
+        {
+          secsleft = (target_us - elapsed_us + 999999)/1000000;
+          /* log_clock ("left=%d last=%d targ=%d elap=%d next=%d\n", */
+          /*            secsleft, lastalert, target_us, elapsed_us, */
+          /*            next_sleep_us); */
+          if (secsleft < lastalert)
+            {
+              log_info (_("waiting for the %s to come up ... (%ds)\n"),
+                        name, secsleft);
+              lastalert = secsleft;
+            }
+        }
+      gnupg_usleep (next_sleep_us);
+      elapsed_us += next_sleep_us;
+      err = assuan_socket_connect (ctx, sockname, 0, 0);
+      if (!err)
+        {
+          if (verbose)
+            {
+              log_info (_("connection to %s established\n"),
+                        name);
+              *did_success_msg = 1;
+            }
+          break;
+        }
+      next_sleep_us *= 2;
+      if (next_sleep_us > 1000000)
+        next_sleep_us = 1000000;
+    }
+  return err;
+}
+
 /* Try to connect to the agent via socket or start it if it is not
    running and AUTOSTART is set.  Handle the server's initial
    greeting.  Returns a new assuan context at R_CTX or an error
@@ -433,25 +483,8 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
             log_error ("failed to start agent '%s': %s\n",
                        agent_program, gpg_strerror (err));
           else
-            {
-              for (i=0; i < SECS_TO_WAIT_FOR_AGENT; i++)
-                {
-                  if (verbose)
-                    log_info (_("waiting for the agent to come up ... (%ds)\n"),
-                              SECS_TO_WAIT_FOR_AGENT - i);
-                  gnupg_sleep (1);
-                  err = assuan_socket_connect (ctx, sockname, 0, 0);
-                  if (!err)
-                    {
-                      if (verbose)
-                        {
-                          log_info (_("connection to agent established\n"));
-                          did_success_msg = 1;
-                        }
-                      break;
-                    }
-                }
-            }
+            err = wait_for_sock (SECS_TO_WAIT_FOR_AGENT, "agent",
+                                 sockname, verbose, ctx, &did_success_msg);
         }
 
       unlock_spawning (&lock, "agent");
@@ -584,29 +617,8 @@ start_new_dirmngr (assuan_context_t *r_ctx,
             log_error ("failed to start the dirmngr '%s': %s\n",
                        dirmngr_program, gpg_strerror (err));
           else
-            {
-              int i;
-
-              for (i=0; i < SECS_TO_WAIT_FOR_DIRMNGR; i++)
-                {
-                  if (verbose)
-                    log_info (_("waiting for the dirmngr "
-                                "to come up ... (%ds)\n"),
-                              SECS_TO_WAIT_FOR_DIRMNGR - i);
-                  gnupg_sleep (1);
-                  err = assuan_socket_connect (ctx, sockname, 0, 0);
-                  if (!err)
-                    {
-                      if (verbose)
-                        {
-                          log_info (_("connection to the dirmngr"
-                                      " established\n"));
-                          did_success_msg = 1;
-                        }
-                      break;
-                    }
-                }
-            }
+            err = wait_for_sock (SECS_TO_WAIT_FOR_DIRMNGR, "dirmngr",
+                                 sockname, verbose, ctx, &did_success_msg);
         }
 
       unlock_spawning (&lock, "dirmngr");
index c1f05b8..76255ba 100644 (file)
@@ -241,3 +241,42 @@ is_valid_user_id (const char *uid)
 
   return 1;
 }
+
+
+/* Returns true if STRING is a valid domain name according to the LDH
+ * rule. */
+int
+is_valid_domain_name (const char *string)
+{
+  static char const ldh_chars[] =
+    "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-";
+  const char *s;
+
+  /* Note that we do not check the length limit of a label or the
+   * entire name */
+
+  for (s=string; *s; s++)
+    if (*s == '.')
+      {
+        if (string == s)
+          return 0; /* Dot at the start of the string.  */
+                    /* (may also be at the end like in ".") */
+        if (s[1] == '.')
+          return 0; /* No - double dot.  */
+      }
+    else if (!strchr (ldh_chars, *s))
+      return 0;
+    else if (*s == '-')
+      {
+        if (string == s)
+          return 0;  /* Leading hyphen.  */
+        if (s[-1] == '.')
+          return 0;  /* Hyphen at begin of a label.  */
+        if (s[1] == '.')
+          return 0;  /* Hyphen at start of a label.  */
+        if (!s[1])
+          return 0;  /* Trailing hyphen.  */
+      }
+
+  return !!*string;
+}
index bce003f..7355cee 100644 (file)
@@ -24,6 +24,7 @@ int is_valid_mailbox (const char *name);
 int is_valid_mailbox_mem (const void *buffer, size_t length);
 char *mailbox_from_userid (const char *userid);
 int is_valid_user_id (const char *uid);
+int is_valid_domain_name (const char *string);
 
 
 #endif /*GNUPG_COMMON_MBOX_UTIL_H*/
index e90010c..55a7ee9 100644 (file)
@@ -340,11 +340,10 @@ gnupg_usleep (unsigned int usecs)
       struct timespec req;
       struct timespec rem;
 
-      req.tv_sec = 0;
-      req.tv_nsec = usecs * 1000;
-
+      req.tv_sec  = usecs / 1000000;
+      req.tv_nsec = (usecs % 1000000) * 1000;
       while (nanosleep (&req, &rem) < 0 && errno == EINTR)
-        req = rem;
+          req = rem;
     }
 
 #else /*Standard Unix*/
index 979d4b3..fb1ac12 100644 (file)
@@ -33,7 +33,7 @@
 
 
 static void
-run_test (void)
+run_mbox_test (void)
 {
   static struct
   {
@@ -93,13 +93,64 @@ run_test (void)
 }
 
 
+static void
+run_dns_test (void)
+{
+  static struct
+  {
+    const char *name;
+    int valid;
+  } testtbl[] =
+    {
+      { "", 0 },
+      { ".", 0 },
+      { "-", 0 },
+      { "a", 1 },
+      { "ab", 1 },
+      { "a.b", 1 },
+      { "a.b.", 1 },
+      { ".a.b.", 0 },
+      { ".a.b", 0 },
+      { "-a.b", 0 },
+      { "a-.b", 0 },
+      { "a.-b", 0 },
+      { "a.b-", 0 },
+      { "a.b-.", 0 },
+      { "a..b", 0 },
+      { "ab.c", 1 },
+      { "a-b.c", 1 },
+      { "a-b-.c", 0 },
+      { "-a-b.c", 0 },
+      { "example.org", 1 },
+      { "x.example.org", 1 },
+      { "xy.example.org", 1 },
+      { "Xy.example.org", 1 },
+      { "-Xy.example.org", 0 },
+      { "Xy.example-.org", 0 },
+      { "foo.example.org..", 0 },
+      { "foo.example.org.", 1 },
+      { ".foo.example.org.", 0 },
+      { "..foo.example.org.", 0 },
+      { NULL, 0 }
+    };
+  int idx;
+
+  for (idx=0; testtbl[idx].name; idx++)
+    {
+      if (is_valid_domain_name (testtbl[idx].name) != testtbl[idx].valid)
+        fail (idx);
+    }
+}
+
+
 int
 main (int argc, char **argv)
 {
   (void)argc;
   (void)argv;
 
-  run_test ();
+  run_mbox_test ();
+  run_dns_test ();
 
   return 0;
 }
index f77317f..8c80377 100644 (file)
@@ -28,7 +28,7 @@ min_automake_version="1.14"
 m4_define([mym4_package],[gnupg])
 m4_define([mym4_major], [2])
 m4_define([mym4_minor], [2])
-m4_define([mym4_micro], [9])
+m4_define([mym4_micro], [10])
 
 # To start a new development series, i.e a new major or minor number
 # you need to mark an arbitrary commit before the first beta release
index 31f8e0f..5965f84 100644 (file)
@@ -1203,6 +1203,14 @@ main (int argc, char **argv)
           current_logfile = xstrdup (logfile);
         }
 
+      if (debug_wait)
+        {
+          log_debug ("waiting for debugger - my pid is %u .....\n",
+                     (unsigned int)getpid());
+          gnupg_sleep (debug_wait);
+          log_debug ("... okay\n");
+        }
+
 #ifndef HAVE_W32_SYSTEM
       if (strchr (socket_name, ':'))
         {
index b7cdb24..fcf0c1a 100644 (file)
@@ -887,6 +887,18 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
       if (err)
         goto leave;
 
+      /* Check for rogue DNS names.  */
+      for (i = 0; i < srvscount; i++)
+        {
+          if (!is_valid_domain_name (srvs[i].target))
+            {
+              err = gpg_error (GPG_ERR_DNS_ADDRESS);
+              log_error ("rogue openpgpkey SRV record for '%s'\n", domain);
+              xfree (srvs);
+              goto leave;
+            }
+        }
+
       /* Find the first target which also ends in DOMAIN or is equal
        * to DOMAIN.  */
       domainlen = strlen (domain);
index d0aa010..3f8f6b9 100644 (file)
@@ -675,6 +675,10 @@ supplied passphrase is used for the new key and the agent does not ask
 for it.  To create a key without any protection @code{--passphrase ''}
 may be used.
 
+Note that it is possible to create a primary key and a subkey using
+non-default algorithms by using ``default'' and changing the default
+parameters using the option @option{--default-new-key-algo}.
+
 @item --quick-set-expire @var{fpr} @var{expire} [*|@var{subfprs}]
 @opindex quick-set-expire
 With two arguments given, directly set the expiration time of the
@@ -702,7 +706,8 @@ and other ECC curves.  For example the string ``rsa'' adds an RSA key
 with the default key length; a string ``rsa4096'' requests that the
 key length is 4096 bits.  The string ``future-default'' is an alias
 for the algorithm which will likely be used as default algorithm in
-future versions of gpg.
+future versions of gpg.  To list the supported ECC curves the command
+@code{gpg --with-colons --list-config curve} can be used.
 
 Depending on the given @var{algo} the subkey may either be an
 encryption subkey or a signing subkey.  If an algorithm is capable of
@@ -2933,6 +2938,13 @@ smartcard, and "%%" results in a single "%". %k, %K, and %f are only
 meaningful when making a key signature (certification), and %c is only
 meaningful when using the OpenPGP smartcard.
 
+@item --known-notation @var{name}
+@opindex known-notation
+Adds @var{name} to a list of known critical signature notations.  The
+effect of this is that gpg will not mark a signature with a critical
+signature notation of that name as bad.  Note that gpg already knows
+by default about a few critical signatures notation names.
+
 @item --sig-policy-url @var{string}
 @itemx --cert-policy-url @var{string}
 @itemx --set-policy-url @var{string}
@@ -3297,13 +3309,14 @@ user.
 @opindex override-session-key
 Don't use the public key but the session key @var{string} respective
 the session key taken from the first line read from file descriptor
-@var{fd}.  The format of this string is the same as the one printed
-by @option{--show-session-key}. This option is normally not used but
+@var{fd}.  The format of this string is the same as the one printed by
+@option{--show-session-key}. This option is normally not used but
 comes handy in case someone forces you to reveal the content of an
 encrypted message; using this option you can do this without handing
 out the secret key.  Note that using @option{--override-session-key}
 may reveal the session key to all local users via the global process
-table.
+table.  Often it is useful to combine this option with
+@option{--no-keyring}.
 
 @item --ask-sig-expire
 @itemx --no-ask-sig-expire
@@ -3603,6 +3616,15 @@ Operation is further controlled by a few environment variables:
 
 @end table
 
+When calling the gpg-agent component @command{@gpgname} sends a set of
+environment variables to gpg-agent.  The names of these variables can
+be listed using the command:
+
+@example
+  gpg-connect-agent 'getinfo std_env_names' /bye | awk '$1=="D" @{print $2@}'
+@end example
+
+
 
 @c *******************************************
 @c ***************            ****************
index 9bc90fb..d086cef 100644 (file)
 #include "call-dirmngr.h"
 
 
+/* Keys retrieved from the web key directory should be small.  There
+ * is only one UID and we can expect that the number of subkeys is
+ * reasonable.  So we set a generous limit of 256 KiB.  */
+#define MAX_WKD_RESULT_LENGTH   (256 * 1024)
+
+
 /* Parameter structure used to gather status info.  Note that it is
  * also used for WKD requests.  */
 struct ks_status_parm_s
@@ -1365,7 +1371,7 @@ gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick,
       goto leave;
     }
 
-  parm.memfp = es_fopenmem (0, "rwb");
+  parm.memfp = es_fopenmem (MAX_WKD_RESULT_LENGTH, "rwb");
   if (!parm.memfp)
     {
       err = gpg_error_from_syserror ();
@@ -1373,6 +1379,8 @@ gpg_dirmngr_wkd_get (ctrl_t ctrl, const char *name, int quick,
     }
   err = assuan_transact (ctx, line, dns_cert_data_cb, &parm,
                          NULL, NULL, ks_status_cb, &stparm);
+  if (gpg_err_code (err) == GPG_ERR_ENOSPC)
+    err = gpg_error (GPG_ERR_TOO_LARGE);
   if (err)
     goto leave;
 
index d76e7cc..c4afe45 100644 (file)
@@ -88,6 +88,9 @@ struct getkey_ctx_s
      their address used in ITEMS.  */
   strlist_t extra_list;
 
+  /* Hack to return the mechanism (AKL_foo) used to find the key.  */
+  int found_via_akl;
+
   /* Part of the search criteria: The low-level search specification
      as passed to keydb_search.  */
   int nitems;
@@ -391,280 +394,21 @@ getkey_disable_caches ()
 }
 
 
-void
-pubkey_free (pubkey_t key)
-{
-  if (key)
-    {
-      xfree (key->pk);
-      release_kbnode (key->keyblock);
-      xfree (key);
-    }
-}
-
+/* Free a list of pubkey_t objects.  */
 void
 pubkeys_free (pubkey_t keys)
 {
   while (keys)
     {
       pubkey_t next = keys->next;
-      pubkey_free (keys);
+      xfree (keys->pk);
+      release_kbnode (keys->keyblock);
+      xfree (keys);
       keys = next;
     }
 }
 
 
-/* Returns all keys that match the search specification SEARCH_TERMS.
- *
- * This function also checks for and warns about duplicate entries in
- * the keydb, which can occur if the user has configured multiple
- * keyrings or keyboxes or if a keyring or keybox was corrupted.
- *
- * Note: SEARCH_TERMS will not be expanded (i.e., it may not be a
- * group).
- *
- * USE is the operation for which the key is required.  It must be
- * either PUBKEY_USAGE_ENC, PUBKEY_USAGE_SIG, PUBKEY_USAGE_CERT or
- * PUBKEY_USAGE_AUTH.
- *
- * INCLUDE_UNUSABLE indicates whether disabled keys are allowed.
- * (Recipients specified with --encrypt-to and --hidden-encrypt-to may
- * be disabled.  It is possible to edit disabled keys.)
- *
- * SOURCE is the context in which SEARCH_TERMS was specified, e.g.,
- * "--encrypt-to", etc.  If this function is called interactively,
- * then this should be NULL.
- *
- * If WARN_POSSIBLY_AMBIGUOUS is set, then emits a warning if the user
- * does not specify a long key id or a fingerprint.
- *
- * The results are placed in *KEYS.  *KEYS must be NULL!
- *
- * Fixme: Currently, only PUBKEY_USAGE_ENC and PUBKEY_USAGE_SIG are
- * implemented.  */
-gpg_error_t
-get_pubkeys (ctrl_t ctrl,
-             char *search_terms, int use, int include_unusable, char *source,
-             int warn_possibly_ambiguous,
-             pubkey_t *r_keys)
-{
-  /* We show a warning when a key appears multiple times in the DB.
-   * This can happen for two reasons:
-   *
-   *   - The user has configured multiple keyrings or keyboxes.
-   *
-   *   - The keyring or keybox has been corrupted in some way, e.g., a
-   *     bug or a random process changing them.
-   *
-   * For each duplicate, we only want to show the key once.  Hence,
-   * this list.  */
-  static strlist_t key_dups;
-  gpg_error_t err;
-  char *use_str;   /* USE transformed to a string.  */
-  KEYDB_SEARCH_DESC desc;
-  GETKEY_CTX ctx;
-  pubkey_t results = NULL;
-  pubkey_t r;
-  int count;
-  char fingerprint[2 * MAX_FINGERPRINT_LEN + 1];
-
-  if (DBG_LOOKUP)
-    {
-      log_debug ("\n");
-      log_debug ("%s: Checking %s=%s\n",
-                 __func__, source ? source : "user input", search_terms);
-    }
-
-  if (*r_keys)
-    log_bug ("%s: KEYS should be NULL!\n", __func__);
-
-  switch (use)
-    {
-    case PUBKEY_USAGE_ENC: use_str = "encrypt"; break;
-    case PUBKEY_USAGE_SIG: use_str = "sign"; break;
-    case PUBKEY_USAGE_CERT: use_str = "cetify"; break;
-    case PUBKEY_USAGE_AUTH: use_str = "authentication"; break;
-    default: log_bug ("%s: Bad value for USE (%d)\n", __func__, use);
-    }
-
-  if (use == PUBKEY_USAGE_CERT || use == PUBKEY_USAGE_AUTH)
-    log_bug ("%s: use=%s is unimplemented.\n", __func__, use_str);
-
-  err = classify_user_id (search_terms, &desc, 1);
-  if (err)
-    {
-      log_info (_("key \"%s\" not found: %s\n"),
-                search_terms, gpg_strerror (err));
-      if (!opt.quiet && source)
-        log_info (_("(check argument of option '%s')\n"), source);
-      goto leave;
-    }
-
-  if (warn_possibly_ambiguous
-      && ! (desc.mode == KEYDB_SEARCH_MODE_LONG_KID
-            || desc.mode == KEYDB_SEARCH_MODE_FPR16
-            || desc.mode == KEYDB_SEARCH_MODE_FPR20
-            || desc.mode == KEYDB_SEARCH_MODE_FPR))
-    {
-      log_info (_("Warning: '%s' should be a long key ID or a fingerprint\n"),
-                search_terms);
-      if (!opt.quiet && source)
-        log_info (_("(check argument of option '%s')\n"), source);
-    }
-
-  /* Gather all of the results.  */
-  ctx = NULL;
-  count = 0;
-  do
-    {
-      PKT_public_key *pk;
-      KBNODE kb;
-
-      pk = xtrycalloc (1, sizeof *pk);
-      if (!pk)
-        {
-          err = gpg_error_from_syserror ();
-          goto leave;
-        }
-
-      pk->req_usage = use;
-
-      if (! ctx)
-        err = get_pubkey_byname (ctrl, &ctx, pk, search_terms, &kb, NULL,
-                                 include_unusable, 1);
-      else
-        err = getkey_next (ctrl, ctx, pk, &kb);
-
-      if (gpg_err_code (err) == GPG_ERR_NOT_FOUND) /* No more results.   */
-        {
-          xfree (pk);
-          break;
-        }
-      else if (err) /* An error (other than "not found").  */
-        {
-          log_error (_("error looking up: %s\n"), gpg_strerror (err));
-          xfree (pk);
-          break;
-        }
-
-      /* Another result!  */
-      count ++;
-
-      r = xtrycalloc (1, sizeof (*r));
-      if (!r)
-        {
-          err = gpg_error_from_syserror ();
-          xfree (pk);
-          goto leave;
-        }
-      r->pk = pk;
-      r->keyblock = kb;
-      r->next = results;
-      results = r;
-    }
-  while (ctx);
-  getkey_end (ctrl, ctx);
-
-  if (DBG_LOOKUP)
-    {
-      log_debug ("%s resulted in %d matches.\n", search_terms, count);
-      for (r = results; r; r = r->next)
-        log_debug ("  %s\n",
-                   hexfingerprint (r->keyblock->pkt->pkt.public_key,
-                                   fingerprint, sizeof (fingerprint)));
-    }
-
-  if (! results && gpg_err_code (err) == GPG_ERR_NOT_FOUND)
-    { /* No match.  */
-      if (DBG_LOOKUP)
-        log_debug ("%s: '%s' not found.\n", __func__, search_terms);
-
-      log_info (_("key \"%s\" not found\n"), search_terms);
-      if (!opt.quiet && source)
-        log_info (_("(check argument of option '%s')\n"), source);
-
-      goto leave;
-    }
-  else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
-    ; /* No more matches.  */
-  else if (err)
-    { /* Some other error.  An error message was already printed out.
-       * Free RESULTS and continue.  */
-      goto leave;
-    }
-
-  /* Check for duplicates.  */
-  if (DBG_LOOKUP)
-    log_debug ("%s: Checking results of %s='%s' for dups\n",
-               __func__, source ? source : "user input", search_terms);
-  count = 0;
-  for (r = results; r; r = r->next)
-    {
-      pubkey_t *prevp;
-      pubkey_t next;
-      pubkey_t r2;
-      int dups = 0;
-
-      prevp = &r->next;
-      next = r->next;
-      while ((r2 = next))
-        {
-          if (cmp_public_keys (r->keyblock->pkt->pkt.public_key,
-                               r2->keyblock->pkt->pkt.public_key) != 0)
-            { /* Not a dup.  */
-              prevp = &r2->next;
-              next = r2->next;
-              continue;
-            }
-
-          dups ++;
-          count ++;
-
-          /* Remove R2 from the list.  */
-          *prevp = r2->next;
-          release_kbnode (r2->keyblock);
-          next = r2->next;
-          xfree (r2);
-        }
-
-      if (dups)
-        {
-          hexfingerprint (r->keyblock->pkt->pkt.public_key,
-                          fingerprint, sizeof fingerprint);
-          if (! strlist_find (key_dups, fingerprint))
-            {
-              char fingerprint_formatted[MAX_FORMATTED_FINGERPRINT_LEN + 1];
-
-              log_info (_("Warning: %s appears in the keyring %d times\n"),
-                        format_hexfingerprint (fingerprint,
-                                               fingerprint_formatted,
-                                               sizeof fingerprint_formatted),
-                        1 + dups);
-              add_to_strlist (&key_dups, fingerprint);
-            }
-        }
-    }
-
-  if (DBG_LOOKUP && count)
-    {
-      log_debug ("After removing %d dups:\n", count);
-      for (r = results, count = 0; r; r = r->next)
-        log_debug ("  %d: %s\n",
-                   count,
-                   hexfingerprint (r->keyblock->pkt->pkt.public_key,
-                                   fingerprint, sizeof fingerprint));
-    }
-
- leave:
-  if (err)
-    pubkeys_free (results);
-  else
-    *r_keys = results;
-
-  return err;
-}
-
-
 static void
 pk_from_block (PKT_public_key *pk, kbnode_t keyblock, kbnode_t found_key)
 {
@@ -1265,6 +1009,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
   int is_mbox;
   int nodefault = 0;
   int anylocalfirst = 0;
+  int mechanism_type = AKL_NODEFAULT;
 
   /* If RETCTX is not NULL, then RET_KDBHD must be NULL.  */
   log_assert (retctx == NULL || ret_kdbhd == NULL);
@@ -1354,18 +1099,19 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
          size_t fpr_len;
          int did_akl_local = 0;
          int no_fingerprint = 0;
-         const char *mechanism = "?";
+         const char *mechanism_string = "?";
 
-         switch (akl->type)
+          mechanism_type = akl->type;
+         switch (mechanism_type)
            {
            case AKL_NODEFAULT:
              /* This is a dummy mechanism.  */
-             mechanism = "None";
+             mechanism_string = "None";
              rc = GPG_ERR_NO_PUBKEY;
              break;
 
            case AKL_LOCAL:
-             mechanism = "Local";
+             mechanism_string = "Local";
              did_akl_local = 1;
              if (retctx)
                {
@@ -1379,35 +1125,35 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
              break;
 
            case AKL_CERT:
-             mechanism = "DNS CERT";
+             mechanism_string = "DNS CERT";
              glo_ctrl.in_auto_key_retrieve++;
              rc = keyserver_import_cert (ctrl, name, 0, &fpr, &fpr_len);
              glo_ctrl.in_auto_key_retrieve--;
              break;
 
            case AKL_PKA:
-             mechanism = "PKA";
+             mechanism_string = "PKA";
              glo_ctrl.in_auto_key_retrieve++;
              rc = keyserver_import_pka (ctrl, name, &fpr, &fpr_len);
              glo_ctrl.in_auto_key_retrieve--;
              break;
 
            case AKL_DANE:
-             mechanism = "DANE";
+             mechanism_string = "DANE";
              glo_ctrl.in_auto_key_retrieve++;
              rc = keyserver_import_cert (ctrl, name, 1, &fpr, &fpr_len);
              glo_ctrl.in_auto_key_retrieve--;
              break;
 
            case AKL_WKD:
-             mechanism = "WKD";
+             mechanism_string = "WKD";
              glo_ctrl.in_auto_key_retrieve++;
              rc = keyserver_import_wkd (ctrl, name, 0, &fpr, &fpr_len);
              glo_ctrl.in_auto_key_retrieve--;
              break;
 
            case AKL_LDAP:
-             mechanism = "LDAP";
+             mechanism_string = "LDAP";
              glo_ctrl.in_auto_key_retrieve++;
              rc = keyserver_import_ldap (ctrl, name, &fpr, &fpr_len);
              glo_ctrl.in_auto_key_retrieve--;
@@ -1420,7 +1166,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
               * and getting a whole lot of keys back. */
              if (keyserver_any_configured (ctrl))
                {
-                 mechanism = "keyserver";
+                 mechanism_string = "keyserver";
                  glo_ctrl.in_auto_key_retrieve++;
                  rc = keyserver_import_name (ctrl, name, &fpr, &fpr_len,
                                               opt.keyserver);
@@ -1428,7 +1174,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
                }
              else
                {
-                 mechanism = "Unconfigured keyserver";
+                 mechanism_string = "Unconfigured keyserver";
                  rc = GPG_ERR_NO_PUBKEY;
                }
              break;
@@ -1437,7 +1183,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
              {
                struct keyserver_spec *keyserver;
 
-               mechanism = akl->spec->uri;
+               mechanism_string = akl->spec->uri;
                keyserver = keyserver_match (akl->spec);
                glo_ctrl.in_auto_key_retrieve++;
                rc = keyserver_import_name (ctrl,
@@ -1499,13 +1245,13 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
              /* Key found.  */
               if (opt.verbose)
                 log_info (_("automatically retrieved '%s' via %s\n"),
-                          name, mechanism);
+                          name, mechanism_string);
              break;
            }
          if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY
               || opt.verbose || no_fingerprint)
            log_info (_("error retrieving '%s' via %s: %s\n"),
-                     name, mechanism,
+                     name, mechanism_string,
                      no_fingerprint ? _("No fingerprint") : gpg_strerror (rc));
        }
     }
@@ -1521,6 +1267,7 @@ get_pubkey_byname (ctrl_t ctrl, GETKEY_CTX * retctx, PKT_public_key * pk,
     {
       log_assert (!(*retctx)->extra_list);
       (*retctx)->extra_list = namelist;
+      (*retctx)->found_via_akl = mechanism_type;
     }
   else
     free_strlist (namelist);
@@ -1568,6 +1315,34 @@ subkey_is_ok (const PKT_public_key *sub)
   return ! sub->flags.revoked && sub->flags.valid && ! sub->flags.disabled;
 }
 
+/* Return true if KEYBLOCK has only expired encryption subkyes.  Note
+ * that the function returns false if the key has no encryption
+ * subkeys at all or the subkecys are revoked.  */
+static int
+only_expired_enc_subkeys (kbnode_t keyblock)
+{
+  kbnode_t node;
+  PKT_public_key *sub;
+  int any = 0;
+
+  for (node = find_next_kbnode (keyblock, PKT_PUBLIC_SUBKEY);
+       node; node = find_next_kbnode (node, PKT_PUBLIC_SUBKEY))
+    {
+      sub = node->pkt->pkt.public_key;
+
+      if (!(sub->pubkey_usage & PUBKEY_USAGE_ENC))
+        continue;
+
+      if (!subkey_is_ok (sub))
+        continue;
+
+      any = 1;
+      if (!sub->has_expired)
+        return 0;
+    }
+
+  return any? 1 : 0;
+}
 
 /* Finally this function compares a NEW key to the former candidate
  * OLD.  Returns < 0 if the old key is worse, > 0 if the old key is
@@ -1636,23 +1411,68 @@ pubkey_cmp (ctrl_t ctrl, const char *name, struct pubkey_cmp_cookie *old,
 gpg_error_t
 get_best_pubkey_byname (ctrl_t ctrl, GETKEY_CTX *retctx, PKT_public_key *pk,
                         const char *name, KBNODE *ret_keyblock,
-                        int include_unusable, int no_akl)
+                        int include_unusable)
 {
   gpg_error_t err;
   struct getkey_ctx_s *ctx = NULL;
+  int is_mbox = is_valid_mailbox (name);
+  int wkd_tried = 0;
 
   if (retctx)
     *retctx = NULL;
 
+ start_over:
+  if (ctx)  /* Clear  in case of a start over.  */
+    {
+      if (ret_keyblock)
+        {
+          release_kbnode (*ret_keyblock);
+          *ret_keyblock = NULL;
+        }
+      getkey_end (ctrl, ctx);
+      ctx = NULL;
+    }
   err = get_pubkey_byname (ctrl, &ctx, pk, name, ret_keyblock,
-                           NULL, include_unusable, no_akl);
+                           NULL, include_unusable, 0);
   if (err)
     {
       getkey_end (ctrl, ctx);
       return err;
     }
 
-  if (is_valid_mailbox (name) && ctx)
+  /* If the keyblock was retrieved from the local database and the key
+   * has expired, do further checks.  However, we can do this only if
+   * the caller requested a keyblock.  */
+  if (is_mbox && ctx && ctx->found_via_akl == AKL_LOCAL && ret_keyblock)
+    {
+      u32 now = make_timestamp ();
+      PKT_public_key *pk2 = (*ret_keyblock)->pkt->pkt.public_key;
+      int found;
+
+      /* If the key has expired and its origin was the WKD then try to
+       * get a fresh key from the WKD.  We also try this if the key
+       * has any only expired encryption subkeys.  In case we checked
+       * for a fresh copy in the last 3 hours we won't do that again.
+       * Unfortunately that does not yet work because KEYUPDATE is
+       * only updated during import iff the key has actually changed
+       * (see import.c:import_one).  */
+      if (!wkd_tried && pk2->keyorg == KEYORG_WKD
+          && (pk2->keyupdate + 3*3600) < now
+          && (pk2->has_expired || only_expired_enc_subkeys (*ret_keyblock)))
+        {
+          if (opt.verbose)
+            log_info (_("checking for a fresh copy of an expired key via %s\n"),
+                      "WKD");
+          wkd_tried = 1;
+          glo_ctrl.in_auto_key_retrieve++;
+          found = !keyserver_import_wkd (ctrl, name, 0, NULL, NULL);
+          glo_ctrl.in_auto_key_retrieve--;
+          if (found)
+            goto start_over;
+        }
+    }
+
+  if (is_mbox && ctx)
     {
       /* Rank results and return only the most relevant key.  */
       struct pubkey_cmp_cookie best = { 0 };
index c117de3..e18eefe 100644 (file)
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -109,6 +109,7 @@ enum cmd_and_opt_values
     oCertNotation,
     oShowNotation,
     oNoShowNotation,
+    oKnownNotation,
     aEncrFiles,
     aEncrSym,
     aDecryptFiles,
@@ -673,6 +674,7 @@ static ARGPARSE_OPTS opts[] = {
   ARGPARSE_s_s (oSetNotation,  "set-notation", "@"),
   ARGPARSE_s_s (oSigNotation,  "sig-notation", "@"),
   ARGPARSE_s_s (oCertNotation, "cert-notation", "@"),
+  ARGPARSE_s_s (oKnownNotation, "known-notation", "@"),
 
   ARGPARSE_group (302, N_(
   "@\n(See the man page for a complete listing of all commands and options)\n"
@@ -3301,6 +3303,7 @@ main (int argc, char **argv)
            break;
          case oSigNotation: add_notation_data( pargs.r.ret_str, 0 ); break;
          case oCertNotation: add_notation_data( pargs.r.ret_str, 1 ); break;
+          case oKnownNotation: register_known_notation (pargs.r.ret_str); break;
          case oShowNotation:
            deprecated_warning(configname,configlineno,"--show-notation",
                               "--list-options ","show-notations");
index 6dad8ee..11de592 100644 (file)
@@ -2070,9 +2070,12 @@ import_one (ctrl_t ctrl,
           keydb_release (hd);
           hd = NULL;
 
-          /* Fixme: we do not track the time we last checked a key for
+          /* FIXME: We do not track the time we last checked a key for
            * updates.  To do this we would need to rewrite even the
-           * keys which have no changes.  */
+           * keys which have no changes.  Adding this would be useful
+           * for the automatic update of expired keys via the WKD in
+           * case the WKD still carries the expired key.  See
+           * get_best_pubkey_byname.  */
           same_key = 1;
           if (is_status_enabled ())
             print_import_ok (pk, 0);
index 8e1a724..6fb4e5e 100644 (file)
@@ -341,20 +341,9 @@ struct pubkey_s
 };
 typedef struct pubkey_s *pubkey_t;
 
-/* Free a single key.  This does not remove key from any list!  */
-void pubkey_free (pubkey_t key);
-
 /* Free a list of public keys.  */
 void pubkeys_free (pubkey_t keys);
 
-/* Returns all keys that match the search specification SEARCH_TERMS.
-   The returned keys should be freed using pubkeys_free.  */
-gpg_error_t
-get_pubkeys (ctrl_t ctrl,
-             char *search_terms, int use, int include_unusable, char *source,
-             int warn_possibly_ambiguous,
-             pubkey_t *r_keys);
-
 /* Find a public key identified by NAME.  */
 int get_pubkey_byname (ctrl_t ctrl,
                        GETKEY_CTX *retctx, PKT_public_key *pk,
@@ -367,7 +356,7 @@ int get_pubkey_byname (ctrl_t ctrl,
 gpg_error_t get_best_pubkey_byname (ctrl_t ctrl,
                                     GETKEY_CTX *retctx, PKT_public_key *pk,
                                     const char *name, KBNODE *ret_keyblock,
-                                    int include_unusable, int no_akl);
+                                    int include_unusable);
 
 /* Get a public key directly from file FNAME.  */
 gpg_error_t get_pubkey_fromfile (ctrl_t ctrl,
index a4949f4..ed57d5d 100644 (file)
@@ -4135,8 +4135,10 @@ generate_keypair (ctrl_t ctrl, int full, const char *fname,
 
   if (opt.batch && card_serialno)
     {
-      /* We don't yet support unattended key generation. */
+      /* We don't yet support unattended key generation with a card
+       * serial number. */
       log_error (_("can't do this in batch mode\n"));
+      print_further_info ("key generation with card serial number");
       return;
     }
 
index c9121a1..7942558 100644 (file)
@@ -652,7 +652,7 @@ locate_one (ctrl_t ctrl, strlist_t names)
 
   for (sl = names; sl; sl = sl->next)
     {
-      rc = get_best_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, 1, 0);
+      rc = get_best_pubkey_byname (ctrl, &ctx, NULL, sl->d, &keyblock, 1);
       if (rc)
        {
          if (gpg_err_code (rc) != GPG_ERR_NO_PUBKEY)
index e76e6af..6d01b10 100644 (file)
@@ -610,6 +610,9 @@ char *issuer_fpr_string (PKT_signature *sig);
 
 /*-- parse-packet.c --*/
 
+
+void register_known_notation (const char *string);
+
 /* Sets the packet list mode to MODE (i.e., whether we are dumping a
    packet or not).  Returns the current mode.  This allows for
    temporarily suspending dumping by doing the following:
index a64d4f7..ff348ec 100644 (file)
 #define MAX_COMMENT_PACKET_LENGTH ( 64 * 1024)
 #define MAX_ATTR_PACKET_LENGTH    ( 16 * 1024*1024)
 
-
 static int mpi_print_mode;
 static int list_mode;
 static estream_t listfp;
 
+/* A linked list of known notation names.  Note that the FLAG is used
+ * to store the length of the name to speed up the check.  */
+static strlist_t known_notations_list;
+
+
 static int parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts,
                  off_t * retpos, int *skip, IOBUF out, int do_skip
 #if DEBUG_PARSE_PACKET
@@ -186,6 +190,36 @@ mpi_read (iobuf_t inp, unsigned int *ret_nread, int secure)
 }
 
 
+/* Register STRING as a known critical notation name.  */
+void
+register_known_notation (const char *string)
+{
+  strlist_t sl;
+
+  if (!known_notations_list)
+    {
+      sl = add_to_strlist (&known_notations_list,
+                           "preferred-email-encoding@pgp.com");
+      sl->flags = 32;
+      sl = add_to_strlist (&known_notations_list, "pka-address@gnupg.org");
+      sl->flags = 21;
+    }
+  if (!string)
+    return; /* Only initialized the default known notations.  */
+
+  /* In --set-notation we use an exclamation mark to indicate a
+   * critical notation.  As a convenience skip this here.  */
+  if (*string == '!')
+    string++;
+
+  if (!*string || strlist_find (known_notations_list, string))
+    return; /* Empty string or already registered.  */
+
+  sl = add_to_strlist (&known_notations_list, string);
+  sl->flags = strlen (string);
+}
+
+
 int
 set_packet_list_mode (int mode)
 {
@@ -1171,7 +1205,7 @@ parse_symkeyenc (IOBUF inp, int pkttype, unsigned long pktlen,
     }
   if (s2kmode == 3)
     {
-      k->s2k.count = iobuf_get (inp);
+      k->s2k.count = iobuf_get_noeof (inp);
       pktlen--;
     }
   k->seskeylen = seskeylen;
@@ -1602,14 +1636,24 @@ parse_one_sig_subpkt (const byte * buffer, size_t n, int type)
 
 /* Return true if we understand the critical notation.  */
 static int
-can_handle_critical_notation (const byte * name, size_t len)
+can_handle_critical_notation (const byte *name, size_t len)
 {
-  if (len == 32 && memcmp (name, "preferred-email-encoding@pgp.com", 32) == 0)
-    return 1;
-  if (len == 21 && memcmp (name, "pka-address@gnupg.org", 21) == 0)
-    return 1;
+  strlist_t sl;
 
-  return 0;
+  register_known_notation (NULL); /* Make sure it is initialized.  */
+
+  for (sl = known_notations_list; sl; sl = sl->next)
+    if (sl->flags == len && !memcmp (sl->d, name, len))
+      return 1; /* Known */
+
+  if (opt.verbose)
+    {
+      log_info(_("Unknown critical signature notation: ") );
+      print_utf8_buffer (log_get_stream(), name, len);
+      log_printf ("\n");
+    }
+
+  return 0; /* Unknown.  */
 }
 
 
@@ -2489,7 +2533,7 @@ parse_key (IOBUF inp, int pkttype, unsigned long pktlen,
                      err = gpg_error (GPG_ERR_INV_PACKET);
                      goto leave;
                    }
-                 ski->s2k.count = iobuf_get (inp);
+                 ski->s2k.count = iobuf_get_noeof (inp);
                  pktlen--;
                  if (list_mode)
                    es_fprintf (listfp, "\tprotect count: %lu (%lu)\n",
index 6f04249..56c9385 100644 (file)
@@ -834,7 +834,7 @@ find_and_check_key (ctrl_t ctrl, const char *name, unsigned int use,
   if (from_file)
     rc = get_pubkey_fromfile (ctrl, pk, name);
   else
-    rc = get_best_pubkey_byname (ctrl, NULL, pk, name, &keyblock, 0, 0);
+    rc = get_best_pubkey_byname (ctrl, NULL, pk, name, &keyblock, 0);
   if (rc)
     {
       int code;
index 4f9002c..7cb1f1e 100644 (file)
--- a/po/de.po
+++ b/po/de.po
@@ -9,7 +9,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: gnupg-2.1.0\n"
 "Report-Msgid-Bugs-To: translations@gnupg.org\n"
-"PO-Revision-Date: 2018-07-12 14:48+0200\n"
+"PO-Revision-Date: 2018-08-30 09:44+0200\n"
 "Last-Translator: Werner Koch <wk@gnupg.org>\n"
 "Language-Team: German <de@li.org>\n"
 "Language: de\n"
@@ -851,19 +851,21 @@ msgstr "WARNUNG: \"%s%s\" ist eine veraltete Option - sie hat keine Wirkung.\n"
 msgid "unknown debug flag '%s' ignored\n"
 msgstr "Unbekanntes Debug Flag '%s' wird ignoriert\n"
 
-#, c-format
-msgid "no running gpg-agent - starting '%s'\n"
-msgstr "Kein aktiver gpg-agent - `%s' wird gestartet\n"
-
-#, c-format
-msgid "waiting for the agent to come up ... (%ds)\n"
+#, fuzzy, c-format
+#| msgid "waiting for the agent to come up ... (%ds)\n"
+msgid "waiting for the %s to come up ... (%ds)\n"
 msgstr "Warte bis der gpg-agent bereit ist ... (%ds)\n"
 
-#, c-format
-msgid "connection to agent established\n"
+#, fuzzy, c-format
+#| msgid "connection to agent established\n"
+msgid "connection to %s established\n"
 msgstr "Verbindung zum gpg-agent aufgebaut\n"
 
 #, c-format
+msgid "no running gpg-agent - starting '%s'\n"
+msgstr "Kein aktiver gpg-agent - `%s' wird gestartet\n"
+
+#, c-format
 msgid "connection to agent is in restricted mode\n"
 msgstr "Verbindung zum gpg-agent ist im eingeschränkten Modus.\n"
 
@@ -871,14 +873,6 @@ msgstr "Verbindung zum gpg-agent ist im eingeschränkten Modus.\n"
 msgid "no running Dirmngr - starting '%s'\n"
 msgstr "Kein aktiver Dirmngr - `%s' wird gestartet\n"
 
-#, c-format
-msgid "waiting for the dirmngr to come up ... (%ds)\n"
-msgstr "Warte bis der Dirmngr bereit ist ... (%ds)\n"
-
-#, c-format
-msgid "connection to the dirmngr established\n"
-msgstr "Verbindung zum Dirmngr aufgebaut\n"
-
 #. TRANSLATORS: Copy the prefix between the vertical bars
 #. verbatim.  It will not be printed.
 msgid "|audit-log-result|Good"
@@ -1830,23 +1824,6 @@ msgid "[User ID not found]"
 msgstr "[User-ID nicht gefunden]"
 
 #, c-format
-msgid "(check argument of option '%s')\n"
-msgstr "(Prüfe das Argument der Option '%s')\n"
-
-#, c-format
-msgid "Warning: '%s' should be a long key ID or a fingerprint\n"
-msgstr ""
-"WARNUNG: '%s' sollte eine lange Schlüssel-ID oder ein Fingerabdruck sein\n"
-
-#, c-format
-msgid "error looking up: %s\n"
-msgstr "Fehler beim Nachschlagen von: %s\n"
-
-#, c-format
-msgid "Warning: %s appears in the keyring %d times\n"
-msgstr "WARNUNG: %s ist %d mal im Schlüsselbund vorhanden\n"
-
-#, c-format
 msgid "automatically retrieved '%s' via %s\n"
 msgstr "`%s' automatisch via %s geholt\n"
 
@@ -1858,10 +1835,18 @@ msgid "No fingerprint"
 msgstr "Kein Fingerabdruck vorhanden"
 
 #, c-format
+msgid "checking for a fresh copy of an expired key via %s\n"
+msgstr "Prüfe auf eine aktuellere Kopie eines abgelaufenen Schlüssels über %s\n"
+
+#, c-format
 msgid "secret key \"%s\" not found: %s\n"
 msgstr "Geheimer Schlüssel \"%s\" nicht gefunden: %s\n"
 
 #, c-format
+msgid "(check argument of option '%s')\n"
+msgstr "(Prüfe das Argument der Option '%s')\n"
+
+#, c-format
 msgid "Warning: not using '%s' as default key: %s\n"
 msgstr ""
 "WARNUNG: \"%s\" wird nicht als voreingestellter geheimer Schlüssel benutzt: "
@@ -4831,6 +4816,11 @@ msgstr ""
 "WARNUNG: Möglicherweise unsicherer symmetrisch verschlüsselter "
 "Sitzungsschlüssel\n"
 
+#, fuzzy, c-format
+#| msgid "Critical signature notation: "
+msgid "Unknown critical signature notation: "
+msgstr "Entscheidender Beglaubigungs-\"Notation\": "
+
 #, c-format
 msgid "subpacket of type %d has critical bit set\n"
 msgstr "Im Unterpaket des Typs %d ist das \"critical bit\" gesetzt\n"
@@ -5831,19 +5821,17 @@ msgstr "Statistik für Schlüssel mit der Email-Adresse \"%s\":\n"
 msgid "this key"
 msgstr "dieser Schlüssel"
 
-#, fuzzy, c-format
-#| msgid "Verified %ld messages signed by \"%s\"."
+#, c-format
 msgid "Verified %d message."
 msgid_plural "Verified %d messages."
-msgstr[0] "%ld überprüfte Nachrichten von \"%s\"."
-msgstr[1] "%ld überprüfte Nachrichten von \"%s\"."
+msgstr[0] "%d überprüfte Nachricht."
+msgstr[1] "%d überprüfte Nachrichten."
 
-#, fuzzy, c-format
-#| msgid "encrypted with %lu passphrases\n"
+#, c-format
 msgid "Encrypted %d message."
 msgid_plural "Encrypted %d messages."
-msgstr[0] "Verschlüsselt mit %lu Passphrases\n"
-msgstr[1] "Verschlüsselt mit %lu Passphrases\n"
+msgstr[0] "%d Nachricht wurde verschlüsselt."
+msgstr[1] "%d Nachrichten wurden verschlüsselt."
 
 #, fuzzy, c-format
 #| msgid "%ld message signed in the future."
@@ -9104,6 +9092,22 @@ msgstr ""
 "Syntax: gpg-check-pattern [optionen] Musterdatei\n"
 "Die von stdin gelesene Passphrase gegen die Musterdatei prüfen\n"
 
+#~ msgid "waiting for the dirmngr to come up ... (%ds)\n"
+#~ msgstr "Warte bis der Dirmngr bereit ist ... (%ds)\n"
+
+#~ msgid "connection to the dirmngr established\n"
+#~ msgstr "Verbindung zum Dirmngr aufgebaut\n"
+
+#~ msgid "Warning: '%s' should be a long key ID or a fingerprint\n"
+#~ msgstr ""
+#~ "WARNUNG: '%s' sollte eine lange Schlüssel-ID oder ein Fingerabdruck sein\n"
+
+#~ msgid "error looking up: %s\n"
+#~ msgstr "Fehler beim Nachschlagen von: %s\n"
+
+#~ msgid "Warning: %s appears in the keyring %d times\n"
+#~ msgstr "WARNUNG: %s ist %d mal im Schlüsselbund vorhanden\n"
+
 #~ msgid "using \"http\" instead of \"https\"\n"
 #~ msgstr "Es wird \"HTTP\" anstatt \"HTTPS\" verwendet\n"
 
index 736d7f8..045c46c 100644 (file)
--- a/po/ja.po
+++ b/po/ja.po
@@ -8,9 +8,9 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: gnupg 2.2.6\n"
+"Project-Id-Version: gnupg 2.2.9\n"
 "Report-Msgid-Bugs-To: translations@gnupg.org\n"
-"PO-Revision-Date: 2018-04-12 10:51+0900\n"
+"PO-Revision-Date: 2018-08-22 17:43+0900\n"
 "Last-Translator: NIIBE Yutaka <gniibe@fsij.org>\n"
 "Language-Team: none\n"
 "Language: ja\n"
@@ -4401,15 +4401,17 @@ msgid ""
 "likely that this message is legitimate.  This is because back\n"
 "then integrity protection was not widely used.\n"
 msgstr ""
+"ヒント: もし、このメッセージが2003年以前に作成されたのであれば、\n"
+"このメッセージはおそらく正当でしょう。当時、整合性の保護機能は\n"
+"広く使われてはいなかったためです。\n"
 
 #, c-format
 msgid "Use the option '%s' to decrypt anyway.\n"
-msgstr ""
+msgstr "それでも復号するにはオプション '%s' を使います。\n"
 
-#, fuzzy, c-format
-#| msgid "decryption failed: %s\n"
+#, c-format
 msgid "decryption forced to fail!\n"
-msgstr "復å\8f·ã\81«å¤±æ\95\97ã\81\97ã\81¾ã\81\97ã\81\9f: %s\n"
+msgstr "復å\8f·ã\81¯å¼·å\88¶ç\9a\84ã\81«å¤±æ\95\97ã\81¨ã\81\95ã\82\8cã\81¾ã\81\97ã\81\9f!\n"
 
 #, c-format
 msgid "decryption okay\n"
@@ -5267,10 +5269,9 @@ msgstr "注意: 鍵 %s は失効済みです\n"
 msgid "bad key signature from key %s: %s (0x%02x, 0x%x)\n"
 msgstr "鍵%sによる不正な鍵への署名: %s (0x%02x, 0x%x)\n"
 
-#, fuzzy, c-format
-#| msgid "bad key signature from key %s: %s (0x%02x, 0x%x)\n"
+#, c-format
 msgid "bad data signature from key %s: %s (0x%02x, 0x%x)\n"
-msgstr "鍵%sによる不正なへの署名: %s (0x%02x, 0x%x)\n"
+msgstr "鍵%sによる不正なデータへの署名: %s (0x%02x, 0x%x)\n"
 
 #, c-format
 msgid "assuming bad signature from key %s due to an unknown critical bit\n"
index 893a782..a44b1ac 100644 (file)
--- a/po/ru.po
+++ b/po/ru.po
@@ -4,14 +4,14 @@
 #              !-- no such user (2011-01-11)
 # Thanks Pawel I. Shajdo <pshajdo@gmail.com>.
 # Thanks Cmecb for the inspiration.
-# Ineiev <ineiev@gnu.org>, 2014, 2015, 2016, 2017
+# Ineiev <ineiev@gnu.org>, 2014, 2015, 2016, 2017, 2018
 #
 # Designated-Translator: none
 msgid ""
 msgstr ""
 "Project-Id-Version: GnuPG 2.2.0\n"
 "Report-Msgid-Bugs-To: translations@gnupg.org\n"
-"PO-Revision-Date: 2018-05-05 17:41+0100\n"
+"PO-Revision-Date: 2018-07-14 17:41+0100\n"
 "Last-Translator: Ineiev <ineiev@gnu.org>\n"
 "Language-Team: Russian <gnupg-ru@gnupg.org>\n"
 "Language: ru\n"
@@ -830,16 +830,16 @@ msgid "unknown debug flag '%s' ignored\n"
 msgstr "неизвестный отладочный флаг '%s' игнорируется\n"
 
 #, c-format
-msgid "no running gpg-agent - starting '%s'\n"
-msgstr "агенÑ\82 gpg Ð½Ðµ Ñ\80абоÑ\82аеÑ\82 - Ð·Ð°Ð¿Ñ\83Ñ\81каем '%s'\n"
+msgid "waiting for the %s to come up ... (%ds)\n"
+msgstr "ожидаÑ\8e Ð¿Ð¾Ð´ÐºÐ»Ñ\8eÑ\87ениÑ\8f %s ... (%iÑ\81)\n"
 
 #, c-format
-msgid "waiting for the agent to come up ... (%ds)\n"
-msgstr "ожидаю подключения агента ... (%iс)\n"
+msgid "connection to %s established\n"
+msgstr "соединение с %s установлено\n"
 
 #, c-format
-msgid "connection to agent established\n"
-msgstr "соединение с агентом установлено\n"
+msgid "no running gpg-agent - starting '%s'\n"
+msgstr "агент gpg не работает - запускаем '%s'\n"
 
 #, c-format
 msgid "connection to agent is in restricted mode\n"
@@ -849,14 +849,6 @@ msgstr "соединение с агентом в ограниченном ре
 msgid "no running Dirmngr - starting '%s'\n"
 msgstr "Dirmngr не выполняется - запуск '%s'\n"
 
-#, c-format
-msgid "waiting for the dirmngr to come up ... (%ds)\n"
-msgstr "ожидаю подключения dirmngr ... (%iс)\n"
-
-#, c-format
-msgid "connection to the dirmngr established\n"
-msgstr "соединение с dirmngr установлено\n"
-
 #. TRANSLATORS: Copy the prefix between the vertical bars
 #. verbatim.  It will not be printed.
 msgid "|audit-log-result|Good"
@@ -1790,23 +1782,6 @@ msgid "[User ID not found]"
 msgstr "[Идентификатор пользователя не найден]"
 
 #, c-format
-msgid "(check argument of option '%s')\n"
-msgstr "(проверьте аргумент параметра '%s')\n"
-
-#, c-format
-msgid "Warning: '%s' should be a long key ID or a fingerprint\n"
-msgstr ""
-"Внимание: '%s' должно быть длинным идентификатором или отпечатком ключа\n"
-
-#, c-format
-msgid "error looking up: %s\n"
-msgstr "ошибка поиска: %s\n"
-
-#, c-format
-msgid "Warning: %s appears in the keyring %d times\n"
-msgstr "Внимание: %s включено в таблицу ключей %d раз\n"
-
-#, c-format
 msgid "automatically retrieved '%s' via %s\n"
 msgstr "автоматически получили '%s' через %s\n"
 
@@ -1818,10 +1793,18 @@ msgid "No fingerprint"
 msgstr "Нет отпечатка"
 
 #, c-format
+msgid "checking for a fresh copy of an expired key via %s\n"
+msgstr "поиск обновленной копии просроченного ключа по %s\n"
+
+#, c-format
 msgid "secret key \"%s\" not found: %s\n"
 msgstr "секретный ключ \"%s\" не найден: %s\n"
 
 #, c-format
+msgid "(check argument of option '%s')\n"
+msgstr "(проверьте аргумент параметра '%s')\n"
+
+#, c-format
 msgid "Warning: not using '%s' as default key: %s\n"
 msgstr "Внимание: '%s' не используется в качестве основного ключа: %s\n"
 
@@ -4501,15 +4484,17 @@ msgid ""
 "likely that this message is legitimate.  This is because back\n"
 "then integrity protection was not widely used.\n"
 msgstr ""
+"Подсказка: если это сообщение создано до 2003 года, вероятно, что\n"
+"оно правомерно, поскольку в те времена защита целостности широко\n"
+"не применялась.\n"
 
 #, c-format
 msgid "Use the option '%s' to decrypt anyway.\n"
-msgstr ""
+msgstr "Воспользуйтесь параметром '%s', чтобы тем не менее расшифровать.\n"
 
-#, fuzzy, c-format
-#| msgid "decryption failed: %s\n"
+#, c-format
 msgid "decryption forced to fail!\n"
-msgstr "сбой расшифровки: %s\n"
+msgstr "принудительный сбой расшифровки!\n"
 
 #, c-format
 msgid "decryption okay\n"
@@ -4774,6 +4759,10 @@ msgstr ""
 "          зашифрованный симметричным шифром\n"
 
 #, c-format
+msgid "Unknown critical signature notation: "
+msgstr "Неизвестное критическое замечание к подписи: "
+
+#, c-format
 msgid "subpacket of type %d has critical bit set\n"
 msgstr "в подпакете типа %d установлен критический бит\n"
 
@@ -5390,12 +5379,11 @@ msgstr "Замечание: ключ для подписей %s отозван\n
 
 #, c-format
 msgid "bad key signature from key %s: %s (0x%02x, 0x%x)\n"
-msgstr "плохая подпись ключом %s: %s (0x%02x 0x%x)\n"
+msgstr "плоÑ\85аÑ\8f Ð¿Ð¾Ð´Ð¿Ð¸Ñ\81Ñ\8c ÐºÐ»Ñ\8eÑ\87а ÐºÐ»Ñ\8eÑ\87ом %s: %s (0x%02x 0x%x)\n"
 
-#, fuzzy, c-format
-#| msgid "bad key signature from key %s: %s (0x%02x, 0x%x)\n"
+#, c-format
 msgid "bad data signature from key %s: %s (0x%02x, 0x%x)\n"
-msgstr "плохая подпись ключом %s: %s (0x%02x 0x%x)\n"
+msgstr "плоÑ\85аÑ\8f Ð¿Ð¾Ð´Ð¿Ð¸Ñ\81Ñ\8c Ð´Ð°Ð½Ð½Ñ\8bÑ\85 ÐºÐ»Ñ\8eÑ\87ом %s: %s (0x%02x 0x%x)\n"
 
 #, c-format
 msgid "assuming bad signature from key %s due to an unknown critical bit\n"
index cd98cc9..9e3594b 100644 (file)
@@ -964,7 +964,8 @@ pcsc_vendor_specific_init (int slot)
           else if (strstr (reader_table[slot].rdrname, "cyberJack")
                    || strstr (reader_table[slot].rdrname, "DIGIPASS")
                    || strstr (reader_table[slot].rdrname, "Gnuk")
-                   || strstr (reader_table[slot].rdrname, "KAAN"))
+                   || strstr (reader_table[slot].rdrname, "KAAN")
+                   || strstr (reader_table[slot].rdrname, "Trustica"))
             reader_table[slot].pinpad_varlen_supported = 1;
         }
 
@@ -1038,7 +1039,8 @@ pcsc_vendor_specific_init (int slot)
   else if (vendor == 0x0c4b /* Tested with Reiner cyberJack GO */
            || vendor == 0x1a44 /* Tested with Vasco DIGIPASS 920 */
            || vendor == 0x234b /* Tested with FSIJ Gnuk Token */
-           || vendor == 0x0d46 /* Tested with KAAN Advanced??? */)
+           || vendor == 0x0d46 /* Tested with KAAN Advanced??? */
+           || (vendor == 0x1fc9 && product == 0x81e6) /* Tested with Trustica Cryptoucan */)
     reader_table[slot].pinpad_varlen_supported = 1;
 
   return 0;
index f33a36c..ae40f01 100644 (file)
@@ -3387,6 +3387,12 @@ ccid_transceive_secure (ccid_driver_t handle,
       if (handle->id_product != CHERRY_ST2000)
         cherry_mode = 1;
       break;
+    case VENDOR_NXP:
+      if (handle->id_product == CRYPTOUCAN){
+        pininfo->maxlen = 25;
+        enable_varlen = 1;
+      }
+      break;
     default:
       if ((handle->id_vendor == VENDOR_GEMPC &&
            handle->id_product == GEMPC_PINPAD)
index b6da30c..c31c25f 100644 (file)
@@ -68,7 +68,8 @@ enum {
   VENDOR_REINER = 0x0c4b,
   VENDOR_KAAN   = 0x0d46,
   VENDOR_FSIJ   = 0x234b,
-  VENDOR_VASCO  = 0x1a44
+  VENDOR_VASCO  = 0x1a44,
+  VENDOR_NXP    = 0x1fc9,
 };
 
 
@@ -84,6 +85,7 @@ enum {
 #define GEMPC_CT30      0x3437
 #define VEGA_ALPHA      0x0008
 #define CYBERJACK_GO    0x0504
+#define CRYPTOUCAN      0x81e6
 
 #endif /*CCID_DRIVER_INCLUDE_USB_IDS*/