Merge branch 'seckey-sync-work' into master
authorWerner Koch <wk@gnupg.org>
Wed, 14 Nov 2018 12:37:41 +0000 (13:37 +0100)
committerWerner Koch <wk@gnupg.org>
Wed, 14 Nov 2018 12:37:41 +0000 (13:37 +0100)
--

170 files changed:
AUTHORS
Makefile.am
NEWS
agent/call-pinentry.c
agent/command-ssh.c
agent/command.c
agent/divert-scd.c
agent/gpg-agent.c
agent/keyformat.txt
agent/learncard.c
agent/protect.c
artwork/README
build-aux/speedo.mk
build-aux/texinfo.tex
common/argparse.c
common/audit.h
common/convert.c
common/dotlock.c
common/iobuf.c
common/mbox-util.c
common/mbox-util.h
common/mkerrors
common/mkerrtok
common/openpgp-oid.c
common/percent.c
common/sexp-parse.h
common/sexputil.c
common/simple-pwquery.c
common/ssh-utils.c
common/stringhelp.c
common/sysutils.c
common/t-exechelp.c
common/t-mbox-util.c
configure.ac
dirmngr/Makefile.am
dirmngr/cdb.h
dirmngr/cdblib.c
dirmngr/crlcache.c
dirmngr/dirmngr-status.h [new file with mode: 0644]
dirmngr/dirmngr.c
dirmngr/dirmngr.h
dirmngr/dirmngr_ldap.c
dirmngr/dns-stuff.c
dirmngr/dns-stuff.h
dirmngr/dns.c
dirmngr/domaininfo.c
dirmngr/http-ntbtls.c
dirmngr/http.c
dirmngr/http.h
dirmngr/ks-action.c
dirmngr/ks-engine-finger.c
dirmngr/ks-engine-hkp.c
dirmngr/ks-engine-http.c
dirmngr/ks-engine-ldap.c
dirmngr/ldap.c
dirmngr/misc.c
dirmngr/ocsp.c
dirmngr/server.c
dirmngr/t-dns-stuff.c
dirmngr/t-http.c
dirmngr/t-support.c [new file with mode: 0644]
dirmngr/workqueue.c
doc/DETAILS
doc/HACKING
doc/Notes
doc/dirmngr.texi
doc/faq.org
doc/gpg.texi
doc/tools.texi
doc/wks.texi
doc/yat2m.c
g10/Makefile.am
g10/armor.c
g10/build-packet.c
g10/call-agent.c
g10/call-agent.h
g10/call-dirmngr.c
g10/card-util.c
g10/cipher-aead.c
g10/cpr.c
g10/decrypt-data.c
g10/encrypt.c
g10/export.c
g10/filter.h
g10/getkey.c
g10/gpg.c
g10/gpgcompose.c
g10/gpgv.c
g10/import.c
g10/key-clean.c [new file with mode: 0644]
g10/key-clean.h [new file with mode: 0644]
g10/keydb.h
g10/keyedit.c
g10/keygen.c
g10/keylist.c
g10/keyserver.c
g10/mainproc.c
g10/misc.c
g10/options.h
g10/packet.h
g10/parse-packet.c
g10/pkclist.c
g10/pubkey-enc.c
g10/seskey.c
g10/sig-check.c
g10/sign.c
g10/skclist.c
g10/tdbio.c
g10/test-stubs.c
g10/tofu.c
g10/trust.c
g10/trustdb.c
g10/trustdb.h
g10/verify.c
g13/call-syshelp.c
g13/mountinfo.c
g13/runner.c
kbx/keybox-blob.c
kbx/keybox-errors.c
kbx/keybox-search-desc.h
kbx/keybox-search.c
kbx/mkerrors
m4/Makefile.am
m4/gpg-error.m4
m4/ksba.m4
m4/libassuan.m4
m4/libgcrypt.m4
m4/npth.m4
m4/ntbtls.m4
m4/tar-ustar.m4 [deleted file]
po/Makevars
po/POTFILES.in
scd/apdu.c
scd/apdu.h
scd/app-dinsig.c
scd/app-geldkarte.c
scd/app-openpgp.c
scd/app.c
scd/ccid-driver.c
scd/ccid-driver.h
scd/command.c
scd/iso7816.c
scd/scdaemon.c
scd/scdaemon.h
sm/call-dirmngr.c
sm/certchain.c
sm/certlist.c
sm/certreqgen-ui.c
sm/gpgsm.c
sm/gpgsm.h
sm/keydb.c
sm/minip12.c
sm/qualified.c
tests/asschk.c
tests/gpgscm/scheme.c
tools/Makefile.am
tools/gpg-check-pattern.c
tools/gpg-connect-agent.c
tools/gpg-wks-client.c
tools/gpg-wks-server.c
tools/gpg-wks.h
tools/gpg-zip.in [deleted file]
tools/gpgconf.c
tools/gpgtar.h
tools/mime-maker.c
tools/mime-parser.c
tools/no-libgcrypt.c
tools/rfc822parse.c
tools/rfc822parse.h
tools/wks-util.c

diff --git a/AUTHORS b/AUTHORS
index f43208a..d5d7814 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -193,6 +193,9 @@ Ineiev <ineiev@gnu.org>
 James Bottomley <James.Bottomley@HansenPartnership.com>
 2018-02-01:1517501629.3145.9.camel@HansenPartnership.com:
 
+Jiri Kerestes <jiri.kerestes@trustica.cz>
+2018-07-25:<d77cfcda-bbc3-0620-4e81-10dff33a94ca@trustica.cz>:
+
 Jonas Borgström <jonas@borgstrom.se>
 2013-08-29:521F1E7A.5080602@borgstrom.se:
 
@@ -205,6 +208,9 @@ Jussi Kivilinna <jussi.kivilinna@iki.fi>
 Kyle Butt <kylebutt@gmail.com>
 2013-05-29:CAAODAYLbCtqOG6msLLL0UTdASKWT6u2ptxsgUQ1JpusBESBoNQ@mail.gmail.com:
 
+Michael Haubenwallner <michael.haubenwallner@ssi-schaefer.com>
+2018-07-13:c397e637-f1ce-34f0-7e6a-df04a76e1c35@ssi-schaefer.com:
+
 Phil Pennock <phil.pennock@spodhuis.org>
 Phil Pennock <phil@pennock-tech.com>
 2017-01-19:20170119061225.GA26207@breadbox.private.spodhuis.org:
index 680fe1b..b59e9e3 100644 (file)
@@ -189,7 +189,7 @@ release:
         $(MAKE) -f  $(RELEASE_NAME)/build-aux/speedo.mk w32-release ;\
         echo "/* Build finished at $$(date -uIseconds) */" ;\
          echo "/*" ;\
-        echo " * Please run the final step interactivly:" ;\
+        echo " * Please run the final step interactively:" ;\
         echo " *   make sign-release" ;\
         echo " */" ;\
        ) 2>&1 | tee "$(RELEASE_NAME).buildlog"
diff --git a/NEWS b/NEWS
index 232d8be..245cc70 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,46 @@
 Noteworthy changes in version 2.3.0 (unreleased)
 ------------------------------------------------
 
+  Changes also found in 2.2.9:
+
+  * dirmngr: Fix recursive resolver mode and other bugs in the libdns
+    code.  [#3374,#3803,#3610]
+
+  * dirmngr: When using libgpg-error 1.32 or later a GnuPG build with
+    NTBTLS support (e.g. the standard Windows installer) does not
+    anymore block for dozens of seconds before returning data.
+
+  * gpg: Fix bug in --show-keys which actually imported revocation
+    certificates.  [#4017]
+
+  * gpg: Ignore too long user-ID and comment packets.  [#4022]
+
+  * gpg: Fix crash due to bad German translation.  Improved printf
+    format compile time check.
+
+  * gpg: Handle missing ISSUER sub packet gracefully in the presence of
+    the new ISSUER_FPR.  [#4046]
+
+  * gpg: Allow decryption using several passphrases in most cases.
+    [#3795,#4050]
+
+  * gpg: Command --show-keys now enables the list options
+    show-unusable-uids, show-unusable-subkeys, show-notations and
+    show-policy-urls by default.
+
+  * gpg: Command --show-keys now prints revocation certificates. [#4018]
+
+  * gpg: Add revocation reason to the "rev" and "rvs" records of the
+    option --with-colons.  [#1173]
+
+  * gpg: Export option export-clean does now remove certain expired
+    subkeys; export-minimal removes all expired subkeys.  [#3622]
+
+  * gpg: New "usage" property for the drop-subkey filters.  [#4019]
+
+  Release-info: https://dev.gnupg.org/T4036
+  See-also: gnupg-announce/2018q3/000427.html
+
   Changes also found in 2.2.8:
 
   * gpg: Decryption of messages not using the MDC mode will now lead
@@ -58,7 +98,7 @@ Noteworthy changes in version 2.3.0 (unreleased)
   * dirmngr: Fallback to CRL if no default OCSP responder is configured.
 
   * dirmngr: Implement CRL fetching via https.  Here a redirection to
-    http is explictly allowed.
+    http is explicitly allowed.
 
   * dirmngr: Make LDAP searching and CRL fetching work under Windows.
     This stopped working with 2.1.  [#3937]
@@ -285,6 +325,7 @@ Noteworthy changes in version 2.3.0 (unreleased)
   Version 2.2.6 (2018-04-09)
   Version 2.2.7 (2018-05-02)
   Version 2.2.8 (2018-06-08)
+  Version 2.2.9 (2018-07-12)
 
 
 Noteworthy changes in version 2.2.0 (2017-08-28)
@@ -918,7 +959,7 @@ Noteworthy changes in version 2.1.11 (2016-01-26)
 
  * gpg: Emit PROGRESS status lines during key generation.
 
- * gpg: Don't check for ambigious or non-matching key specification in
+ * gpg: Don't check for ambiguous or non-matching key specification in
    the config file or given to --encrypt-to.  This feature will return
    in 2.3.x.
 
@@ -945,7 +986,7 @@ Noteworthy changes in version 2.1.11 (2016-01-26)
  * dirmmgr: All configured keyservers are now searched.
 
  * dirmngr: Install CA certificate for hkps.pool.sks-keyservers.net.
-   Use this certiticate even if --hkp-cacert is not used.
+   Use this certificate even if --hkp-cacert is not used.
 
  * gpgtar: Add actual encryption code.  gpgtar does now fully replace
    gpg-zip.
@@ -979,7 +1020,7 @@ Noteworthy changes in version 2.1.10 (2015-12-04)
  * gpg: New option --only-sign-text-ids to exclude photo IDs from key
    signing.
 
- * gpg: Check for ambigious or non-matching key specification in the
+ * gpg: Check for ambiguous or non-matching key specification in the
    config file or given to --encrypt-to.
 
  * gpg: Show the used card reader with --card-status.
@@ -1269,7 +1310,7 @@ Noteworthy changes in version 2.1.1 (2014-12-16)
 
  * gpg: Fixed regression in --refresh-keys.
 
- * gpg: Fixed regresion in %g and %p codes for --sig-notation.
+ * gpg: Fixed regression in %g and %p codes for --sig-notation.
 
  * gpg: Fixed best matching hash algo detection for ECDSA and EdDSA.
 
@@ -1349,7 +1390,7 @@ Noteworthy changes in version 2.1.0 (2014-11-06)
 
  * gpg: Default keyring is now created with a .kbx suffix.
 
- * gpg: Add a shortcut to the key capabilies menu (e.g. "=e" sets the
+ * gpg: Add a shortcut to the key capabilities menu (e.g. "=e" sets the
    encryption capabilities).
 
  * gpg: Fixed obsolete options parsing.
@@ -1541,7 +1582,7 @@ Noteworthy changes in version 2.1.0 (2014-11-06)
  * scdaemon: Does not anymore block after changing a card (regression
    fix).
 
- * tools: gpg-connect-agent does now proberly display the help output
+ * tools: gpg-connect-agent does now properly display the help output
    for "SCD HELP" commands.
 
 
@@ -1666,7 +1707,7 @@ Noteworthy changes in version 2.0.13 (2009-09-04)
  * Add hack to the internal CCID driver to allow the use of some
    Omnikey based card readers with 2048 bit keys.
 
- * GPG now repeatly asks the user to insert the requested OpenPGP
+ * GPG now repeatedly asks the user to insert the requested OpenPGP
    card.  This can be disabled with --limit-card-insert-tries=1.
 
  * Minor bug fixes.
@@ -1792,7 +1833,7 @@ Noteworthy changes in version 2.0.9 (2008-03-26)
 
  * Extended the PKITS framework.
 
- * Fixed a bug in the ambigious name detection.
+ * Fixed a bug in the ambiguous name detection.
 
  * Fixed possible memory corruption while importing OpenPGP keys (bug
    introduced with 2.0.8). [CVE-2008-1530]
@@ -2342,7 +2383,7 @@ Noteworthy changes in version 1.9.2 (2003-11-17)
    command but from the menu provided by the new --card-edit command.
 
  * PINs are now properly cached and there are only 2 PINs visible.
-   The 3rd PIN (CHV2) is internally syncronized with the regular PIN.
+   The 3rd PIN (CHV2) is internally synchronized with the regular PIN.
 
  * All kind of other internal stuff.
 
@@ -3046,7 +3087,7 @@ Noteworthy changes in version 1.0.1 (1999-12-16)
     * Fixed some minor bugs and the problem with conventional encrypted
       packets which did use the gpg v3 partial length headers.
 
-    * Add Indonesian and Portugese translations.
+    * Add Indonesian and Portuguese translations.
 
     * Fixed a bug with symmetric-only encryption using the non-default 3DES.
       The option --emulate-3des-s2k-bug may be used to decrypt documents
@@ -3149,7 +3190,7 @@ Noteworthy changes in version 0.9.8 (1999-06-26)
 
     * New option --with-key-data to list the public key parameters.
       New option -N to insert notations and a --set-policy-url.
-      A couple of other options to allow reseting of options.
+      A couple of other options to allow resetting of options.
 
     * Better support for HPUX.
 
@@ -3628,7 +3669,7 @@ Noteworthy changes in version 0.2.19 (1998-05-29)
 Noteworthy changes in version 0.2.18 (1998-05-15)
 ------------------------------------
 
-    * Splitted cipher/random.c, add new option "--disable-dev-random"
+    * Split cipher/random.c, add new option "--disable-dev-random"
       to configure to support the development of a random source for
       other systems. Prepared sourcefiles rand-unix.c, rand-w32.c
       and rand-dummy.c (which is used to allow compilation on systems
index af4eb06..38c01e2 100644 (file)
@@ -98,11 +98,15 @@ void
 initialize_module_call_pinentry (void)
 {
   static int initialized;
+  int err;
 
   if (!initialized)
     {
-      if (npth_mutex_init (&entry_lock, NULL))
-        initialized = 1;
+      err = npth_mutex_init (&entry_lock, NULL);
+      if (err)
+       log_fatal ("error initializing mutex: %s\n", strerror (err));
+
+      initialized = 1;
     }
 }
 
@@ -497,14 +501,16 @@ start_pinentry (ctrl_t ctrl)
 
   {
     /* Provide a few default strings for use by the pinentries.  This
-       may help a pinentry to avoid implementing localization code.  */
+     * may help a pinentry to avoid implementing localization code.
+     * Note that gpg-agent has been set to utf-8 so that the strings
+     * are in the expected encoding.  */
     static const struct { const char *key, *value; int what; } tbl[] = {
-      /* TRANSLATORS: These are labels for buttons etc used in
-         Pinentries.  An underscore indicates that the next letter
-         should be used as an accelerator.  Double the underscore for
-         a literal one.  The actual to be translated text starts after
-         the second vertical bar.  Note that gpg-agent has been set to
-         utf-8 so that the strings are in the expected encoding.  */
+      /* TRANSLATORS: These are labels for buttons etc as used in
+       * Pinentries.  In your translation copy the text before the
+       * second vertical bar verbatim; translate only the following
+       * text.  An underscore indicates that the next letter should be
+       * used as an accelerator.  Double the underscore to have
+       * pinentry display a literal underscore.   */
       { "ok",     N_("|pinentry-label|_OK") },
       { "cancel", N_("|pinentry-label|_Cancel") },
       { "yes",    N_("|pinentry-label|_Yes") },
@@ -1537,14 +1543,6 @@ agent_popup_message_stop (ctrl_t ctrl)
       TerminateProcess (process, 1);
     }
 #else
-  else if (pid && ((rc=waitpid (pid, NULL, WNOHANG))==-1 || (rc == pid)) )
-    { /* The daemon already died.  No need to send a kill.  However
-         because we already waited for the process, we need to tell
-         assuan that it should not wait again (done by
-         unlock_pinentry). */
-      if (rc == pid)
-        assuan_set_flag (entry_ctx, ASSUAN_NO_WAITPID, 1);
-    }
   else if (pid > 0)
     kill (pid, SIGINT);
 #endif
index df63ed7..8a41505 100644 (file)
@@ -2751,7 +2751,7 @@ data_hash (unsigned char *data, size_t data_n,
    allow the use of signature algorithms that implement the hashing
    internally (e.g. Ed25519).  On success the created signature is
    stored in ssh format at R_SIG and it's size at R_SIGLEN; the caller
-   must use es_free to releaase this memory.  */
+   must use es_free to release this memory.  */
 static gpg_error_t
 data_sign (ctrl_t ctrl, ssh_key_type_spec_t *spec,
            const void *hash, size_t hashlen,
@@ -3249,9 +3249,10 @@ ssh_handler_add_identity (ctrl_t ctrl, estream_t request, estream_t response)
   while (1)
     {
       err = stream_read_byte (request, &b);
-      if (gpg_err_code (err) == GPG_ERR_EOF)
-       {
-         err = 0;
+      if (err)
+        {
+          if (gpg_err_code (err) == GPG_ERR_EOF)
+            err = 0;
          break;
        }
 
@@ -3625,7 +3626,7 @@ static void
 get_client_info (int fd, struct peer_info_s *out)
 {
   pid_t client_pid = (pid_t)(-1);
-  uid_t client_uid = (uid_t)-1;
+  int client_uid = -1;
 
 #ifdef SO_PEERCRED
   {
@@ -3640,10 +3641,10 @@ get_client_info (int fd, struct peer_info_s *out)
       {
 #if defined (HAVE_STRUCT_SOCKPEERCRED_PID) || defined (HAVE_STRUCT_UCRED_PID)
         client_pid = cr.pid;
-        client_uid = cr.uid;
+        client_uid = (int)cr.uid;
 #elif defined (HAVE_STRUCT_UCRED_CR_PID)
         client_pid = cr.cr_pid;
-        client_pid = cr.cr_uid;
+        client_uid = (int)cr.cr_uid;
 #else
 #error "Unknown SO_PEERCRED struct"
 #endif
@@ -3660,7 +3661,7 @@ get_client_info (int fd, struct peer_info_s *out)
       len = sizeof (struct xucred);
 
       if (!getsockopt (fd, SOL_LOCAL, LOCAL_PEERCRED, &cr, &len))
-       client_uid = cr.cr_uid;
+       client_uid = (int)cr.cr_uid;
     }
 #endif
   }
@@ -3670,8 +3671,10 @@ get_client_info (int fd, struct peer_info_s *out)
     socklen_t unpl = sizeof unp;
 
     if (getsockopt (fd, 0, LOCAL_PEEREID, &unp, &unpl) != -1)
-      client_pid = unp.unp_pid;
-      client_uid = unp.unp_euid;
+      {
+        client_pid = unp.unp_pid;
+        client_uid = (int)unp.unp_euid;
+      }
   }
 #elif defined (HAVE_GETPEERUCRED)
   {
@@ -3680,7 +3683,7 @@ get_client_info (int fd, struct peer_info_s *out)
     if (getpeerucred (fd, &ucred) != -1)
       {
         client_pid = ucred_getpid (ucred);
-       client_uid = ucred_geteuid (ucred);
+       client_uid = (int)ucred_geteuid (ucred);
         ucred_free (ucred);
       }
   }
@@ -3689,7 +3692,7 @@ get_client_info (int fd, struct peer_info_s *out)
 #endif
 
   out->pid = (client_pid == (pid_t)(-1)? 0 : (unsigned long)client_pid);
-  out->uid = (int)client_uid;
+  out->uid = client_uid;
 }
 
 
index 925d1f7..7fbf1de 100644 (file)
@@ -887,7 +887,7 @@ cmd_genkey (assuan_context_t ctx, char *line)
   ctrl_t ctrl = assuan_get_pointer (ctx);
   int rc;
   int no_protection;
-  unsigned char *value;
+  unsigned char *value = NULL;
   size_t valuelen;
   unsigned char *newpasswd = NULL;
   membuf_t outbuf;
@@ -3588,8 +3588,13 @@ start_command_handler (ctrl_t ctrl, gnupg_fd_t listen_fd, gnupg_fd_t fd)
         }
       else
         {
+#ifdef HAVE_W32_SYSTEM
+          pid = assuan_get_pid (ctx);
+          ctrl->client_uid = -1;
+#else
           pid = client_creds->pid;
           ctrl->client_uid = client_creds->uid;
+#endif
         }
       ctrl->client_pid = (pid == ASSUAN_INVALID_PID)? 0 : (unsigned long)pid;
       ctrl->server_local->connect_from_self = (pid == getpid ());
index b85b490..b978154 100644 (file)
@@ -195,7 +195,7 @@ has_percent0A_suffix (const char *string)
    string with the passphrase, the buffer may optionally be padded
    with arbitrary characters.
 
-   If DESC_TEXT is not NULL it can be used as further informtion shown
+   If DESC_TEXT is not NULL it can be used as further information shown
    atop of the INFO message.
 
    INFO gets displayed as part of a generic string.  However if the
@@ -278,25 +278,47 @@ getpin_cb (void *opaque, const char *desc_text, const char *info,
         {
           if (info)
             {
-              char *desc, *desc2;
+              char *desc;
+              const char *desc2;
 
-              if ( asprintf (&desc,
-                             L_("%s%%0A%%0AUse the reader's pinpad for input."),
-                             info) < 0 )
-                rc = gpg_error_from_syserror ();
+              if (!strcmp (info, "--ack"))
+                {
+                  desc2 = L_("Push ACK button on card/token.");
+
+                  if (desc_text)
+                    {
+                      desc = strconcat (desc_text,
+                                        has_percent0A_suffix (desc_text)
+                                        ? "%0A" : "%0A%0A",
+                                        desc2, NULL);
+                      desc2 = NULL;
+                    }
+                  else
+                    desc = NULL;
+                }
               else
                 {
-                  /* Prepend DESC_TEXT to INFO.  */
+                  desc2 = NULL;
+
                   if (desc_text)
-                    desc2 = strconcat (desc_text,
-                                       has_percent0A_suffix (desc_text)
-                                       ? "%0A" : "%0A%0A",
-                                       desc, NULL);
+                    desc = strconcat (desc_text,
+                                      has_percent0A_suffix (desc_text)
+                                      ? "%0A" : "%0A%0A",
+                                      info, "%0A%0A",
+                                      L_("Use the reader's pinpad for input."),
+                                      NULL);
                   else
-                    desc2 = NULL;
+                    desc = strconcat (info, "%0A%0A",
+                                      L_("Use the reader's pinpad for input."),
+                                      NULL);
+                }
+
+              if (!desc2 && !desc)
+                rc = gpg_error_from_syserror ();
+              else
+                {
                   rc = agent_popup_message_start (ctrl,
                                                   desc2? desc2:desc, NULL);
-                  xfree (desc2);
                   xfree (desc);
                 }
             }
index 1fdc94d..911064c 100644 (file)
@@ -851,7 +851,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
 
     case oLogFile:
       if (!reread)
-        return 0; /* not handeld */
+        return 0; /* not handled */
       if (!current_logfile || !pargs->r.ret_str
           || strcmp (current_logfile, pargs->r.ret_str))
         {
@@ -1768,7 +1768,7 @@ main (int argc, char **argv )
 
           /* Unless we are running with a program given on the command
            * line we can assume that the inotify things works and thus
-           * we can avoid tye regular stat calls.  */
+           * we can avoid the regular stat calls.  */
           if (!argc)
             reliable_homedir_inotify = 1;
         }
@@ -2108,7 +2108,7 @@ get_agent_scd_notify_event (void)
                                  GetCurrentProcess(), &h2,
                                  EVENT_MODIFY_STATE|SYNCHRONIZE, TRUE, 0))
         {
-          log_error ("setting syncronize for scd notify event failed: %s\n",
+          log_error ("setting synchronize for scd notify event failed: %s\n",
                      w32_strerror (-1) );
           CloseHandle (h);
         }
index 2e48b34..c7426db 100644 (file)
@@ -234,7 +234,7 @@ The currently defined protection modes are:
      (csum n)
      (protection PROTTYPE PROTALGO IV S2KMODE S2KHASH S2KSALT S2KCOUNT)))
 
-  Note that the public key paramaters in SKEY are duplicated and
+  Note that the public key parameters in SKEY are duplicated and
   should be identical to their copies in the standard parameter
   elements.  Here is an example of an entire protected private key
   using this format:
@@ -359,8 +359,8 @@ KEY_1 to KEY_N are unique identifiers for the shared secret, for
 example an URI.  In case this information should be kept confidential
 as well, they may not appear in the unprotected part; however they are
 mandatory in the encrypted_octet_string.  The list of keywords is
-optional.  The oder of the "key" lists and the order of the "value"
-lists mut match, that is the first "key"-list is associated with the
+optional.  The order of the "key" lists and the order of the "value"
+lists must match, that is the first "key"-list is associated with the
 first "value" list in the encrypted_octet_string.
 
 The protection mode etc. is identical to the protection mode as
index abe1dd0..f3219ed 100644 (file)
@@ -40,7 +40,7 @@ struct keypair_info_s
   char hexgrip[1];   /* The keygrip (i.e. a hash over the public key
                         parameters) formatted as a hex string.
                         Allocated somewhat large to also act as
-                        memeory for the above ID field. */
+                        memory for the above ID field. */
 };
 typedef struct keypair_info_s *KEYPAIR_INFO;
 
index 16ae715..c7bd30b 100644 (file)
@@ -1109,7 +1109,7 @@ agent_unprotect (ctrl_t ctrl,
   if (!protect_info[infidx].algo)
     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
 
-  /* See wether we have a protected-at timestamp.  */
+  /* See whether we have a protected-at timestamp.  */
   protect_list = s;  /* Save for later.  */
   if (protected_at)
     {
index 13b8653..068bdea 100644 (file)
@@ -14,3 +14,11 @@ gnupg-logo-new.ai
 gnupg-favicon-1.ico  Icons for the website (rectangular)
 gnupg-favicon-2.ico  (round)
 
+
+The above GnuPG logos are Copyright (c) 2006 g10 Code GmbH, and are
+released under the terms of the GNU General Public License, version 3
+or any later version, or, at your option, of the Creative Commons
+Attribution-ShareAlike 4.0 International License.
+
+We would appreciate that you make a logo image a link to
+https://gnupg.org/ if you use it on a web page.
index d9b4a75..d0f97f3 100644 (file)
@@ -157,8 +157,9 @@ INST_NAME=gnupg-w32
 # Use this to override the installaion directory for native builds.
 INSTALL_PREFIX=none
 
-# The Authenticode key used to sign the Windows installer
+# The Authenticode key and cert chain used to sign the Windows installer
 AUTHENTICODE_KEY=${HOME}/.gnupg/g10code-authenticode-key.p12
+AUTHENTICODE_CERTS=${HOME}/.gnupg/g10code-authenticode-certs.pem
 
 
 # Directory names.
@@ -520,12 +521,12 @@ endif
 # The LDFLAGS is needed for -lintl for glib.
 ifeq ($(WITH_GUI),1)
 speedo_pkg_gpgme_configure = \
-       --enable-static --enable-w32-glib --disable-w32-qt \
+       --enable-static --enable-w32-glib  \
        --with-gpg-error-prefix=$(idir) \
        LDFLAGS=-L$(idir)/lib
 else
 speedo_pkg_gpgme_configure = \
-       --disable-static --disable-w32-glib --disable-w32-qt \
+       --disable-static --disable-w32-glib \
        --with-gpg-error-prefix=$(idir) \
        LDFLAGS=-L$(idir)/lib
 endif
@@ -970,7 +971,7 @@ else
 endif
        @touch $(stampdir)/stamp-$(1)-01-configure
 
-# Note that unpack has no 64 bit version becuase it is just the source.
+# Note that unpack has no 64 bit version because it is just the source.
 # Fixme: We should use templates to create the standard and w64
 # version of these rules.
 $(stampdir)/stamp-w64-$(1)-01-configure: $(stampdir)/stamp-$(1)-00-unpack
@@ -1142,7 +1143,7 @@ all-speedo: $(stampdir)/stamp-final
 
 report-speedo: $(addprefix report-,$(speedo_build_list))
 
-# Just to check if we catched all stamps.
+# Just to check if we caught all stamps.
 clean-stamps:
        $(RM) -fR $(stampdir)
 
@@ -1266,8 +1267,11 @@ sign-installer:
         echo "speedo:  * Signing installer" ;\
         echo "speedo:  * Key: $(AUTHENTICODE_KEY)";\
         echo "speedo:  */" ;\
-        osslsigncode sign -pkcs12 $(AUTHENTICODE_KEY) -askpass \
-            -h sha256 -in "PLAY/inst/$$exefile" -out "../../$$exefile" ;\
+        osslsigncode sign -certs $(AUTHENTICODE_CERTS)\
+            -pkcs12 $(AUTHENTICODE_KEY) -askpass \
+            -ts "http://timestamp.globalsign.com/scripts/timstamp.dll" \
+            -h sha256 -n GnuPG -i https://gnupg.org \
+           -in "PLAY/inst/$$exefile" -out "../../$$exefile" ;\
         exefile="../../$$exefile" ;\
         $(call MKSWDB_commands,$${exefile},$${reldate}); \
         echo "speedo: /*" ;\
@@ -1283,7 +1287,7 @@ endif
 
 
 #
-# Check availibility of standard tools
+# Check availability of standard tools
 #
 check-tools:
 
index 5a17f97..9e11848 100644 (file)
@@ -3,7 +3,7 @@
 % Load plain if necessary, i.e., if running under initex.
 \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
 %
-\def\texinfoversion{2007-05-03.09}
+\def\texinfoversion{2018-10-25.16}
 %
 % Copyright (C) 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
 % 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
@@ -4598,7 +4598,7 @@ end
 \chardef\maxseclevel = 3
 %
 % A numbered section within an unnumbered changes to unnumbered too.
-% To achive this, remember the "biggest" unnum. sec. we are currently in:
+% To achieve this, remember the "biggest" unnum. sec. we are currently in:
 \chardef\unmlevel = \maxseclevel
 %
 % Trace whether the current chapter is an appendix or not:
index 331998b..db0b7e0 100644 (file)
@@ -408,7 +408,7 @@ static void
 store_alias( ARGPARSE_ARGS *arg, char *name, char *value )
 {
     /* TODO: replace this dummy function with a rea one
-     * and fix the probelms IRIX has with (ALIAS_DEV)arg..
+     * and fix the problems IRIX has with (ALIAS_DEV)arg..
      * used as lvalue
      */
   (void)arg;
@@ -439,7 +439,7 @@ ignore_invalid_option_p (ARGPARSE_ARGS *arg, const char *keyword)
 
 /* Add the keywords up to the next LF to the list of to be ignored
    options.  After returning FP will either be at EOF or the next
-   character read wll be the first of a new line.  The function
+   character read will be the first of a new line.  The function
    returns 0 on success or true on malloc failure.  */
 static int
 ignore_invalid_option_add (ARGPARSE_ARGS *arg, FILE *fp)
@@ -1280,7 +1280,7 @@ long_opt_strlen( ARGPARSE_OPTS *o )
  *    this option
  *  - a description,ine which starts with a '@' and is followed by
  *    any other characters is printed as is; this may be used for examples
- *    ans such.
+ *    and such.
  *  - A description which starts with a '|' outputs the string between this
  *    bar and the next one as arguments of the long option.
  */
index 4ef2645..05f3953 100644 (file)
@@ -185,7 +185,7 @@ typedef enum
        if no real recipient has been given.  */
 
     AUDIT_SESSION_KEY,     /* string */
-    /* Mark the creation or availibility of the session key.  The
+    /* Mark the creation or availability of the session key.  The
        parameter is the algorithm ID.  */
 
     AUDIT_ENCRYPTED_TO,   /* cert, err */
index 6d03adc..40fb4ee 100644 (file)
@@ -177,7 +177,7 @@ bin2hexcolon (const void *buffer, size_t length, char *stringbuf)
    string or a white space character.  The function makes sure that
    the resulting string in BUFFER is terminated by a Nul byte.  Note
    that the returned string may include embedded Nul bytes; the extra
-   Nul byte at the end is used to make sure tha the result can always
+   Nul byte at the end is used to make sure that the result can always
    be used as a C-string.
 
    BUFSIZE is the available length of BUFFER; if the converted result
index 5227bb6..1bc31d8 100644 (file)
    you pass (0) instead of (-1) the function does not wait in case the
    file is already locked but returns -1 and sets ERRNO to EACCES.
    Any other positive value for the second parameter is considered a
-   timeout valuie in milliseconds.
+   timeout value in milliseconds.
 
    To release the lock you call:
 
index 02c9b49..5eeba8f 100644 (file)
@@ -68,8 +68,8 @@
 
 /*-- End configurable part.  --*/
 
-/* The size of the iobuffers.  This can be chnages using the
- * iobuf_set_buffer_size fucntion.  */
+/* The size of the iobuffers.  This can be changed using the
+ * iobuf_set_buffer_size function.  */
 static unsigned int iobuf_buffer_size = DEFAULT_IOBUF_BUFFER_SIZE;
 
 
@@ -878,9 +878,9 @@ block_filter (void *opaque, int control, iobuf_t chain, byte * buffer,
                    }
                  else if (c == 255)
                    {
-                     a->size = (size_t)iobuf_get (chain) << 24;
-                     a->size |= iobuf_get (chain) << 16;
-                     a->size |= iobuf_get (chain) << 8;
+                     a->size = iobuf_get_noeof (chain) << 24;
+                     a->size |= iobuf_get_noeof (chain) << 16;
+                     a->size |= iobuf_get_noeof (chain) << 8;
                      if ((c = iobuf_get (chain)) == -1)
                        {
                          log_error ("block_filter: invalid 4 byte length\n");
@@ -2610,12 +2610,50 @@ iobuf_read_line (iobuf_t a, byte ** addr_of_buffer,
     }
 
   p = buffer;
-  while ((c = iobuf_get (a)) != -1)
+  while (1)
     {
-      *p++ = c;
-      nbytes++;
-      if (c == '\n')
-       break;
+      if (!a->nofast && a->d.start < a->d.len && nbytes < length - 1)
+       /* Fast path for finding '\n' by using standard C library's optimized
+          memchr.  */
+       {
+         unsigned size = a->d.len - a->d.start;
+         byte *newline_pos;
+
+         if (size > length - 1 - nbytes)
+           size = length - 1 - nbytes;
+
+         newline_pos = memchr (a->d.buf + a->d.start, '\n', size);
+         if (newline_pos)
+           {
+             /* Found newline, copy buffer and return. */
+             size = (newline_pos - (a->d.buf + a->d.start)) + 1;
+             memcpy (p, a->d.buf + a->d.start, size);
+             p += size;
+             nbytes += size;
+             a->d.start += size;
+             a->nbytes += size;
+             break;
+           }
+         else
+           {
+             /* No newline, copy buffer and continue. */
+             memcpy (p, a->d.buf + a->d.start, size);
+             p += size;
+             nbytes += size;
+             a->d.start += size;
+             a->nbytes += size;
+           }
+       }
+      else
+       {
+         c = iobuf_readbyte (a);
+         if (c == -1)
+           break;
+         *p++ = c;
+         nbytes++;
+         if (c == '\n')
+           break;
+       }
 
       if (nbytes == length - 1)
        /* We don't have enough space to add a \n and a \0.  Increase
index c1f05b8..a9086a3 100644 (file)
@@ -173,11 +173,12 @@ is_valid_mailbox (const char *name)
 
 
 /* Return the mailbox (local-part@domain) form a standard user id.
-   All plain ASCII characters in the result are converted to
-   lowercase.  Caller must free the result.  Returns NULL if no valid
-   mailbox was found (or we are out of memory). */
+ * All plain ASCII characters in the result are converted to
+ * lowercase.  If SUBADDRESS is 1, '+' denoted sub-addresses are not
+ * included in the result.  Caller must free the result.  Returns NULL
+ * if no valid mailbox was found (or we are out of memory). */
 char *
-mailbox_from_userid (const char *userid)
+mailbox_from_userid (const char *userid, int subaddress)
 {
   const char *s, *s_end;
   size_t len;
@@ -226,6 +227,29 @@ mailbox_from_userid (const char *userid)
   else
     errno = EINVAL;
 
+  if (result && subaddress == 1)
+    {
+      char *atsign, *plus;
+
+      if ((atsign = strchr (result, '@')))
+        {
+          /* We consider a subaddress only if there is a single '+'
+           * in the local part and the '+' is not the first or last
+           * character.  */
+          *atsign = 0;
+          if ((plus = strchr (result, '+'))
+              && !strchr (plus+1, '+')
+              && result != plus
+              && plus[1] )
+            {
+              *atsign = '@';
+              memmove (plus, atsign, strlen (atsign)+1);
+            }
+          else
+            *atsign = '@';
+        }
+    }
+
   return result? ascii_strlwr (result): NULL;
 }
 
@@ -241,3 +265,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..10ff2c4 100644 (file)
@@ -22,8 +22,9 @@
 int has_invalid_email_chars (const void *buffer, size_t length);
 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);
+char *mailbox_from_userid (const char *userid, int subaddress);
 int is_valid_user_id (const char *uid);
+int is_valid_domain_name (const char *string);
 
 
 #endif /*GNUPG_COMMON_MBOX_UTIL_H*/
index 138d3c1..2a6960a 100755 (executable)
@@ -30,7 +30,7 @@ cat <<EOF
  * gnupg_strerror:
  * @err:  Error code
  *
- * This function returns a textual representaion of the given
+ * This function returns a textual representation of the given
  * errorcode. If this is an unknown value, a string with the value
  * is returned (Beware: it is hold in a static buffer).
  *
index e631072..49c10e5 100755 (executable)
@@ -26,7 +26,7 @@ cat <<EOF
  * gnupg_error_token:
  * @err:  Error code
  *
- * This function returns a textual representaion of the given
+ * This function returns a textual representation of the given
  * errorcode. If this is an unknown value, a static string is returned.
  * This function differs from gnupg_strerror that it yields the string
  * representation of the macro which is never subject to i18n.
index d800e7d..86885e0 100644 (file)
@@ -184,7 +184,7 @@ openpgp_oid_from_str (const char *string, gcry_mpi_t *r_mpi)
 }
 
 
-/* Return a malloced string represenation of the OID in the opaque MPI
+/* Return a malloced string representation of the OID in the opaque MPI
    A.  In case of an error NULL is returned and ERRNO is set.  */
 char *
 openpgp_oid_to_str (gcry_mpi_t a)
@@ -221,7 +221,7 @@ openpgp_oid_to_str (gcry_mpi_t a)
 
   /* To calculate the length of the string we can safely assume an
      upper limit of 3 decimal characters per byte.  Two extra bytes
-     account for the special first octect */
+     account for the special first octet */
   string = p = xtrymalloc (length*(1+3)+2+1);
   if (!string)
     return NULL;
index eeb026f..7b81768 100644 (file)
@@ -42,7 +42,7 @@
    failure.
 
    Note that we also escape the quote character to work around a bug
-   in the mingw32 runtime which does not correcty handle command line
+   in the mingw32 runtime which does not correctly handle command line
    quoting.  We correctly double the quote mark when calling a program
    (i.e. gpg-protect-tool), but the pre-main code does not notice the
    double quote as an escaped quote.  We do this also on POSIX systems
index 4f77f14..0403d65 100644 (file)
@@ -105,7 +105,7 @@ smatch (unsigned char const **buf, size_t buflen, const char *token)
 }
 
 /* Format VALUE for use as the length indicatior of an S-expression.
-   The caller needs to provide a buffer HELP_BUFFER wth a length of
+   The caller needs to provide a buffer HELP_BUFFER with a length of
    HELP_BUFLEN.  The return value is a pointer into HELP_BUFFER with
    the formatted length string.  The colon and a trailing nul are
    appended.  HELP_BUFLEN must be at least 3 - a more useful value is
index f30790a..02e52d0 100644 (file)
@@ -303,7 +303,7 @@ make_simple_sexp_from_hexstr (const char *line, size_t *nscanned)
   for (; n > 1; n -=2, s += 2)
     *p++ = xtoi_2 (s);
   *p++ = ')';
-  *p = 0; /* (Not really neaded.) */
+  *p = 0; /* (Not really needed.) */
 
   return buf;
 }
index e7f4af3..7688c84 100644 (file)
@@ -75,7 +75,7 @@
 
 
 /* Name of the socket to be used.  This is a kludge to keep on using
-   the existsing code despite that we only support a standard socket.  */
+   the existing code despite that we only support a standard socket.  */
 static char *default_gpg_agent_info;
 
 
@@ -246,6 +246,7 @@ agent_open (assuan_context_t *ctx)
 #ifdef SPWQ_USE_LOGGING
       log_error (_("no gpg-agent running in this session\n"));
 #endif
+      *ctx = NULL;
       return SPWQ_NO_AGENT;
     }
 
index 38d6e8a..013b28e 100644 (file)
@@ -247,7 +247,7 @@ get_fingerprint (gcry_sexp_t key, int algo,
           goto leave;
         }
 
-      strncpy (*r_fpr, algo_name, strlen (algo_name));
+      memcpy (*r_fpr, algo_name, strlen (algo_name));
       fpr = (char *) *r_fpr + strlen (algo_name);
       *fpr++ = ':';
 
index 0abac8a..751e571 100644 (file)
@@ -1400,7 +1400,7 @@ parse_version_number (const char *s, int *number)
 
 
 /* This function breaks up the complete string-representation of the
-   version number S, which is of the following struture: <major
+   version number S, which is of the following structure: <major
    number>.<minor number>[.<micro number>]<patch level>.  The major,
    minor, and micro number components will be stored in *MAJOR, *MINOR
    and *MICRO.  If MICRO is not given 0 is used instead.
index 55a7ee9..0a3dc2e 100644 (file)
@@ -551,14 +551,13 @@ gnupg_tmpfile (void)
 void
 gnupg_reopen_std (const char *pgmname)
 {
-#if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
-  struct stat statbuf;
+#ifdef F_GETFD
   int did_stdin = 0;
   int did_stdout = 0;
   int did_stderr = 0;
   FILE *complain;
 
-  if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
+  if (fcntl (STDIN_FILENO, F_GETFD) == -1 && errno ==EBADF)
     {
       if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
        did_stdin = 1;
@@ -566,7 +565,7 @@ gnupg_reopen_std (const char *pgmname)
        did_stdin = 2;
     }
 
-  if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
+  if (fcntl (STDOUT_FILENO, F_GETFD) == -1 && errno == EBADF)
     {
       if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
        did_stdout = 1;
@@ -574,7 +573,7 @@ gnupg_reopen_std (const char *pgmname)
        did_stdout = 2;
     }
 
-  if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
+  if (fcntl (STDERR_FILENO, F_GETFD)==-1 && errno==EBADF)
     {
       if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
        did_stderr = 1;
@@ -607,7 +606,7 @@ gnupg_reopen_std (const char *pgmname)
 
   if (did_stdin == 2 || did_stdout == 2 || did_stderr == 2)
     exit (3);
-#else /* !(HAVE_STAT && !HAVE_W32_SYSTEM) */
+#else /* !F_GETFD */
   (void)pgmname;
 #endif
 }
index cf967fc..3bf082b 100644 (file)
@@ -131,7 +131,7 @@ test_close_all_fds (void)
   free (array);
 
   /* Now let's check the realloc we use.  We do this and the next
-     tests only if we are allowed to open enought descriptors.  */
+     tests only if we are allowed to open enough descriptors.  */
   if (get_max_fds () > 32)
     {
       int except[] = { 20, 23, 24, -1 };
index 979d4b3..ae717f9 100644 (file)
@@ -25,6 +25,9 @@
 #include "util.h"
 #include "mbox-util.h"
 
+#define PGM "t-mbox-util"
+
+
 #define pass()  do { ; } while(0)
 #define fail(a)  do { fprintf (stderr, "%s:%d: test %d failed\n",\
                                __FILE__,__LINE__, (a));          \
                     } while(0)
 
 
+static int verbose;
+static int debug;
+
+
+static void
+run_mbox_test (void)
+{
+  static struct
+  {
+    const char *userid;
+    const char *mbox;
+  } testtbl[] =
+    {
+      { "Werner Koch <wk@gnupg.org>", "wk@gnupg.org" },
+      { "<wk@gnupg.org>", "wk@gnupg.org" },
+      { "wk@gnupg.org", "wk@gnupg.org" },
+      { "wk@gnupg.org ", NULL },
+      { " wk@gnupg.org", NULL },
+      { "Werner Koch (test) <wk@gnupg.org>", "wk@gnupg.org" },
+      { "Werner Koch <wk@gnupg.org> (test)", "wk@gnupg.org" },
+      { "Werner Koch <wk@gnupg.org (test)", NULL },
+      { "Werner Koch <wk@gnupg.org >", NULL },
+      { "Werner Koch <wk@gnupg.org", NULL },
+      { "", NULL },
+      { "@", NULL },
+      { "bar <>", NULL },
+      { "<foo@example.org>", "foo@example.org" },
+      { "<foo.@example.org>", "foo.@example.org" },
+      { "<.foo.@example.org>", ".foo.@example.org" },
+      { "<foo..@example.org>", "foo..@example.org" },
+      { "<foo..bar@example.org>", "foo..bar@example.org" },
+      { "<foo@example.org.>", NULL },
+      { "<foo@example..org>", NULL },
+      { "<foo@.>", NULL },
+      { "<@example.org>", NULL },
+      { "<foo@@example.org>", NULL },
+      { "<@foo@example.org>", NULL },
+      { "<foo@example.org> ()", "foo@example.org" },
+      { "<fo()o@example.org> ()", "fo()o@example.org" },
+      { "<fo()o@example.org> ()", "fo()o@example.org" },
+      { "fo()o@example.org", NULL},
+      { "Mr. Foo <foo@example.org><bar@example.net>", "foo@example.org"},
+      { NULL, NULL }
+    };
+  int idx;
+
+  for (idx=0; testtbl[idx].userid; idx++)
+    {
+      char *mbox = mailbox_from_userid (testtbl[idx].userid, 0);
+
+      if (!testtbl[idx].mbox)
+        {
+          if (mbox)
+            fail (idx);
+        }
+      else if (!mbox)
+        fail (idx);
+      else if (strcmp (mbox, testtbl[idx].mbox))
+        fail (idx);
+
+      xfree (mbox);
+    }
+}
+
+
 static void
-run_test (void)
+run_mbox_no_sub_test (void)
 {
   static struct
   {
@@ -41,6 +109,7 @@ run_test (void)
     const char *mbox;
   } testtbl[] =
     {
+      { "foo+bar@example.org", "foo@example.org" },
       { "Werner Koch <wk@gnupg.org>", "wk@gnupg.org" },
       { "<wk@gnupg.org>", "wk@gnupg.org" },
       { "wk@gnupg.org", "wk@gnupg.org" },
@@ -70,13 +139,30 @@ run_test (void)
       { "<fo()o@example.org> ()", "fo()o@example.org" },
       { "fo()o@example.org", NULL},
       { "Mr. Foo <foo@example.org><bar@example.net>", "foo@example.org"},
+      { "foo+bar@example.org", "foo@example.org" },
+      { "foo++bar@example.org", "foo++bar@example.org" },
+      { "foo++@example.org", "foo++@example.org" },
+      { "foo+@example.org", "foo+@example.org" },
+      { "+foo@example.org", "+foo@example.org" },
+      { "++foo@example.org", "++foo@example.org" },
+      { "+foo+@example.org", "+foo+@example.org" },
+      { "+@example.org", "+@example.org" },
+      { "++@example.org", "++@example.org" },
+      { "foo+b@example.org", "foo@example.org" },
+      { "foo+ba@example.org", "foo@example.org" },
+      { "foo+bar@example.org", "foo@example.org" },
+      { "foo+barb@example.org", "foo@example.org" },
+      { "foo+barba@example.org", "foo@example.org" },
+      { "f+b@example.org", "f@example.org" },
+      { "fo+b@example.org", "fo@example.org" },
+
       { NULL, NULL }
     };
   int idx;
 
   for (idx=0; testtbl[idx].userid; idx++)
     {
-      char *mbox = mailbox_from_userid (testtbl[idx].userid);
+      char *mbox = mailbox_from_userid (testtbl[idx].userid, 1);
 
       if (!testtbl[idx].mbox)
         {
@@ -93,13 +179,155 @@ 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);
+    }
+}
+
+
+static void
+run_filter (int no_sub)
+{
+  char buf[4096];
+  int c;
+  char *p, *mbox;
+  unsigned int count1 = 0;
+  unsigned int count2 = 0;
+
+  while (fgets (buf, sizeof buf, stdin))
+    {
+      p = strchr (buf, '\n');
+      if (p)
+        *p = 0;
+      else
+        {
+          /* Skip to the end of the line.  */
+          while ((c = getc (stdin)) != EOF && c != '\n')
+            ;
+        }
+      count1++;
+      trim_spaces (buf);
+      mbox = mailbox_from_userid (buf, no_sub);
+      if (mbox)
+        {
+          printf ("%s\n", mbox);
+          xfree (mbox);
+          count2++;
+        }
+    }
+  if (verbose)
+    fprintf (stderr, PGM ": lines=%u mboxes=%u\n", count1, count2);
+}
+
+
 int
 main (int argc, char **argv)
 {
-  (void)argc;
-  (void)argv;
+  int last_argc = -1;
+  int opt_filter = 0;
+  int opt_no_sub = 0;
 
-  run_test ();
+  if (argc)
+    { argc--; argv++; }
+  while (argc && last_argc != argc )
+    {
+      last_argc = argc;
+      if (!strcmp (*argv, "--"))
+        {
+          argc--; argv++;
+          break;
+        }
+      else if (!strcmp (*argv, "--help"))
+        {
+          fputs ("usage: " PGM " [FILE]\n"
+                 "Options:\n"
+                 "  --verbose         Print timings etc.\n"
+                 "  --debug           Flyswatter\n"
+                 "  --filter          Filter mboxes from input lines\n"
+                 "  --no-sub          Ignore '+'-sub-addresses\n"
+                 , stdout);
+          exit (0);
+        }
+      else if (!strcmp (*argv, "--verbose"))
+        {
+          verbose++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--debug"))
+        {
+          verbose += 2;
+          debug++;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--filter"))
+        {
+          opt_filter = 1;
+          argc--; argv++;
+        }
+      else if (!strcmp (*argv, "--no-sub"))
+        {
+          opt_no_sub = 1;
+          argc--; argv++;
+        }
+      else if (!strncmp (*argv, "--", 2))
+        {
+          fprintf (stderr, PGM ": unknown option '%s'\n", *argv);
+          exit (1);
+        }
+    }
+
+  if (opt_filter)
+    run_filter (opt_no_sub);
+  else
+    {
+      run_mbox_test ();
+      run_mbox_no_sub_test ();
+      run_dns_test ();
+    }
 
   return 0;
 }
index 03f3af9..9d3eb41 100644 (file)
@@ -129,7 +129,10 @@ GNUPG_BUILD_PROGRAM(symcryptrun, no)
 # We use gpgtar to unpack test data, hence we always build it.  If the
 # user opts out, we simply don't install it.
 GNUPG_BUILD_PROGRAM(gpgtar, yes)
-GNUPG_BUILD_PROGRAM(wks-tools, no)
+# We also install the gpg-wks-server tool by default but disable it
+# later for platforms where it can't be build.
+GNUPG_BUILD_PROGRAM(wks-tools, yes)
+
 
 AC_SUBST(PACKAGE)
 AC_SUBST(PACKAGE_GT)
@@ -623,7 +626,6 @@ AC_ARG_VAR(YAT2M, [tool to convert texi to man pages])
 AM_CONDITIONAL(HAVE_YAT2M, test -n "$ac_cv_path_YAT2M")
 AC_ISC_POSIX
 AC_SYS_LARGEFILE
-GNUPG_CHECK_USTAR
 
 
 # We need to compile and run a program on the build machine.  A
@@ -682,6 +684,7 @@ case "${host}" in
         try_gettext="no"
        use_simple_gettext=yes
        mmap_needed=no
+        build_wks_tools=no
         ;;
     i?86-emx-os2 | i?86-*-os2*emx )
         # OS/2 with the EMX environment
@@ -689,6 +692,7 @@ case "${host}" in
         AC_DEFINE(HAVE_DRIVE_LETTERS)
         have_dosish_system=yes
         try_gettext="no"
+        build_wks_tools=no
         ;;
 
     i?86-*-msdosdjgpp*)
@@ -697,6 +701,7 @@ case "${host}" in
         AC_DEFINE(HAVE_DRIVE_LETTERS)
         have_dosish_system=yes
         try_gettext="no"
+        build_wks_tools=no
         ;;
 
     *-*-hpux*)
@@ -727,6 +732,7 @@ case "${host}" in
         # Android is fully utf-8 and we do not want to use iconv to
         # keeps things simple
         require_iconv=no
+        build_wks_tools=no
         ;;
     *-apple-darwin*)
         AC_DEFINE(_DARWIN_C_SOURCE, 900000L,
@@ -1482,7 +1488,7 @@ if test "$use_regex" = yes ; then
     use_regex=no
   else
     if test x"$cross_compiling" = xyes; then
-      AC_MSG_WARN([cross compiling; assuming regexp libray is not broken])
+      AC_MSG_WARN([cross compiling; assuming regexp library is not broken])
     else
       AC_CACHE_CHECK([whether your system's regexp library is broken],
        [gnupg_cv_regex_broken],
@@ -2044,7 +2050,6 @@ agent/Makefile
 scd/Makefile
 g13/Makefile
 dirmngr/Makefile
-tools/gpg-zip
 tools/Makefile
 doc/Makefile
 tests/Makefile
index 43f59bd..22b8c1a 100644 (file)
@@ -62,7 +62,7 @@ dirmngr_SOURCES = dirmngr.c dirmngr.h server.c crlcache.c crlfetch.c  \
        domaininfo.c \
        workqueue.c \
        loadswdb.c \
-       cdb.h cdblib.c misc.c dirmngr-err.h  \
+       cdb.h cdblib.c misc.c dirmngr-err.h dirmngr-status.h \
        ocsp.c ocsp.h validate.c validate.h  \
        dns-stuff.c dns-stuff.h \
        http.c http.h http-common.c http-common.h http-ntbtls.c \
@@ -111,7 +111,7 @@ dirmngr_client_LDADD = $(libcommon) \
 dirmngr_client_LDFLAGS = $(extra_bin_ldflags)
 
 
-t_common_src = t-support.h
+t_common_src = t-support.h t-support.c
 if USE_LIBDNS
 t_common_src += dns.c dns.h
 endif
index 0c0d270..5d46f69 100644 (file)
@@ -85,7 +85,7 @@ int cdb_make_put(struct cdb_make *cdbmp,
                 const void *key, cdbi_t klen,
                 const void *val, cdbi_t vlen,
                 int flag);
-#define CDB_PUT_ADD    0       /* add unconditionnaly, like cdb_make_add() */
+#define CDB_PUT_ADD    0       /* add unconditionally, like cdb_make_add() */
 #define CDB_PUT_REPLACE        1       /* replace: do not place to index OLD record */
 #define CDB_PUT_INSERT 2       /* add only if not already exists */
 #define CDB_PUT_WARN   3       /* add unconditionally but ret. 1 if exists */
index 827399f..c401263 100644 (file)
@@ -19,7 +19,7 @@
    length, meaning that corresponding hash table is empty.
 
    Right after toc section, data section follows without any
-   alingment.  It consists of series of records, each is a key length,
+   alignment.  It consists of series of records, each is a key length,
    value (data) length, key and value.  Again, key and value length
    are 4-byte unsigned integers.  Each next record follows previous
    without any special alignment.
@@ -52,7 +52,7 @@
    beginning of a table).  When hash value in question is found in
    hash table, look to key of corresponding record, comparing it with
    key in question.  If them of the same length and equals to each
-   other, then record is found, overwise, repeat with next hash table
+   other, then record is found, otherwise, repeat with next hash table
    slot.  Note that there may be several records with the same key.
 */
 
@@ -245,7 +245,7 @@ cdb_find(struct cdb *cdbp, const void *key, cdbi_t klen)
   pos = cdb_unpack(htp);       /* htab position */
   if (n > (cdbp->cdb_fsize >> 3) /* overflow of httodo ? */
       || pos > cdbp->cdb_fsize /* htab start within file ? */
-      || httodo > cdbp->cdb_fsize - pos) /* entrie htab within file ? */
+      || httodo > cdbp->cdb_fsize - pos) /* htab entry within file ? */
   {
     gpg_err_set_errno (EPROTO);
     return -1;
index fbe3bee..c9e5ca6 100644 (file)
@@ -1250,13 +1250,15 @@ crl_cache_deinit (void)
 }
 
 
-/* Delete the cache from disk. Return 0 on success.*/
+/* Delete the cache from disk and memory. Return 0 on success.*/
 int
 crl_cache_flush (void)
 {
   int rc;
 
+  crl_cache_deinit ();
   rc = cleanup_cache_dir (0)? -1 : 0;
+  crl_cache_init ();
 
   return rc;
 }
@@ -1782,7 +1784,7 @@ crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
             ksba_sexp_t keyid;
 
             /* We need to look for the issuer only after having read
-               all items.  The issuer itselfs comes before the items
+               all items.  The issuer itself comes before the items
                but the optional authorityKeyIdentifier comes after the
                items. */
             err = ksba_crl_get_issuer (crl, &crlissuer);
@@ -1907,7 +1909,7 @@ get_crl_number (ksba_crl_t crl)
 
 
 /* Return the authorityKeyIdentifier or NULL if it is not available.
-   The issuer name may consists of several parts - they are delimted by
+   The issuer name may consists of several parts - they are delimited by
    0x01. */
 static char *
 get_auth_key_id (ksba_crl_t crl, char **serialno)
diff --git a/dirmngr/dirmngr-status.h b/dirmngr/dirmngr-status.h
new file mode 100644 (file)
index 0000000..2c3fd78
--- /dev/null
@@ -0,0 +1,39 @@
+/* dirmngr-status.h - Status code helper functions for dirmnmgr.
+ * Copyright (C) 2004, 2014, 2015, 2018 g10 Code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0+
+ */
+
+/* We keep them separate so that we don't always need to include the
+ * entire dirmngr.h */
+
+#ifndef DIRMNGR_STATUS_H
+#define DIRMNGR_STATUS_H
+
+
+/*-- server.c --*/
+gpg_error_t dirmngr_status (ctrl_t ctrl, const char *keyword, ...);
+gpg_error_t dirmngr_status_help (ctrl_t ctrl, const char *text);
+gpg_error_t dirmngr_status_helpf (ctrl_t ctrl, const char *format,
+                                  ...) GPGRT_ATTR_PRINTF(2,3);
+gpg_error_t dirmngr_status_printf (ctrl_t ctrl, const char *keyword,
+                                   const char *format,
+                                   ...) GPGRT_ATTR_PRINTF(3,4);
+
+
+#endif /* DIRMNGR_STATUS_H */
index 6fdfe36..80fb134 100644 (file)
@@ -338,7 +338,7 @@ static int active_connections;
  * thread to run background network tasks.  */
 static int network_activity_seen;
 
-/* A list of filenames registred with --hkp-cacert.  */
+/* A list of filenames registered with --hkp-cacert.  */
 static strlist_t hkp_cacert_filenames;
 
 
@@ -411,7 +411,7 @@ my_strusage( int level )
 
 /* Callback from libksba to hash a provided buffer.  Our current
    implementation does only allow SHA-1 for hashing. This may be
-   extended by mapping the name, testing for algorithm availibility
+   extended by mapping the name, testing for algorithm availability
    and adjust the length checks accordingly. */
 static gpg_error_t
 my_ksba_hash_buffer (void *arg, const char *oid,
@@ -520,7 +520,7 @@ set_tor_mode (void)
 {
   if (dirmngr_use_tor ())
     {
-      /* Enable Tor mode and when called again force a new curcuit
+      /* Enable Tor mode and when called again force a new circuit
        * (e.g. on SIGHUP).  */
       enable_dns_tormode (1);
       if (assuan_sock_set_flag (ASSUAN_INVALID_FD, "tor-mode", 1))
@@ -752,7 +752,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
 }
 
 
-/* This fucntion is called after option parsing to adjust some values
+/* This function is called after option parsing to adjust some values
  * and call option setup functions.  */
 static void
 post_option_parsing (void)
@@ -1143,6 +1143,7 @@ main (int argc, char **argv)
       thread_init ();
       cert_cache_init (hkp_cacert_filenames);
       crl_cache_init ();
+      ks_hkp_init ();
       http_register_netactivity_cb (netactivity_action);
       start_command_handler (ASSUAN_INVALID_FD, 0);
       shutdown_reaper ();
@@ -1178,6 +1179,7 @@ main (int argc, char **argv)
       thread_init ();
       cert_cache_init (hkp_cacert_filenames);
       crl_cache_init ();
+      ks_hkp_init ();
       http_register_netactivity_cb (netactivity_action);
       handle_connections (3);
       shutdown_reaper ();
@@ -1399,6 +1401,7 @@ main (int argc, char **argv)
       thread_init ();
       cert_cache_init (hkp_cacert_filenames);
       crl_cache_init ();
+      ks_hkp_init ();
       http_register_netactivity_cb (netactivity_action);
       handle_connections (fd);
       shutdown_reaper ();
@@ -1421,6 +1424,7 @@ main (int argc, char **argv)
       thread_init ();
       cert_cache_init (hkp_cacert_filenames);
       crl_cache_init ();
+      ks_hkp_init ();
       if (!argc)
         rc = crl_cache_load (&ctrlbuf, NULL);
       else
@@ -1444,6 +1448,7 @@ main (int argc, char **argv)
       thread_init ();
       cert_cache_init (hkp_cacert_filenames);
       crl_cache_init ();
+      ks_hkp_init ();
       rc = crl_fetch (&ctrlbuf, argv[0], &reader);
       if (rc)
         log_error (_("fetching CRL from '%s' failed: %s\n"),
index 5189f93..9c26c09 100644 (file)
@@ -36,6 +36,7 @@
 #include "../common/sysutils.h" /* (gnupg_fd_t) */
 #include "../common/asshelp.h"  /* (assuan_context_t) */
 #include "../common/i18n.h"
+#include "dirmngr-status.h"
 #include "http.h"     /* (parsed_uri_t) */
 
 /* This objects keeps information about a particular LDAP server and
@@ -217,7 +218,7 @@ int dirmngr_use_tor (void);
 /*-- Various housekeeping functions.  --*/
 void ks_hkp_housekeeping (time_t curtime);
 void ks_hkp_reload (void);
-
+void ks_hkp_init (void);
 
 /*-- server.c --*/
 ldap_server_t get_ldapservers_from_ctrl (ctrl_t ctrl);
@@ -229,13 +230,6 @@ gpg_error_t get_istrusted_from_client (ctrl_t ctrl, const char *hexfpr);
 int dirmngr_assuan_log_monitor (assuan_context_t ctx, unsigned int cat,
                                 const char *msg);
 void start_command_handler (gnupg_fd_t fd, unsigned int session_id);
-gpg_error_t dirmngr_status (ctrl_t ctrl, const char *keyword, ...);
-gpg_error_t dirmngr_status_help (ctrl_t ctrl, const char *text);
-gpg_error_t dirmngr_status_helpf (ctrl_t ctrl, const char *format,
-                                  ...) GPGRT_ATTR_PRINTF(2,3);
-gpg_error_t dirmngr_status_printf (ctrl_t ctrl, const char *keyword,
-                                   const char *format,
-                                   ...) GPGRT_ATTR_PRINTF(3,4);
 gpg_error_t dirmngr_tick (ctrl_t ctrl);
 
 /*-- http-ntbtls.c --*/
index 8452c3b..dd7e4bd 100644 (file)
@@ -417,9 +417,9 @@ set_timeout (my_opt_t myopt)
           sec_attr.nLength = sizeof sec_attr;
           sec_attr.bInheritHandle = FALSE;
 
-          /* Create a manual resetable timer.  */
+          /* Create a manual resettable timer.  */
           timer = CreateWaitableTimer (NULL, TRUE, NULL);
-          /* Intially set the timer.  */
+          /* Initially set the timer.  */
           SetWaitableTimer (timer, &due_time, 0, NULL, NULL, 0);
 
           if (CreateThread (&sec_attr, 0, alarm_thread, timer, 0, &tid))
index ffac816..7aa07c7 100644 (file)
@@ -73,6 +73,7 @@
 #include "./dirmngr-err.h"
 #include "../common/util.h"
 #include "../common/host2net.h"
+#include "dirmngr-status.h"
 #include "dns-stuff.h"
 
 #ifdef USE_NPTH
@@ -150,7 +151,7 @@ static char tor_socks_password[20];
 
 
 #ifdef USE_LIBDNS
-/* Libdns gobal data.  */
+/* Libdns global data.  */
 struct libdns_s
 {
   struct dns_resolv_conf *resolv_conf;
@@ -433,12 +434,13 @@ resolv_conf_changed_p (void)
 /* Initialize libdns.  Returns 0 on success; prints a diagnostic and
  * returns an error code on failure.  */
 static gpg_error_t
-libdns_init (void)
+libdns_init (ctrl_t ctrl)
 {
   gpg_error_t err;
   struct libdns_s ld;
   int derr;
   char *cfgstr = NULL;
+  const char *fname = NULL;
 
   if (libdns.resolv_conf)
     return 0; /* Already initialized.  */
@@ -532,7 +534,6 @@ libdns_init (void)
       xfree (ninfo);
 
 #else /* Unix */
-      const char *fname;
 
       fname = RESOLV_CONF_NAME;
       resolv_conf_changed_p (); /* Reset timestamp.  */
@@ -622,6 +623,7 @@ libdns_init (void)
     {
       err = libdns_error_to_gpg_error (derr);
       log_error ("failed to load DNS hints: %s\n", gpg_strerror (err));
+      fname = "[dns hints]";
       goto leave;
     }
 
@@ -632,6 +634,14 @@ libdns_init (void)
     log_debug ("dns: libdns initialized%s\n", tor_mode?" (tor mode)":"");
 
  leave:
+  if (!fname)
+    fname = cfgstr;
+  if (err && fname)
+    dirmngr_status_printf (ctrl, "WARNING",
+                           "dns_config_problem %u"
+                           " error accessing '%s': %s <%s>",
+                           err, fname, gpg_strerror (err), gpg_strsource (err));
+
   xfree (cfgstr);
   return err;
 }
@@ -686,7 +696,7 @@ reload_dns_stuff (int force)
  * failure an error code is returned and NULL stored at R_RES.
  */
 static gpg_error_t
-libdns_res_open (struct dns_resolver **r_res)
+libdns_res_open (ctrl_t ctrl, struct dns_resolver **r_res)
 {
   gpg_error_t err;
   struct dns_resolver *res;
@@ -708,7 +718,7 @@ libdns_res_open (struct dns_resolver **r_res)
       libdns_deinit ();
     }
 
-  err = libdns_init ();
+  err = libdns_init (ctrl);
   if (err)
     return err;
 
@@ -790,7 +800,7 @@ libdns_res_wait (struct dns_resolver *res)
 
 #ifdef USE_LIBDNS
 static gpg_error_t
-resolve_name_libdns (const char *name, unsigned short port,
+resolve_name_libdns (ctrl_t ctrl, const char *name, unsigned short port,
                      int want_family, int want_socktype,
                      dns_addrinfo_t *r_dai, char **r_canonname)
 {
@@ -823,7 +833,7 @@ resolve_name_libdns (const char *name, unsigned short port,
       portstr = portstr_;
     }
 
-  err = libdns_res_open (&res);
+  err = libdns_res_open (ctrl, &res);
   if (err)
     goto leave;
 
@@ -935,7 +945,7 @@ resolve_name_libdns (const char *name, unsigned short port,
 
 /* Resolve a name using the standard system function.  */
 static gpg_error_t
-resolve_name_standard (const char *name, unsigned short port,
+resolve_name_standard (ctrl_t ctrl, const char *name, unsigned short port,
                        int want_family, int want_socktype,
                        dns_addrinfo_t *r_dai, char **r_canonname)
 {
@@ -981,7 +991,7 @@ resolve_name_standard (const char *name, unsigned short port,
              CNAME redirection again.  */
           char *cname;
 
-          if (get_dns_cname (name, &cname))
+          if (get_dns_cname (ctrl, name, &cname))
             goto leave; /* Still no success.  */
 
           ret = getaddrinfo (cname, *portstr? portstr : NULL, &hints, &aibuf);
@@ -1046,18 +1056,19 @@ resolve_name_standard (const char *name, unsigned short port,
 
 
 /* This a wrapper around getaddrinfo with slightly different semantics.
-   NAME is the name to resolve.
-   PORT is the requested port or 0.
-   WANT_FAMILY is either 0 (AF_UNSPEC), AF_INET6, or AF_INET4.
-   WANT_SOCKETTYPE is either SOCK_STREAM or SOCK_DGRAM.
-
-   On success the result is stored in a linked list with the head
-   stored at the address R_AI; the caller must call gpg_addrinfo_free
-   on this.  If R_CANONNAME is not NULL the official name of the host
-   is stored there as a malloced string; if that name is not available
-   NULL is stored.  */
+ * NAME is the name to resolve.
+ * PORT is the requested port or 0.
+ * WANT_FAMILY is either 0 (AF_UNSPEC), AF_INET6, or AF_INET4.
+ * WANT_SOCKETTYPE is either 0 for any socket type
+ *                 or SOCK_STREAM or SOCK_DGRAM.
+ *
+ * On success the result is stored in a linked list with the head
+ * stored at the address R_AI; the caller must call free_dns_addrinfo
+ * on this.  If R_CANONNAME is not NULL the official name of the host
+ * is stored there as a malloced string; if that name is not available
+ * NULL is stored.  */
 gpg_error_t
-resolve_dns_name (const char *name, unsigned short port,
+resolve_dns_name (ctrl_t ctrl, const char *name, unsigned short port,
                   int want_family, int want_socktype,
                   dns_addrinfo_t *r_ai, char **r_canonname)
 {
@@ -1066,15 +1077,15 @@ resolve_dns_name (const char *name, unsigned short port,
 #ifdef USE_LIBDNS
   if (!standard_resolver)
     {
-      err = resolve_name_libdns (name, port, want_family, want_socktype,
+      err = resolve_name_libdns (ctrl, name, port, want_family, want_socktype,
                                   r_ai, r_canonname);
       if (err && libdns_switch_port_p (err))
-        err = resolve_name_libdns (name, port, want_family, want_socktype,
+        err = resolve_name_libdns (ctrl, name, port, want_family, want_socktype,
                                    r_ai, r_canonname);
     }
   else
 #endif /*USE_LIBDNS*/
-    err = resolve_name_standard (name, port, want_family, want_socktype,
+    err = resolve_name_standard (ctrl, name, port, want_family, want_socktype,
                                  r_ai, r_canonname);
   if (opt_debug)
     log_debug ("dns: resolve_dns_name(%s): %s\n", name, gpg_strerror (err));
@@ -1085,7 +1096,8 @@ resolve_dns_name (const char *name, unsigned short port,
 #ifdef USE_LIBDNS
 /* Resolve an address using libdns.  */
 static gpg_error_t
-resolve_addr_libdns (const struct sockaddr_storage *addr, int addrlen,
+resolve_addr_libdns (ctrl_t ctrl,
+                     const struct sockaddr_storage *addr, int addrlen,
                      unsigned int flags, char **r_name)
 {
   gpg_error_t err;
@@ -1117,7 +1129,7 @@ resolve_addr_libdns (const struct sockaddr_storage *addr, int addrlen,
     goto leave;
 
 
-  err = libdns_res_open (&res);
+  err = libdns_res_open (ctrl, &res);
   if (err)
     goto leave;
 
@@ -1281,7 +1293,8 @@ resolve_addr_standard (const struct sockaddr_storage *addr, int addrlen,
 
 /* A wrapper around getnameinfo.  */
 gpg_error_t
-resolve_dns_addr (const struct sockaddr_storage *addr, int addrlen,
+resolve_dns_addr (ctrl_t ctrl,
+                  const struct sockaddr_storage *addr, int addrlen,
                   unsigned int flags, char **r_name)
 {
   gpg_error_t err;
@@ -1290,9 +1303,9 @@ resolve_dns_addr (const struct sockaddr_storage *addr, int addrlen,
   /* Note that we divert to the standard resolver for NUMERICHOST.  */
   if (!standard_resolver && !(flags & DNS_NUMERICHOST))
     {
-      err = resolve_addr_libdns (addr, addrlen, flags, r_name);
+      err = resolve_addr_libdns (ctrl, addr, addrlen, flags, r_name);
       if (err && libdns_switch_port_p (err))
-        err = resolve_addr_libdns (addr, addrlen, flags, r_name);
+        err = resolve_addr_libdns (ctrl, addr, addrlen, flags, r_name);
     }
   else
 #endif /*USE_LIBDNS*/
@@ -1390,7 +1403,7 @@ is_onion_address (const char *name)
 /* libdns version of get_dns_cert.  */
 #ifdef USE_LIBDNS
 static gpg_error_t
-get_dns_cert_libdns (const char *name, int want_certtype,
+get_dns_cert_libdns (ctrl_t ctrl, const char *name, int want_certtype,
                      void **r_key, size_t *r_keylen,
                      unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
 {
@@ -1410,7 +1423,7 @@ get_dns_cert_libdns (const char *name, int want_certtype,
            : (want_certtype - DNS_CERTTYPE_RRBASE));
 
 
-  err = libdns_res_open (&res);
+  err = libdns_res_open (ctrl, &res);
   if (err)
     goto leave;
 
@@ -1776,7 +1789,7 @@ get_dns_cert_standard (const char *name, int want_certtype,
    supported certtypes only records with this certtype are considered
    and the first found is returned.  (R_KEY,R_KEYLEN) are optional. */
 gpg_error_t
-get_dns_cert (const char *name, int want_certtype,
+get_dns_cert (ctrl_t ctrl, const char *name, int want_certtype,
               void **r_key, size_t *r_keylen,
               unsigned char **r_fpr, size_t *r_fprlen, char **r_url)
 {
@@ -1793,10 +1806,10 @@ get_dns_cert (const char *name, int want_certtype,
 #ifdef USE_LIBDNS
   if (!standard_resolver)
     {
-      err = get_dns_cert_libdns (name, want_certtype, r_key, r_keylen,
+      err = get_dns_cert_libdns (ctrl, name, want_certtype, r_key, r_keylen,
                                  r_fpr, r_fprlen, r_url);
       if (err && libdns_switch_port_p (err))
-        err = get_dns_cert_libdns (name, want_certtype, r_key, r_keylen,
+        err = get_dns_cert_libdns (ctrl, name, want_certtype, r_key, r_keylen,
                                    r_fpr, r_fprlen, r_url);
     }
   else
@@ -1828,7 +1841,8 @@ priosort(const void *a,const void *b)
  * R_COUNT.  */
 #ifdef USE_LIBDNS
 static gpg_error_t
-getsrv_libdns (const char *name, struct srventry **list, unsigned int *r_count)
+getsrv_libdns (ctrl_t ctrl,
+               const char *name, struct srventry **list, unsigned int *r_count)
 {
   gpg_error_t err;
   struct dns_resolver *res = NULL;
@@ -1839,7 +1853,7 @@ getsrv_libdns (const char *name, struct srventry **list, unsigned int *r_count)
   int derr;
   unsigned int srvcount = 0;
 
-  err = libdns_res_open (&res);
+  err = libdns_res_open (ctrl, &res);
   if (err)
     goto leave;
 
@@ -2058,7 +2072,8 @@ getsrv_standard (const char *name,
  * we do not return NONAME but simply store 0 at R_COUNT.  On error an
  * error code is returned and 0 stored at R_COUNT.  */
 gpg_error_t
-get_dns_srv (const char *name, const char *service, const char *proto,
+get_dns_srv (ctrl_t ctrl,
+             const char *name, const char *service, const char *proto,
              struct srventry **list, unsigned int *r_count)
 {
   gpg_error_t err;
@@ -2087,9 +2102,9 @@ get_dns_srv (const char *name, const char *service, const char *proto,
 #ifdef USE_LIBDNS
   if (!standard_resolver)
     {
-      err = getsrv_libdns (name, list, &srvcount);
+      err = getsrv_libdns (ctrl, name, list, &srvcount);
       if (err && libdns_switch_port_p (err))
-        err = getsrv_libdns (name, list, &srvcount);
+        err = getsrv_libdns (ctrl, name, list, &srvcount);
     }
   else
 #endif /*USE_LIBDNS*/
@@ -2194,7 +2209,7 @@ get_dns_srv (const char *name, const char *service, const char *proto,
 #ifdef USE_LIBDNS
 /* libdns version of get_dns_cname.  */
 gpg_error_t
-get_dns_cname_libdns (const char *name, char **r_cname)
+get_dns_cname_libdns (ctrl_t ctrl, const char *name, char **r_cname)
 {
   gpg_error_t err;
   struct dns_resolver *res;
@@ -2202,7 +2217,7 @@ get_dns_cname_libdns (const char *name, char **r_cname)
   struct dns_cname cname;
   int derr;
 
-  err = libdns_res_open (&res);
+  err = libdns_res_open (ctrl, &res);
   if (err)
     goto leave;
 
@@ -2347,7 +2362,7 @@ get_dns_cname_standard (const char *name, char **r_cname)
 
 
 gpg_error_t
-get_dns_cname (const char *name, char **r_cname)
+get_dns_cname (ctrl_t ctrl, const char *name, char **r_cname)
 {
   gpg_error_t err;
 
@@ -2356,9 +2371,9 @@ get_dns_cname (const char *name, char **r_cname)
 #ifdef USE_LIBDNS
   if (!standard_resolver)
     {
-      err = get_dns_cname_libdns (name, r_cname);
+      err = get_dns_cname_libdns (ctrl, name, r_cname);
       if (err && libdns_switch_port_p (err))
-        err = get_dns_cname_libdns (name, r_cname);
+        err = get_dns_cname_libdns (ctrl, name, r_cname);
       return err;
     }
 #endif /*USE_LIBDNS*/
index 612b2e5..06a4312 100644 (file)
@@ -137,12 +137,14 @@ void reload_dns_stuff (int force);
 void free_dns_addrinfo (dns_addrinfo_t ai);
 
 /* Function similar to getaddrinfo.  */
-gpg_error_t resolve_dns_name (const char *name, unsigned short port,
+gpg_error_t resolve_dns_name (ctrl_t ctrl,
+                              const char *name, unsigned short port,
                               int want_family, int want_socktype,
                               dns_addrinfo_t *r_dai, char **r_canonname);
 
 /* Function similar to getnameinfo.  */
-gpg_error_t resolve_dns_addr (const struct sockaddr_storage *addr, int addrlen,
+gpg_error_t resolve_dns_addr (ctrl_t ctrl,
+                              const struct sockaddr_storage *addr, int addrlen,
                               unsigned int flags, char **r_name);
 
 /* Return true if NAME is a numerical IP address.  */
@@ -152,16 +154,18 @@ int is_ip_address (const char *name);
 int is_onion_address (const char *name);
 
 /* Get the canonical name for NAME.  */
-gpg_error_t get_dns_cname (const char *name, char **r_cname);
+gpg_error_t get_dns_cname (ctrl_t ctrl, const char *name, char **r_cname);
 
 /* Return a CERT record or an arbitrary RR.  */
-gpg_error_t get_dns_cert (const char *name, int want_certtype,
+gpg_error_t get_dns_cert (ctrl_t ctrl,
+                          const char *name, int want_certtype,
                           void **r_key, size_t *r_keylen,
                           unsigned char **r_fpr, size_t *r_fprlen,
                           char **r_url);
 
 /* Return an array of SRV records.  */
-gpg_error_t get_dns_srv (const char *name,
+gpg_error_t get_dns_srv (ctrl_t ctrl,
+                         const char *name,
                          const char *service, const char *proto,
                          struct srventry **list, unsigned int *r_count);
 
index 77f83f4..596e81f 100644 (file)
@@ -1832,7 +1832,7 @@ static void dns_p_free(struct dns_packet *P) {
 } /* dns_p_free() */
 
 
-/* convience routine to free any existing packet before storing new packet */
+/* convenience routine to free any existing packet before storing new packet */
 static struct dns_packet *dns_p_setptr(struct dns_packet **dst, struct dns_packet *src) {
        dns_p_free(*dst);
 
@@ -7634,7 +7634,7 @@ retry:
                        goto udp_connect_retry;
                } else if (error == ECONNREFUSED)
                        /* Error for previous socket operation may
-                          be reserverd asynchronously. */
+                          be reserverd(?) asynchronously. */
                        goto udp_connect_retry;
 
                if (error)
index a2effff..f6263b0 100644 (file)
@@ -119,7 +119,7 @@ domaininfo_print_stats (void)
 }
 
 
-/* Return true if DOMAIN definitely does not support WKD.  Noet that
+/* Return true if DOMAIN definitely does not support WKD.  Note that
  * DOMAIN is expected to be lowercase.  */
 int
 domaininfo_is_wkd_not_supported (const char *domain)
index ed4cdd4..924b8b2 100644 (file)
@@ -55,7 +55,7 @@ gnupg_http_tls_verify_cb (void *opaque,
   log_assert (ctrl && ctrl->magic == SERVER_CONTROL_MAGIC);
   log_assert (!ntbtls_check_context (tls));
 
-  /* Get the peer's certs fron ntbtls.  */
+  /* Get the peer's certs from ntbtls.  */
   for (idx = 0;
        (cert = ntbtls_x509_get_peer_cert (tls, idx)); idx++)
     {
index 049aefc..5fb7eed 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999, 2001, 2002, 2003, 2004, 2006, 2009, 2010,
  *               2011 Free Software Foundation, Inc.
  * Copyright (C) 2014 Werner Koch
- * Copyright (C) 2015-2017 g10 Code GmbH
+ * Copyright (C) 2015-2018 g10 Code GmbH
  *
  * This file is part of GnuPG.
  *
@@ -152,14 +152,15 @@ static int remove_escapes (char *string);
 static int insert_escapes (char *buffer, const char *string,
                            const char *special);
 static uri_tuple_t parse_tuple (char *string);
-static gpg_error_t send_request (http_t hd, const char *httphost,
+static gpg_error_t send_request (ctrl_t ctrl, http_t hd, const char *httphost,
                                  const char *auth,const char *proxy,
                                 const char *srvtag, unsigned int timeout,
                                  strlist_t headers);
 static char *build_rel_path (parsed_uri_t uri);
 static gpg_error_t parse_response (http_t hd);
 
-static gpg_error_t connect_server (const char *server, unsigned short port,
+static gpg_error_t connect_server (ctrl_t ctrl,
+                                   const char *server, unsigned short port,
                                    unsigned int flags, const char *srvtag,
                                    unsigned int timeout, assuan_fd_t *r_sock);
 static gpgrt_ssize_t read_server (assuan_fd_t sock, void *buffer, size_t size);
@@ -937,7 +938,7 @@ http_session_set_timeout (http_session_t sess, unsigned int timeout)
    If HTTPHOST is not NULL it is used for the Host header instead of a
    Host header derived from the URL. */
 gpg_error_t
-http_open (http_t *r_hd, http_req_t reqtype, const char *url,
+http_open (ctrl_t ctrl, http_t *r_hd, http_req_t reqtype, const char *url,
            const char *httphost,
            const char *auth, unsigned int flags, const char *proxy,
            http_session_t session, const char *srvtag, strlist_t headers)
@@ -961,7 +962,7 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
 
   err = parse_uri (&hd->uri, url, 0, !!(flags & HTTP_FLAG_FORCE_TLS));
   if (!err)
-    err = send_request (hd, httphost, auth, proxy, srvtag,
+    err = send_request (ctrl, hd, httphost, auth, proxy, srvtag,
                         hd->session? hd->session->connect_timeout : 0,
                         headers);
 
@@ -985,7 +986,8 @@ http_open (http_t *r_hd, http_req_t reqtype, const char *url,
    this http abstraction layer.  This has the advantage of providing
    service tags and an estream interface.  TIMEOUT is in milliseconds. */
 gpg_error_t
-http_raw_connect (http_t *r_hd, const char *server, unsigned short port,
+http_raw_connect (ctrl_t ctrl, http_t *r_hd,
+                  const char *server, unsigned short port,
                   unsigned int flags, const char *srvtag, unsigned int timeout)
 {
   gpg_error_t err = 0;
@@ -1021,7 +1023,8 @@ http_raw_connect (http_t *r_hd, const char *server, unsigned short port,
   {
     assuan_fd_t sock;
 
-    err = connect_server (server, port, hd->flags, srvtag, timeout, &sock);
+    err = connect_server (ctrl, server, port,
+                          hd->flags, srvtag, timeout, &sock);
     if (err)
       {
         xfree (hd);
@@ -1174,14 +1177,14 @@ http_wait_response (http_t hd)
    be used as an HTTP proxy and any enabled $http_proxy gets
    ignored. */
 gpg_error_t
-http_open_document (http_t *r_hd, const char *document,
+http_open_document (ctrl_t ctrl, http_t *r_hd, const char *document,
                     const char *auth, unsigned int flags, const char *proxy,
                     http_session_t session,
                     const char *srvtag, strlist_t headers)
 {
   gpg_error_t err;
 
-  err = http_open (r_hd, HTTP_REQ_GET, document, NULL, auth, flags,
+  err = http_open (ctrl, r_hd, HTTP_REQ_GET, document, NULL, auth, flags,
                    proxy, session, srvtag, headers);
   if (err)
     return err;
@@ -1712,7 +1715,7 @@ is_hostname_port (const char *string)
  * Returns 0 if the request was successful
  */
 static gpg_error_t
-send_request (http_t hd, const char *httphost, const char *auth,
+send_request (ctrl_t ctrl, http_t hd, const char *httphost, const char *auth,
              const char *proxy, const char *srvtag, unsigned int timeout,
               strlist_t headers)
 {
@@ -1859,14 +1862,16 @@ send_request (http_t hd, const char *httphost, const char *auth,
             }
         }
 
-      err = connect_server (*uri->host ? uri->host : "localhost",
+      err = connect_server (ctrl,
+                            *uri->host ? uri->host : "localhost",
                             uri->port ? uri->port : 80,
                             hd->flags, NULL, timeout, &sock);
       http_release_parsed_uri (uri);
     }
   else
     {
-      err = connect_server (server, port, hd->flags, srvtag, timeout, &sock);
+      err = connect_server (ctrl,
+                            server, port, hd->flags, srvtag, timeout, &sock);
     }
 
   if (err)
@@ -2870,7 +2875,7 @@ connect_with_timeout (assuan_fd_t sock,
  * function tries to connect to all known addresses and the timeout is
  * for each one. */
 static gpg_error_t
-connect_server (const char *server, unsigned short port,
+connect_server (ctrl_t ctrl, const char *server, unsigned short port,
                 unsigned int flags, const char *srvtag, unsigned int timeout,
                 assuan_fd_t *r_sock)
 {
@@ -2923,7 +2928,7 @@ connect_server (const char *server, unsigned short port,
   /* Do the SRV thing */
   if (srvtag)
     {
-      err = get_dns_srv (server, srvtag, NULL, &serverlist, &srvcount);
+      err = get_dns_srv (ctrl, server, srvtag, NULL, &serverlist, &srvcount);
       if (err)
         log_info ("getting '%s' SRV for '%s' failed: %s\n",
                   srvtag, server, gpg_strerror (err));
@@ -2953,7 +2958,8 @@ connect_server (const char *server, unsigned short port,
       if (opt_debug)
         log_debug ("http.c:connect_server: trying name='%s' port=%hu\n",
                    serverlist[srv].target, port);
-      err = resolve_dns_name (serverlist[srv].target, port, 0, SOCK_STREAM,
+      err = resolve_dns_name (ctrl,
+                              serverlist[srv].target, port, 0, SOCK_STREAM,
                               &aibuf, NULL);
       if (err)
         {
index 4cfb4c8..a86abbe 100644 (file)
@@ -135,12 +135,12 @@ gpg_error_t http_parse_uri (parsed_uri_t *ret_uri, const char *uri,
 
 void http_release_parsed_uri (parsed_uri_t uri);
 
-gpg_error_t http_raw_connect (http_t *r_hd,
+gpg_error_t http_raw_connect (ctrl_t ctrl, http_t *r_hd,
                               const char *server, unsigned short port,
                               unsigned int flags, const char *srvtag,
                               unsigned int timeout);
 
-gpg_error_t http_open (http_t *r_hd, http_req_t reqtype,
+gpg_error_t http_open (ctrl_t ctrl, http_t *r_hd, http_req_t reqtype,
                        const char *url,
                        const char *httphost,
                        const char *auth,
@@ -156,7 +156,7 @@ gpg_error_t http_wait_response (http_t hd);
 
 void http_close (http_t hd, int keep_read_stream);
 
-gpg_error_t http_open_document (http_t *r_hd,
+gpg_error_t http_open_document (ctrl_t ctrl, http_t *r_hd,
                                 const char *document,
                                 const char *auth,
                                 unsigned int flags,
index c1ecafb..3651ca7 100644 (file)
@@ -88,7 +88,7 @@ ks_action_help (ctrl_t ctrl, const char *url)
         return err;
     }
 
-  /* Call all engines to give them a chance to print a help sting.  */
+  /* Call all engines to give them a chance to print a help string.  */
   err = ks_hkp_help (ctrl, parsed_uri);
   if (!err)
     err = ks_http_help (ctrl, parsed_uri);
index e53a0ee..30ede15 100644 (file)
@@ -82,7 +82,7 @@ ks_finger_fetch (ctrl_t ctrl, parsed_uri_t uri, estream_t *r_fp)
     }
   *server++ = 0;
 
-  err = http_raw_connect (&http, server, 79,
+  err = http_raw_connect (ctrl, &http, server, 79,
                           ((dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR : 0)
                            | (opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)
                            | (opt.disable_ipv6? HTTP_FLAG_IGNORE_IPv6 : 0)),
index 32840e6..790a8b1 100644 (file)
@@ -35,6 +35,7 @@
 # include <netdb.h>
 #endif /*!HAVE_W32_SYSTEM*/
 
+#include <npth.h>
 #include "dirmngr.h"
 #include "misc.h"
 #include "../common/userids.h"
@@ -108,6 +109,8 @@ struct hostinfo_s
    resolved from a pool name and its allocated size.*/
 static hostinfo_t *hosttable;
 static int hosttable_size;
+/* A mutex used to serialize access to the hosttable. */
+static npth_mutex_t hosttable_lock;
 
 /* The number of host slots we initially allocate for HOSTTABLE.  */
 #define INITIAL_HOSTTABLE_SIZE 50
@@ -304,7 +307,7 @@ tor_not_running_p (ctrl_t ctrl)
    PROTOCOL.  If NAME specifies a pool (as indicated by IS_POOL),
    update the given reference table accordingly.  */
 static void
-add_host (const char *name, int is_pool,
+add_host (ctrl_t ctrl, const char *name, int is_pool,
           const dns_addrinfo_t ai,
           enum ks_protocol protocol, unsigned short port)
 {
@@ -320,7 +323,7 @@ add_host (const char *name, int is_pool,
   if (is_pool)
     {
       /* For a pool immediately convert the address to a string.  */
-      tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
+      tmperr = resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
                                  (DNS_NUMERICHOST | DNS_WITHBRACKET), &tmphost);
     }
   else if (!is_ip_address (name))
@@ -337,7 +340,7 @@ add_host (const char *name, int is_pool,
     {
       /* Do a PTR lookup on AI.  If a name was not found the function
        * returns the numeric address (with brackets).  */
-      tmperr = resolve_dns_addr (ai->addr, ai->addrlen,
+      tmperr = resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
                                  DNS_WITHBRACKET, &tmphost);
     }
 
@@ -498,7 +501,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
       unsigned int srvscount;
 
       /* Check for SRV records.  */
-      err = get_dns_srv (name, srvtag, NULL, &srvs, &srvscount);
+      err = get_dns_srv (ctrl, name, srvtag, NULL, &srvs, &srvscount);
       if (err)
         {
           if (gpg_err_code (err) == GPG_ERR_ECONNREFUSED)
@@ -514,13 +517,13 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
 
           for (i = 0; i < srvscount; i++)
             {
-              err = resolve_dns_name (srvs[i].target, 0,
+              err = resolve_dns_name (ctrl, srvs[i].target, 0,
                                       AF_UNSPEC, SOCK_STREAM,
                                       &ai, &cname);
               if (err)
                 continue;
               dirmngr_tick (ctrl);
-              add_host (name, is_pool, ai, protocol, srvs[i].port);
+              add_host (ctrl, name, is_pool, ai, protocol, srvs[i].port);
               new_hosts = 1;
             }
 
@@ -535,7 +538,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
     {
       /* Find all A records for this entry and put them into the pool
          list - if any.  */
-      err = resolve_dns_name (name, 0, 0, SOCK_STREAM, &aibuf, &cname);
+      err = resolve_dns_name (ctrl, name, 0, 0, SOCK_STREAM, &aibuf, &cname);
       if (err)
         {
           log_error ("resolving '%s' failed: %s\n", name, gpg_strerror (err));
@@ -566,7 +569,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
                 continue;
               dirmngr_tick (ctrl);
 
-              add_host (name, is_pool, ai, 0, 0);
+              add_host (ctrl, name, is_pool, ai, 0, 0);
               new_hosts = 1;
             }
 
@@ -624,7 +627,7 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
        * hosttable. */
       char *host;
 
-      err = resolve_dns_name (hi->name, 0, 0, SOCK_STREAM, &aibuf, NULL);
+      err = resolve_dns_name (ctrl, hi->name, 0, 0, SOCK_STREAM, &aibuf, NULL);
       if (!err)
         {
           for (ai = aibuf; ai; ai = ai->next)
@@ -632,7 +635,8 @@ map_host (ctrl_t ctrl, const char *name, const char *srvtag, int force_reselect,
               if ((!opt.disable_ipv6 && ai->family == AF_INET6)
                   || (!opt.disable_ipv4 && ai->family == AF_INET))
                 {
-                  err = resolve_dns_addr (ai->addr, ai->addrlen, 0, &host);
+                  err = resolve_dns_addr (ctrl,
+                                          ai->addr, ai->addrlen, 0, &host);
                   if (!err)
                     {
                       /* Okay, we return the first found name.  */
@@ -755,9 +759,15 @@ ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
   if (!name || !*name || !strcmp (name, "localhost"))
     return 0;
 
+  if (npth_mutex_lock (&hosttable_lock))
+    log_fatal ("failed to acquire mutex\n");
+
   idx = find_hostinfo (name);
   if (idx == -1)
-    return gpg_error (GPG_ERR_NOT_FOUND);
+    {
+      err = gpg_error (GPG_ERR_NOT_FOUND);
+      goto leave;
+    }
 
   hi = hosttable[idx];
   if (alive && hi->dead)
@@ -816,6 +826,10 @@ ks_hkp_mark_host (ctrl_t ctrl, const char *name, int alive)
         }
     }
 
+ leave:
+  if (npth_mutex_unlock (&hosttable_lock))
+    log_fatal ("failed to release mutex\n");
+
   return err;
 }
 
@@ -836,7 +850,9 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
   if (err)
     return err;
 
-  /* FIXME: We need a lock for the hosttable.  */
+  if (npth_mutex_lock (&hosttable_lock))
+    log_fatal ("failed to acquire mutex\n");
+
   curtime = gnupg_get_time ();
   for (idx=0; idx < hosttable_size; idx++)
     if ((hi=hosttable[idx]))
@@ -865,7 +881,7 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
 
                 /* Turn the numerical IP address string into an AI and
                  * then do a DNS PTR lookup.  */
-                if (!resolve_dns_name (hi->name, 0, 0,
+                if (!resolve_dns_name (ctrl, hi->name, 0, 0,
                                        SOCK_STREAM,
                                        &aibuf, &canon))
                   {
@@ -876,7 +892,7 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
                       }
                     for (ai = aibuf; !canon && ai; ai = ai->next)
                       {
-                        resolve_dns_addr (ai->addr, ai->addrlen,
+                        resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
                                           DNS_WITHBRACKET, &canon);
                         if (canon && is_ip_address (canon))
                           {
@@ -896,14 +912,14 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
                 /* Get the IP address as a string from a name.  Note
                  * that resolve_dns_addr allocates CANON on success
                  * and thus terminates the loop. */
-                if (!resolve_dns_name (hi->name, 0,
+                if (!resolve_dns_name (ctrl, hi->name, 0,
                                        hi->v6? AF_INET6 : AF_INET,
                                        SOCK_STREAM,
                                        &aibuf, NULL))
                   {
                     for (ai = aibuf; !canon && ai; ai = ai->next)
                       {
-                        resolve_dns_addr (ai->addr, ai->addrlen,
+                        resolve_dns_addr (ctrl, ai->addr, ai->addrlen,
                                           DNS_NUMERICHOST|DNS_WITHBRACKET,
                                           &canon);
                       }
@@ -929,12 +945,12 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
                               diedstr? ")":""   );
         xfree (died);
         if (err)
-          return err;
+         goto leave;
 
         if (hi->cname)
           err = ks_printf_help (ctrl, "  .       %s", hi->cname);
         if (err)
-          return err;
+         goto leave;
 
         if (hi->pool)
           {
@@ -949,14 +965,21 @@ ks_hkp_print_hosttable (ctrl_t ctrl)
             put_membuf( &mb, "", 1);
             p = get_membuf (&mb, NULL);
             if (!p)
-              return gpg_error_from_syserror ();
+             {
+               err = gpg_error_from_syserror ();
+               goto leave;
+             }
             err = ks_print_help (ctrl, p);
             xfree (p);
             if (err)
-              return err;
+              goto leave;
           }
       }
-  return 0;
+
+ leave:
+  if (npth_mutex_unlock (&hosttable_lock))
+    log_fatal ("failed to release mutex\n");
+  return err;
 }
 
 
@@ -1025,9 +1048,16 @@ make_host_part (ctrl_t ctrl,
       protocol = KS_PROTOCOL_HKP;
     }
 
+  if (npth_mutex_lock (&hosttable_lock))
+    log_fatal ("failed to acquire mutex\n");
+
   portstr[0] = 0;
   err = map_host (ctrl, host, srvtag, force_reselect, protocol,
                   &hostname, portstr, r_httpflags, r_httphost);
+
+  if (npth_mutex_unlock (&hosttable_lock))
+    log_fatal ("failed to release mutex\n");
+
   if (err)
     return err;
 
@@ -1101,6 +1131,9 @@ ks_hkp_housekeeping (time_t curtime)
   int idx;
   hostinfo_t hi;
 
+  if (npth_mutex_lock (&hosttable_lock))
+    log_fatal ("failed to acquire mutex\n");
+
   for (idx=0; idx < hosttable_size; idx++)
     {
       hi = hosttable[idx];
@@ -1117,6 +1150,9 @@ ks_hkp_housekeeping (time_t curtime)
           log_info ("resurrected host '%s'", hi->name);
         }
     }
+
+  if (npth_mutex_unlock (&hosttable_lock))
+    log_fatal ("failed to release mutex\n");
 }
 
 
@@ -1128,6 +1164,9 @@ ks_hkp_reload (void)
   int idx, count;
   hostinfo_t hi;
 
+  if (npth_mutex_lock (&hosttable_lock))
+    log_fatal ("failed to acquire mutex\n");
+
   for (idx=count=0; idx < hosttable_size; idx++)
     {
       hi = hosttable[idx];
@@ -1141,6 +1180,9 @@ ks_hkp_reload (void)
     }
   if (count)
     log_info ("number of resurrected hosts: %d", count);
+
+  if (npth_mutex_unlock (&hosttable_lock))
+    log_fatal ("failed to release mutex\n");
 }
 
 
@@ -1182,7 +1224,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
   http_session_set_timeout (session, ctrl->timeout);
 
  once_more:
-  err = http_open (&http,
+  err = http_open (ctrl, &http,
                    post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
                    request,
                    httphost,
@@ -1339,7 +1381,7 @@ handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
   int retry = 0;
 
   /* Fixme: Should we disable all hosts of a protocol family if a
-   * request for an address of that familiy returned ENETDOWN?  */
+   * request for an address of that family returned ENETDOWN?  */
 
   switch (gpg_err_code (err))
     {
@@ -1493,7 +1535,11 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
       goto again;
     }
   if (err)
-    goto leave;
+    {
+      if (gpg_err_code (err) == GPG_ERR_NO_DATA)
+        dirmngr_status (ctrl, "SOURCE", hostport, NULL);
+      goto leave;
+    }
 
   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
   if (err)
@@ -1628,7 +1674,11 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
       goto again;
     }
   if (err)
-    goto leave;
+    {
+      if (gpg_err_code (err) == GPG_ERR_NO_DATA)
+        dirmngr_status (ctrl, "SOURCE", hostport, NULL);
+      goto leave;
+    }
 
   err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
   if (err)
@@ -1748,3 +1798,13 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
   xfree (httphost);
   return err;
 }
+
+void
+ks_hkp_init (void)
+{
+  int err;
+
+  err = npth_mutex_init (&hosttable_lock, NULL);
+  if (err)
+    log_fatal ("error initializing mutex: %s\n", strerror (err));
+}
index 946c927..9e6b9e1 100644 (file)
@@ -103,7 +103,7 @@ ks_http_fetch (ctrl_t ctrl, const char *url, unsigned int flags,
   http_session_set_timeout (session, ctrl->timeout);
 
   *r_fp = NULL;
-  err = http_open (&http,
+  err = http_open (ctrl, &http,
                    HTTP_REQ_GET,
                    url,
                    /* httphost */ NULL,
index f50ba50..d94bd5e 100644 (file)
@@ -1694,26 +1694,16 @@ extract_attributes (LDAPMod ***modlist, char *line)
 
   if (is_pub || is_sub)
     {
-      char *size = fields[2];
-      int val = atoi (size);
-      size = NULL;
+      char padded[6];
+      int val;
 
-      if (val > 0)
-       {
-         /* We zero pad this on the left to make PGP happy. */
-         char padded[6];
-         if (val < 99999 && val > 0)
-           {
-             snprintf (padded, sizeof padded, "%05u", val);
-             size = padded;
-           }
-       }
-
-      if (size)
-       {
-         if (is_pub || is_sub)
-           modlist_add (modlist, "pgpKeySize", size);
-       }
+      val = atoi (fields[2]);
+      if (val < 99999 && val > 0)
+        {
+          /* We zero pad this on the left to make PGP happy. */
+          snprintf (padded, sizeof padded, "%05u", val);
+          modlist_add (modlist, "pgpKeySize", padded);
+        }
     }
 
   if (is_pub)
@@ -1736,10 +1726,7 @@ extract_attributes (LDAPMod ***modlist, char *line)
        }
 
       if (algo)
-       {
-         if (is_pub)
-           modlist_add (modlist, "pgpKeyType", algo);
-       }
+        modlist_add (modlist, "pgpKeyType", algo);
     }
 
   if (is_pub || is_sub || is_sig)
index cb3c0b7..a04bb97 100644 (file)
@@ -388,7 +388,7 @@ parse_one_pattern (const char *pattern)
 }
 
 /* Take the string STRING and escape it according to the URL rules.
-   Retun a newly allocated string. */
+   Return a newly allocated string. */
 static char *
 escape4url (const char *string)
 {
index 1270b83..9cedf91 100644 (file)
@@ -515,7 +515,7 @@ host_and_port_from_url (const char *url, int *port)
   if ((p = strchr (buf, '/')))
     *p++ = 0;
   strlwr (buf);
-  if ((p = strchr (p, ':')))
+  if ((p = strchr (buf, ':')))
     {
       *p++ = 0;
       *port = atoi (p);
@@ -637,7 +637,7 @@ armor_data (char **r_string, const void *data, size_t datalen)
 }
 
 
-/* Copy all data from IN to OUT.  OUT may be NULL to use this fucntion
+/* Copy all data from IN to OUT.  OUT may be NULL to use this function
  * as a dummy reader.  */
 gpg_error_t
 copy_stream (estream_t in, estream_t out)
index 22391c3..79c252d 100644 (file)
@@ -172,7 +172,7 @@ do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md,
     }
 
  once_more:
-  err = http_open (&http, HTTP_REQ_POST, url, NULL, NULL,
+  err = http_open (ctrl, &http, HTTP_REQ_POST, url, NULL, NULL,
                    ((opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0)
                     | (dirmngr_use_tor ()? HTTP_FLAG_FORCE_TOR:0)
                     | (opt.disable_ipv4? HTTP_FLAG_IGNORE_IPv4 : 0)
@@ -343,7 +343,7 @@ validate_responder_cert (ctrl_t ctrl, ksba_cert_t cert,
 
          Note, that in theory we could simply ask the client via an
          inquire to validate a certificate but this might involve
-         calling DirMngr again recursivly - we can't do that as of now
+         calling DirMngr again recursively - we can't do that as of now
          (neither DirMngr nor gpgsm have the ability for concurrent
          access to DirMngr.   */
 
@@ -391,7 +391,7 @@ check_signature_core (ctrl_t ctrl, ksba_cert_t cert, gcry_sexp_t s_sig,
 }
 
 
-/* Check the signature of an OCSP repsonse.  OCSP is the context,
+/* Check the signature of an OCSP response.  OCSP is the context,
    S_SIG the signature value and MD the handle of the hash we used for
    the response.  This function automagically finds the correct public
    key.  If SIGNER_FPR_LIST is not NULL, the default OCSP reponder has been
@@ -653,6 +653,33 @@ ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
   if (err)
     goto leave;
 
+  /* It is sometimes useful to know the responder ID. */
+  if (opt.verbose)
+    {
+      char *resp_name;
+      ksba_sexp_t resp_keyid;
+
+      err = ksba_ocsp_get_responder_id (ocsp, &resp_name, &resp_keyid);
+      if (err)
+        log_info (_("error getting responder ID: %s\n"), gpg_strerror (err));
+      else
+        {
+          log_info ("responder id: ");
+          if (resp_name)
+            log_printf ("'/%s' ", resp_name);
+          if (resp_keyid)
+            {
+              log_printf ("{");
+              dump_serial (resp_keyid);
+              log_printf ("} ");
+            }
+          log_printf ("\n");
+        }
+      ksba_free (resp_name);
+      ksba_free (resp_keyid);
+      err = 0;
+    }
+
   /* We got a useful answer, check that the answer has a valid signature. */
   sigval = ksba_ocsp_get_sig_val (ocsp, produced_at);
   if (!sigval || !*produced_at)
@@ -761,7 +788,7 @@ ocsp_isvalid (ctrl_t ctrl, ksba_cert_t cert, const char *cert_fpr,
         err = gpg_error (GPG_ERR_TIME_CONFLICT);
     }
 
-  /* Check that we are not beyound NEXT_UPDATE  (plus some extra time). */
+  /* Check that we are not beyond NEXT_UPDATE  (plus some extra time). */
   if (*next_update)
     {
       gnupg_copy_time (tmp_time, next_update);
index b7cdb24..4a24253 100644 (file)
@@ -666,7 +666,7 @@ static const char hlp_dns_cert[] =
 static gpg_error_t
 cmd_dns_cert (assuan_context_t ctx, char *line)
 {
-  /* ctrl_t ctrl = assuan_get_pointer (ctx); */
+  ctrl_t ctrl = assuan_get_pointer (ctx);
   gpg_error_t err = 0;
   int pka_mode, dane_mode;
   char *mbox = NULL;
@@ -731,7 +731,7 @@ cmd_dns_cert (assuan_context_t ctx, char *line)
       /* We lowercase ascii characters but the DANE I-D does not allow
          this.  FIXME: Check after the release of the RFC whether to
          change this.  */
-      mbox = mailbox_from_userid (line);
+      mbox = mailbox_from_userid (line, 0);
       if (!mbox || !(domain = strchr (mbox, '@')))
         {
           err = set_error (GPG_ERR_INV_USER_ID, "no mailbox in user id");
@@ -782,7 +782,7 @@ cmd_dns_cert (assuan_context_t ctx, char *line)
   else
     name = line;
 
-  err = get_dns_cert (name, certtype, &key, &keylen, &fpr, &fprlen, &url);
+  err = get_dns_cert (ctrl, name, certtype, &key, &keylen, &fpr, &fprlen, &url);
   if (err)
     goto leave;
 
@@ -837,8 +837,11 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
   gpg_error_t err = 0;
   char *mbox = NULL;
   char *domainbuf = NULL;
-  char *domain;     /* Points to mbox or domainbuf.  */
-  char *domain_orig;/* Points to mbox.  */
+  char *domain;     /* Points to mbox or domainbuf.  This is used to
+                     * connect to the host.  */
+  char *domain_orig;/* Points to mbox.  This is the used for the
+                     * query; i.e. the domain part of the
+                     * addrspec.  */
   char sha1buf[20];
   char *uri = NULL;
   char *encodedhash = NULL;
@@ -847,6 +850,7 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
   int is_wkd_query;   /* True if this is a real WKD query.  */
   int no_log = 0;
   char portstr[20] = { 0 };
+  int subdomain_mode = 0;
 
   opt_submission_addr = has_option (line, "--submission-address");
   opt_policy_flags = has_option (line, "--policy-flags");
@@ -855,7 +859,7 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
   line = skip_options (line);
   is_wkd_query = !(opt_policy_flags || opt_submission_addr);
 
-  mbox = mailbox_from_userid (line);
+  mbox = mailbox_from_userid (line, 0);
   if (!mbox || !(domain = strchr (mbox, '@')))
     {
       err = set_error (GPG_ERR_INV_USER_ID, "no mailbox in user id");
@@ -864,7 +868,8 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
   *domain++ = 0;
   domain_orig = domain;
 
-  /* First check whether we already know that the domain does not
+
+  /* Let's check whether we already know that the domain does not
    * support WKD.  */
   if (is_wkd_query)
     {
@@ -875,18 +880,63 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
         }
     }
 
-  /* Check for SRV records.  */
-  if (1)
+
+  /* First try the new "openpgp" subdomain.  We check that the domain
+   * is valid because it is later used as an unescaped filename part
+   * of the URI.  */
+  if (is_valid_domain_name (domain_orig))
+    {
+      dns_addrinfo_t aibuf;
+
+      domainbuf = strconcat ( "openpgpkey.", domain_orig, NULL);
+      if (!domainbuf)
+        {
+          err = gpg_error_from_syserror ();
+          goto leave;
+        }
+
+      /* FIXME: We should put a cache into dns-stuff because the same
+       * query (with a different port and socket type, though) will be
+       * done later by http function.  */
+      err = resolve_dns_name (ctrl, domainbuf, 0, 0, 0, &aibuf, NULL);
+      if (err)
+        {
+          err = 0;
+          xfree (domainbuf);
+          domainbuf = NULL;
+        }
+      else /* Got a subdomain. */
+        {
+          free_dns_addrinfo (aibuf);
+          subdomain_mode = 1;
+          domain = domainbuf;
+        }
+    }
+
+  /* Check for SRV records unless we have a subdomain. */
+  if (!subdomain_mode)
     {
       struct srventry *srvs;
       unsigned int srvscount;
       size_t domainlen, targetlen;
       int i;
 
-      err = get_dns_srv (domain, "openpgpkey", NULL, &srvs, &srvscount);
+      err = get_dns_srv (ctrl, domain, "openpgpkey", NULL, &srvs, &srvscount);
       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);
@@ -919,6 +969,7 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
       xfree (srvs);
     }
 
+  /* Prepare the hash of the local part.  */
   gcry_md_hash_buffer (GCRY_MD_SHA1, sha1buf, mbox, strlen (mbox));
   encodedhash = zb32_encode (sha1buf, 8*20);
   if (!encodedhash)
@@ -932,7 +983,10 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
       uri = strconcat ("https://",
                        domain,
                        portstr,
-                       "/.well-known/openpgpkey/submission-address",
+                       "/.well-known/openpgpkey/",
+                       subdomain_mode? domain_orig : "",
+                       subdomain_mode? "/" : "",
+                       "submission-address",
                        NULL);
     }
   else if (opt_policy_flags)
@@ -940,24 +994,39 @@ proc_wkd_get (ctrl_t ctrl, assuan_context_t ctx, char *line)
       uri = strconcat ("https://",
                        domain,
                        portstr,
-                       "/.well-known/openpgpkey/policy",
+                       "/.well-known/openpgpkey/",
+                       subdomain_mode? domain_orig : "",
+                       subdomain_mode? "/" : "",
+                       "policy",
                        NULL);
     }
   else
     {
-      uri = strconcat ("https://",
-                       domain,
-                       portstr,
-                       "/.well-known/openpgpkey/hu/",
-                       encodedhash,
-                       NULL);
-      no_log = 1;
-      if (uri)
+      char *escapedmbox;
+
+      escapedmbox = http_escape_string (mbox, "%;?&=");
+      if (escapedmbox)
         {
-          err = dirmngr_status_printf (ctrl, "SOURCE", "https://%s%s",
-                                       domain, portstr);
-          if (err)
-            goto leave;
+          uri = strconcat ("https://",
+                           domain,
+                           portstr,
+                           "/.well-known/openpgpkey/",
+                           subdomain_mode? domain_orig : "",
+                           subdomain_mode? "/" : "",
+                           "hu/",
+                           encodedhash,
+                           "?l=",
+                           escapedmbox,
+                           NULL);
+          xfree (escapedmbox);
+          no_log = 1;
+          if (uri)
+            {
+              err = dirmngr_status_printf (ctrl, "SOURCE", "https://%s%s",
+                                           domain, portstr);
+              if (err)
+                goto leave;
+            }
         }
     }
   if (!uri)
@@ -2668,6 +2737,20 @@ cmd_reloaddirmngr (assuan_context_t ctx, char *line)
 }
 
 
+static const char hlp_flushcrls[] =
+  "FLUSHCRLS\n"
+  "\n"
+  "Remove all cached CRLs from memory and\n"
+  "the file system.";
+static gpg_error_t
+cmd_flushcrls (assuan_context_t ctx, char *line)
+{
+  (void)line;
+
+  return leave_cmd (ctx, crl_cache_flush () ? GPG_ERR_GENERAL : 0);
+}
+
+
 \f
 /* Tell the assuan library about our commands. */
 static int
@@ -2698,6 +2781,7 @@ register_commands (assuan_context_t ctx)
     { "LOADSWDB",   cmd_loadswdb,   hlp_loadswdb },
     { "KILLDIRMNGR",cmd_killdirmngr,hlp_killdirmngr },
     { "RELOADDIRMNGR",cmd_reloaddirmngr,hlp_reloaddirmngr },
+    { "FLUSHCRLS",  cmd_flushcrls,  hlp_flushcrls },
     { NULL, NULL }
   };
   int i, j, rc;
@@ -2977,7 +3061,7 @@ dirmngr_status_printf (ctrl_t ctrl, const char *keyword,
   va_list arg_ptr;
   assuan_context_t ctx;
 
-  if (!ctrl->server_local || !(ctx = ctrl->server_local->assuan_ctx))
+  if (!ctrl || !ctrl->server_local || !(ctx = ctrl->server_local->assuan_ctx))
     return 0;
 
   va_start (arg_ptr, format);
index 5a3ede1..6d52160 100644 (file)
@@ -178,7 +178,7 @@ main (int argc, char **argv)
       if (verbose || any_options)
         printf ("CERT lookup on '%s'\n", name);
 
-      err = get_dns_cert (name, DNS_CERTTYPE_ANY, &key, &keylen,
+      err = get_dns_cert (NULL, name, DNS_CERTTYPE_ANY, &key, &keylen,
                           &fpr, &fpr_len, &url);
       if (err)
         printf ("get_dns_cert failed: %s <%s>\n",
@@ -218,7 +218,7 @@ main (int argc, char **argv)
       char *cname;
 
       printf ("CNAME lookup on '%s'\n", name);
-      err = get_dns_cname (name, &cname);
+      err = get_dns_cname (NULL, name, &cname);
       if (err)
         printf ("get_dns_cname failed: %s <%s>\n",
                 gpg_strerror (err), gpg_strsource (err));
@@ -234,7 +234,7 @@ main (int argc, char **argv)
       unsigned int count;
       int i;
 
-      err = get_dns_srv (name? name : "_hkp._tcp.wwwkeys.pgp.net",
+      err = get_dns_srv (NULL, name? name : "_hkp._tcp.wwwkeys.pgp.net",
                          NULL, NULL, &srv, &count);
       if (err)
         printf ("get_dns_srv failed: %s <%s>\n",
@@ -261,7 +261,7 @@ main (int argc, char **argv)
 
       printf ("Lookup on '%s'\n", name);
 
-      err = resolve_dns_name (name, 0, 0, SOCK_STREAM, &aibuf, &cname);
+      err = resolve_dns_name (NULL, name, 0, 0, SOCK_STREAM, &aibuf, &cname);
       if (err)
         {
           fprintf (stderr, PGM": resolving '%s' failed: %s\n",
@@ -278,7 +278,7 @@ main (int argc, char **argv)
                   ai->family == AF_INET?  "inet4" : "?    ",
                   ai->socktype, ai->protocol);
 
-          err = resolve_dns_addr (ai->addr, ai->addrlen,
+          err = resolve_dns_addr (NULL, ai->addr, ai->addrlen,
                                   (DNS_NUMERICHOST
                                    | (opt_bracket? DNS_WITHBRACKET:0)),
                                   &host);
@@ -290,7 +290,7 @@ main (int argc, char **argv)
               xfree (host);
             }
 
-          err = resolve_dns_addr (ai->addr, ai->addrlen,
+          err = resolve_dns_addr (NULL, ai->addr, ai->addrlen,
                                   (opt_bracket? DNS_WITHBRACKET:0),
                                   &host);
           if (err)
index 440633d..8b32613 100644 (file)
@@ -137,7 +137,7 @@ my_http_tls_verify_cb (void *opaque,
   (void)session;
   (void)http_flags;
 
-  /* Get the peer's certs fron ntbtls.  */
+  /* Get the peer's certs from ntbtls.  */
   for (idx = 0;
        (cert = ntbtls_x509_get_peer_cert (tls_context, idx)); idx++)
     {
@@ -438,7 +438,7 @@ main (int argc, char **argv)
   if (session)
     http_session_set_timeout (session, timeout);
 
-  rc = http_open_document (&hd, *argv, NULL, my_http_flags,
+  rc = http_open_document (NULL, &hd, *argv, NULL, my_http_flags,
                            NULL, session, NULL, NULL);
   if (rc)
     {
diff --git a/dirmngr/t-support.c b/dirmngr/t-support.c
new file mode 100644 (file)
index 0000000..fc9546a
--- /dev/null
@@ -0,0 +1,43 @@
+/* t-support.c - Module test support (stubs etc).
+ * Copyright (C) 2018 g10 Code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ * SPDX-License-Identifier: GPL-3.0+
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+
+#include "../common/util.h"
+#include "dirmngr-status.h"
+#include "t-support.h"
+
+
+
+/* Stub for testing. See server.c for the real implementation.  */
+gpg_error_t
+dirmngr_status_printf (ctrl_t ctrl, const char *keyword,
+                       const char *format, ...)
+{
+  (void)ctrl;
+  (void)keyword;
+  (void)format;
+
+  return 0;
+}
index 2cb8573..a47cdeb 100644 (file)
@@ -116,7 +116,7 @@ workqueue_add_task (wqtask_t func, const char *args, unsigned int session_id,
 
 
 /* Run the task described by ITEM.  ITEM must have been detached from
- * the workqueue; its ownership is transferred to this fucntion.  */
+ * the workqueue; its ownership is transferred to this function.  */
 static void
 run_a_task (ctrl_t ctrl, wqitem_t item)
 {
index eb6d7dd..74a63ef 100644 (file)
@@ -59,7 +59,7 @@ described here.
     - uat :: User attribute (same as user id except for field 10).
     - sig :: Signature
     - rev :: Revocation signature
-    - rvs :: Recocation signature (standalone) [since 2.2.9]
+    - rvs :: Revocation signature (standalone) [since 2.2.9]
     - fpr :: Fingerprint (fingerprint is in field 10)
     - pkd :: Public key data [*]
     - grp :: Keygrip
@@ -126,7 +126,7 @@ described here.
 *** Field 4 - Public key algorithm
 
     The values here are those from the OpenPGP specs or if they are
-    greather than 255 the algorithm ids as used by Libgcrypt.
+    greater than 255 the algorithm ids as used by Libgcrypt.
 
 *** Field 5 - KeyID
 
@@ -544,7 +544,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
 *** DECRYPTION_KEY <fpr> <fpr2> <otrust>
     This line is emitted when a public key decryption succeeded in
     providing a session key.  <fpr> is the hexified fingerprint of the
-    actual key used for descryption.  <fpr2> is the fingerprint of the
+    actual key used for decryption.  <fpr2> is the fingerprint of the
     primary key.  <otrust> is the letter with the ownertrust; this is
     in general a 'u' which stands for ultimately trusted.
 *** DECRYPTION_INFO <mdc_method> <sym_algo> [<aead_algo>]
@@ -700,7 +700,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
 
        -  0 :: No specific reason given
        -  1 :: Not Found
-       -  2 :: Ambigious specification
+       -  2 :: Ambiguous specification
        -  3 :: Wrong key usage
        -  4 :: Key revoked
        -  5 :: Key expired
@@ -1016,7 +1016,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
       - 2 :: bad PIN
 
 *** SC_OP_SUCCESS
-    A smart card operaion succeeded.  This status is only printed for
+    A smart card operation succeeded.  This status is only printed for
     certain operation and is mostly useful to check whether a PIN
     change really worked.
 
@@ -1073,7 +1073,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
     Deleting a key failed.  Reason codes are:
     - 1 :: No such key
     - 2 :: Must delete secret key first
-    - 3 :: Ambigious specification
+    - 3 :: Ambiguous specification
     - 4 :: Key is stored on a smartcard.
 
 *** PROGRESS <what> <char> <cur> <total> [<units>]
index 17c5826..4781bf6 100644 (file)
@@ -150,7 +150,7 @@ Note that such a comment will be removed if the git commit option
       if ( 42 == foo )
 #+end_src
     this is harder to read and modern compilers are pretty good in
-    detecing accidential assignments.  It is also suggested not to
+    detecing accidental assignments.  It is also suggested not to
     compare to 0 or NULL but to test the value direct or with a '!';
     this makes it easier to see that a boolean test is done.
   - We use our own printf style functions like =es_printf=, and
@@ -342,7 +342,7 @@ Note that such a comment will be removed if the git commit option
   - g10/main.h     :: Prototypes and some constants
   - g10/mainproc.c :: Message processing
   - g10/armor.c    :: Ascii armor filter
-  - g10/mdfilter.c :: Filter to calculate hashs
+  - g10/mdfilter.c :: Filter to calculate hashes
   - g10/textfilter.c :: Filter to handle CR/LF and trailing white space
   - g10/cipher.c   :: En-/Decryption filter
   - g10/misc.c     :: Utility functions
@@ -395,7 +395,7 @@ The *secure versions allocate memory in the secure memory.  That is,
 swapping out of this memory is avoided and is gets overwritten on
 free.  Use this for passphrases, session keys and other sensitive
 material.  This memory set aside for secure memory is linited to a few
-k.  In general the function don't print a memeory message and
+k.  In general the function don't print a memory message and
 terminate the process if there is not enough memory available.  The
 "try" versions of the functions return NULL instead.
 
index 19241b7..33ef292 100644 (file)
--- a/doc/Notes
+++ b/doc/Notes
@@ -1,5 +1,5 @@
 
-Add an infor page for watchgnupg.
+Add an info page for watchgnupg.
 
 > * How to mark a CA certificate as trusted.
 
@@ -57,7 +57,7 @@ or
 
 In general you should first import the root certificates and then down
 to the end user certificate.  You may put all into one file and gpgsm
-will do the right thing in this case independend of the order.  
+will do the right thing in this case independent of the order.
 
 While verifying a signature, all included certificates are
 automagically imported.
@@ -82,7 +82,7 @@ you get an output like:
   uid:::::::::CN=Werner Koch,OU=test,O=g10 Code,C=de::
   uid:::::::::<wk@g10code.de>::
 
-This should be familar to advanced gpg-users; see doc/DETAILS in gpg
+This should be familiar to advanced gpg-users; see doc/DETAILS in gpg
 1.3 (CVS HEAD) for a description of the records.  The value in the
 "grp" tagged record is the so called keygrip and you should find a
 file ~/.gnupg/private-keys-v1.d/C92DB9CFD588ADE846BE3AC4E7A2E1B11A4A2ADB.key
index 76be528..f5910a8 100644 (file)
@@ -1096,7 +1096,7 @@ as a binary blob.
 @c In the end the same fucntionality is used, albeit hidden by a couple
 @c of indirection and argument and result code mangling.  It furthere
 @c ingetrages OCSP checking depending on options are the way it is
-@c called.  GPGSM still uses this command but might eventuall switch over
+@c called.  GPGSM still uses this command but might eventually switch over
 @c to CHECKCRL and CHECKOCSP so that ISVALID can be retired.
 @c
 @c
index ddbeafa..2f873e6 100644 (file)
@@ -1096,7 +1096,7 @@ update this FAQ in the next month.  See the section "Changes" for recent updates
     As of 1.0.3, keys generated with gpg are created with preferences to
     TWOFISH (and AES since 1.0.4) and that also means that they have the
     capability to use the new MDC encryption method. This will go into
-    OpenPGP soon, and is also suppoted by PGP 7. This new method avoids
+    OpenPGP soon, and is also supported by PGP 7. This new method avoids
     a (not so new) attack on all email encryption systems.
 
     This in turn means that pre-1.0.3 gpg binaries have problems with
index 4cfd000..dedb8cc 100644 (file)
@@ -624,9 +624,9 @@ fingerprint (preferred) or their keyid.
 @end table
 
 
-@c *******************************************
-@c *******  KEY MANGEMENT COMMANDS  **********
-@c *******************************************
+@c ********************************************
+@c *******  KEY MANAGEMENT COMMANDS  **********
+@c ********************************************
 @node OpenPGP Key Management
 @subsection How to manage your keys
 
@@ -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
@@ -1719,7 +1724,8 @@ Set what trust model GnuPG should follow. The models are:
   @opindex trust-model:auto
   Select the trust model depending on whatever the internal trust
   database says. This is the default model if such a database already
-  exists.
+  exists.  Note that a tofu trust model is not considered here and
+  must be enabled explicitly.
 @end table
 
 @item --auto-key-locate @var{mechanisms}
@@ -2258,9 +2264,8 @@ The AEAD encryption mode encrypts the data in chunks so that a
 receiving side can check for transmission errors or tampering at the
 end of each chunk and does not need to delay this until all data has
 been received.  The used chunk size is 2^@var{n} byte.  The lowest
-allowed value for @var{n} is 6 (64 byte) and the largest is 62 (4
-EiB). The default value for @var{n} is 30 which creates chunks not
-larger than 1 GiB.
+allowed value for @var{n} is 6 (64 byte) and the largest is the
+default of 27 which creates chunks not larger than 128 MiB.
 
 @item --input-size-hint @var{n}
 @opindex input-size-hint
@@ -2338,6 +2343,11 @@ opposite meaning. The options are:
   on the keyring. This option is the same as running the @option{--edit-key}
   command "clean" after import. Defaults to no.
 
+  @item import-drop-uids
+  Do not import any user ids or their binding signatures.  This option
+  can be used to update only the subkeys or other non-user id related
+  information.
+
   @item repair-keys.  After import, fix various problems with the
   keys.  For example, this reorders signatures, and strips duplicate
   signatures.  Defaults to yes.
@@ -2502,6 +2512,11 @@ opposite meaning.  The options are:
   running the @option{--edit-key} command "minimize" before export except
   that the local copy of the key is not modified. Defaults to no.
 
+  @item export-drop-uids
+  Do no export any user id or attribute packets or their associates
+  signatures.  Note that due to missing user ids the resulting output is
+  not strictly RFC-4880 compliant.
+
   @item export-pka
   Instead of outputting the key material output PKA records suitable
   to put into DNS zone files.  An ORIGIN line is printed before each
@@ -2608,7 +2623,7 @@ These options are obsolete and have no effect since GnuPG 2.1.
 @item --force-aead
 @opindex force-aead
 Force the use of AEAD encryption over MDC encryption.  AEAD is a
-modern and faster way to do authenticated encrytion than the old MDC
+modern and faster way to do authenticated encryption than the old MDC
 method.  See also options @option{--aead-algo} and
 @option{--chunk-size}.
 
@@ -2621,7 +2636,7 @@ to declare that a not yet standardized feature is used.
 @opindex disable-mdc
 These options are obsolete and have no effect since GnuPG 2.2.8.  The
 MDC is always used unless the keys indicate that an AEAD algorithm can
-be used in which case AEAD is used.  But note: If the creation or of a
+be used in which case AEAD is used.  But note: If the creation of a
 legacy non-MDC message is exceptionally required, the option
 @option{--rfc2440} allows for this.
 
@@ -2764,7 +2779,7 @@ This option is obsolete; it is handled as an alias for @option{--pgp7}
 
 @item --pgp7
 @opindex pgp7
-Set up all options to be as PGP 7 compliant as possible. This allowd
+Set up all options to be as PGP 7 compliant as possible. This allowed
 the ciphers IDEA, 3DES, CAST5,AES128, AES192, AES256, and TWOFISH.,
 the hashes MD5, SHA1 and RIPEMD160, and the compression algorithms
 none and ZIP.  This option implies @option{--escape-from-lines} and
@@ -2862,6 +2877,13 @@ Change the buffer size of the IOBUFs to @var{n} kilobyte.  Using 0
 prints the current size.  Note well: This is a maintainer only option
 and may thus be changed or removed at any time without notice.
 
+@item --debug-allow-large-chunks
+@opindex debug-allow-large-chunks
+To facilitate in-memory decryption on the receiving site, the largest
+recommended chunk size is 128 MiB (@code{--chunk-size 27}).  This
+option allows to specify a limit of up to 4 EiB (@code{--chunk-size
+62}) for experiments.
+
 @item --faked-system-time @var{epoch}
 @opindex faked-system-time
 This option is only useful for testing; it sets the system time back or
@@ -2964,6 +2986,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}
@@ -3022,7 +3051,7 @@ same thing.
 @opindex aead-algo
 Specify that the AEAD algorithm @var{name} is to be used.  This is
 useful for symmetric encryption where no key preference are available
-to select the AEAD algorithm.  Runing @command{@gpgname} with option
+to select the AEAD algorithm.  Running @command{@gpgname} with option
 @option{--version} shows the available AEAD algorithms.  In general,
 you do not want to use this option as it allows you to violate the
 OpenPGP standard.  The option @option{--personal-aead-preferences} is
@@ -3340,13 +3369,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
@@ -3637,6 +3667,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 7becf67..6256c05 100644 (file)
@@ -1561,7 +1561,7 @@ string @code{true} or @code{yes}.  The evaluation is done by passing
   /subst
   /let i 3
   /while $i
-    /echo loop couter is $i
+    /echo loop counter is $i
     /let i $@{- $i 1@}
   /end
 @end smallexample
@@ -1962,7 +1962,7 @@ Extract all files from an encrypted archive.
 
 @item --sign
 @itemx -s
-Make a signed archive from the given files and directories.  Thsi can
+Make a signed archive from the given files and directories.  This can
 be combined with option @option{--encrypt} to create a signed and then
 encrypted archive.
 
@@ -2031,7 +2031,7 @@ linefeed to separate file names.
 
 @item --openpgp
 @opindex openpgp
-This option has no effect becuase OpenPGP encryption and signing is
+This option has no effect because OpenPGP encryption and signing is
 the default.
 
 @item --cms
index 4508ae2..03d7482 100644 (file)
@@ -61,11 +61,12 @@ Service provider.  This is usuallay done to upload a key into a Web
 Key Directory.
 
 With the @option{--supported} command the caller can test whether a
-site supports the Web Key Service.  The argument is an arbitray
+site supports the Web Key Service.  The argument is an arbitrary
 address in the to be tested domain. For example
 @file{foo@@example.net}.  The command returns success if the Web Key
 Service is supported.  The operation is silent; to get diagnostic
-output use the option @option{--verbose}.
+output use the option @option{--verbose}.  See option
+@option{--with-colons} for a variant of this command.
 
 With the @option{--check} command the caller can test whether a key
 exists for a supplied mail address.  The command returns success if a
@@ -109,6 +110,44 @@ $(gpgconf --list-dirs libexecdir)/gpg-wks-client --check foo@@example.net
 Directly send created mails using the @command{sendmail} command.
 Requires installation of that command.
 
+@item --with-colons
+@opindex with-colons
+This option has currently only an effect on the @option{--supported}
+command.  If it is used all arguimenst on the command line are taken
+as domain names and tested for WKD support.  The output format is one
+line per domain with colon delimited fields.  The currently specified
+fields are (future versions may specify additional fields):
+
+@table @asis
+
+  @item 1 - domain
+  This is the domain name.  Although quoting is not required for valid
+  domain names this field is specified to be quoted in standard C
+  manner.
+
+  @item 2 - WKD
+  If the value is true the domain supports the Web Key Directory.
+
+  @item 3 - WKS
+  If the value is true the domain supports the Web Key Service
+  protocol to upload keys to the directory.
+
+  @item 4 - error-code
+  This may contain an gpg-error code to describe certain
+  failures.  Use @samp{gpg-error CODE} to explain the code.
+
+  @item 5 - protocol-version
+  The minimum protocol version supported by the server.
+
+  @item 6 - auth-submit
+  The auth-submit flag from the policy file of the server.
+
+  @item 7 - mailbox-only
+  The mailbox-only flag from the policy file of the server.
+@end table
+
+
+
 @item --output @var{file}
 @itemx -o
 @opindex output
@@ -206,7 +245,7 @@ mail is processed.  Commonly this command is used with the option
 @option{--send} to directly send the crerated mails back.  See below
 for an installation example.
 
-The command @option{--cron} is used for regualr cleanup tasks.  For
+The command @option{--cron} is used for regular cleanup tasks.  For
 example non-confirmed requested should be removed after their expire
 time.  It is best to run this command once a day from a cronjob.
 
@@ -215,9 +254,9 @@ Further it creates missing directories for the configuration and
 prints warnings pertaining to problems in the configuration.
 
 The command @option{--check-key} (or just @option{--check}) checks
-whether a key with the given user-id is installed.  The process return
-success in this case; to also print a diagnostic, use option
-@option{-v}.  If the key is not installed a diagnostics is printed and
+whether a key with the given user-id is installed.  The process returns
+success in this case; to also print a diagnostic use the option
+@option{-v}.  If the key is not installed a diagnostic is printed and
 the process returns failure; to suppress the diagnostic, use option
 @option{-q}.  More than one user-id can be given; see also option
 @option{with-file}.
@@ -243,6 +282,12 @@ The command @option{--revoke-key} is not yet functional.
 
 @table @gnupgtabopt
 
+@item -C @var{dir}
+@itemx --directory @var{dir}
+@opindex directory
+Use @var{dir} as top level directory for domains.  The default is
+@file{/var/lib/gnupg/wks}.
+
 @item --from @var{mailaddr}
 @opindex from
 Use @var{mailaddr} as the default sender address.
@@ -256,21 +301,22 @@ Add the mail header "@var{name}: @var{value}" to all outgoing mails.
 Directly send created mails using the @command{sendmail} command.
 Requires installation of that command.
 
-@item --output @var{file}
-@itemx -o
+@item -o @var{file}
+@itemx --output @var{file}
 @opindex output
 Write the created mail also to @var{file}. Note that the value
 @code{-} for @var{file} would write it to stdout.
 
 @item --with-dir
 @opindex with-dir
-Also print the directory name for each domain listed by command
-@option{--list-domains}.
+When used with the command @option{--list-domains} print for each
+installed domain the domain name and its directory name.
 
 @item --with-file
 @opindex with-file
-With command @option{--check-key} print for each user-id, the address,
-'i' for installed key or 'n' for not installed key, and the filename.
+When used with the command @option{--check-key} print for each user-id,
+the address, 'i' for installed key or 'n' for not installed key, and
+the filename.
 
 @item --verbose
 @opindex verbose
@@ -316,7 +362,7 @@ Finally run
   $ gpg-wks-server --list-domains
 @end example
 
-to create the required sub-directories with the permission set
+to create the required sub-directories with the permissions set
 correctly.  For each domain a submission address needs to be
 configured.  All service mails are directed to that address.  It can
 be the same address for all configured domains, for example:
@@ -326,7 +372,7 @@ be the same address for all configured domains, for example:
   $ echo key-submission@@example.net >submission-address
 @end example
 
-The protocol requires that the key to be published is sent with an
+The protocol requires that the key to be published is send with an
 encrypted mail to the service.  Thus you need to create a key for
 the submission address:
 
index c7bec33..be0ef17 100644 (file)
@@ -55,7 +55,7 @@
       .B whateever you want
       @end ifset
 
-    alternativly a special comment may be used:
+    alternatively a special comment may be used:
 
       @c man:.B whatever you want
 
@@ -704,7 +704,7 @@ write_th (FILE *fp)
 
 
 /* Process the texinfo command COMMAND (without the leading @) and
-   write output if needed to FP. REST is the remainer of the line
+   write output if needed to FP. REST is the remainder of the line
    which should either point to an opening brace or to a white space.
    The function returns the number of characters already processed
    from REST.  LEN is the usable length of REST.  TABLE_LEVEL is used to
@@ -1197,7 +1197,7 @@ parse_file (const char *fname, FILE *fp, char **section_name, int in_pause)
           if (*p == '@' && !strncmp (p+1, "item", 4))
             item_indent = p - line;  /* Set a new indent level.  */
           else if (p - line < item_indent)
-            item_indent = 0;         /* Switch off indention.  */
+            item_indent = 0;         /* Switch off indentation.  */
 
           if (item_indent)
             {
index b8b92d7..3b44643 100644 (file)
@@ -152,6 +152,7 @@ gpg_sources = server.c          \
              trust.c $(trust_source) $(tofu_source) \
              $(card_source) \
              exec.c exec.h \
+              key-clean.c key-clean.h \
              key-check.c key-check.h
 
 gpg_SOURCES  = gpg.c \
index cc80968..9727665 100644 (file)
@@ -1,4 +1,4 @@
-/* armor.c - Armor flter
+/* armor.c - Armor filter
  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
  *               2007 Free Software Foundation, Inc.
  *
 
 #define MAX_LINELEN 20000
 
-#define CRCINIT 0xB704CE
-#define CRCPOLY 0X864CFB
-#define CRCUPDATE(a,c) do {                                                \
-                       a = ((a) << 8) ^ crc_table[((a)&0xff >> 16) ^ (c)]; \
-                       a &= 0x00ffffff;                                    \
-                   } while(0)
-static u32 crc_table[256];
-static byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-                        "abcdefghijklmnopqrstuvwxyz"
-                        "0123456789+/";
-static byte asctobin[256]; /* runtime initialized */
+static const byte bintoasc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                               "abcdefghijklmnopqrstuvwxyz"
+                               "0123456789+/";
+static u32 asctobin[4][256]; /* runtime initialized */
 static int is_initialized;
 
 
@@ -121,9 +114,22 @@ armor_filter_context_t *
 new_armor_context (void)
 {
   armor_filter_context_t *afx;
+  gpg_error_t err;
 
   afx = xcalloc (1, sizeof *afx);
-  afx->refcount = 1;
+  if (afx)
+    {
+      err = gcry_md_open (&afx->crc_md, GCRY_MD_CRC24_RFC2440, 0);
+      if (err != 0)
+       {
+         log_error ("gcry_md_open failed for GCRY_MD_CRC24_RFC2440: %s",
+                   gpg_strerror (err));
+         xfree (afx);
+         return NULL;
+       }
+
+      afx->refcount = 1;
+    }
 
   return afx;
 }
@@ -138,6 +144,7 @@ release_armor_context (armor_filter_context_t *afx)
   log_assert (afx->refcount);
   if ( --afx->refcount )
     return;
+  gcry_md_close (afx->crc_md);
   xfree (afx);
 }
 
@@ -161,35 +168,42 @@ push_armor_filter (armor_filter_context_t *afx, iobuf_t iobuf)
 static void
 initialize(void)
 {
-    int i, j;
-    u32 t;
-    byte *s;
-
-    /* init the crc lookup table */
-    crc_table[0] = 0;
-    for(i=j=0; j < 128; j++ ) {
-       t = crc_table[j];
-       if( t & 0x00800000 ) {
-           t <<= 1;
-           crc_table[i++] = t ^ CRCPOLY;
-           crc_table[i++] = t;
-       }
-       else {
-           t <<= 1;
-           crc_table[i++] = t;
-           crc_table[i++] = t ^ CRCPOLY;
-       }
-    }
-    /* build the helptable for radix64 to bin conversion */
-    for(i=0; i < 256; i++ )
-       asctobin[i] = 255; /* used to detect invalid characters */
+    u32 i;
+    const byte *s;
+
+    /* Build the helptable for radix64 to bin conversion.  Value 0xffffffff is
+       used to detect invalid characters.  */
+    memset (asctobin, 0xff, sizeof(asctobin));
     for(s=bintoasc,i=0; *s; s++,i++ )
-       asctobin[*s] = i;
+      {
+       asctobin[0][*s] = i << (0 * 6);
+       asctobin[1][*s] = i << (1 * 6);
+       asctobin[2][*s] = i << (2 * 6);
+       asctobin[3][*s] = i << (3 * 6);
+      }
 
     is_initialized=1;
 }
 
 
+static inline u32
+get_afx_crc (armor_filter_context_t *afx)
+{
+  const byte *crc_buf;
+  u32 crc;
+
+  crc_buf = gcry_md_read (afx->crc_md, GCRY_MD_CRC24_RFC2440);
+
+  crc = crc_buf[0];
+  crc <<= 8;
+  crc |= crc_buf[1];
+  crc <<= 8;
+  crc |= crc_buf[2];
+
+  return crc;
+}
+
+
 /*
  * Check whether this is an armored file.  See also
  * parse-packet.c for details on this code.
@@ -592,7 +606,7 @@ check_input( armor_filter_context_t *afx, IOBUF a )
        afx->faked = 1;
     else {
        afx->inp_checked = 1;
-       afx->crc = CRCINIT;
+       gcry_md_reset (afx->crc_md);
        afx->idx = 0;
        afx->radbuf[0] = 0;
     }
@@ -768,7 +782,7 @@ fake_packet( armor_filter_context_t *afx, IOBUF a,
            }
        }
        afx->inp_checked = 1;
-       afx->crc = CRCINIT;
+       gcry_md_reset (afx->crc_md);
        afx->idx = 0;
        afx->radbuf[0] = 0;
     }
@@ -793,14 +807,14 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
              byte *buf, size_t size )
 {
     byte val;
-    int c=0, c2; /*init c because gcc is not clever enough for the continue*/
+    int c;
+    u32 binc;
     int checkcrc=0;
     int rc = 0;
     size_t n = 0;
-    int  idx, i, onlypad=0;
-    u32 crc;
+    int idx, onlypad=0;
+    int skip_fast = 0;
 
-    crc = afx->crc;
     idx = afx->idx;
     val = afx->radbuf[0];
     for( n=0; n < size; ) {
@@ -820,6 +834,122 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
        }
 
       again:
+       binc = asctobin[0][c];
+
+       if( binc != 0xffffffffUL )
+         {
+           if( idx == 0 && skip_fast == 0
+               && afx->buffer_pos + (16 - 1) < afx->buffer_len
+               && n + 12 < size)
+             {
+               /* Fast path for radix64 to binary conversion.  */
+               u32 b0,b1,b2,b3;
+
+               /* Speculatively load 15 more input bytes.  */
+               b0 = binc << (3 * 6);
+               b0 |= asctobin[2][afx->buffer[afx->buffer_pos + 0]];
+               b0 |= asctobin[1][afx->buffer[afx->buffer_pos + 1]];
+               b0 |= asctobin[0][afx->buffer[afx->buffer_pos + 2]];
+               b1  = asctobin[3][afx->buffer[afx->buffer_pos + 3]];
+               b1 |= asctobin[2][afx->buffer[afx->buffer_pos + 4]];
+               b1 |= asctobin[1][afx->buffer[afx->buffer_pos + 5]];
+               b1 |= asctobin[0][afx->buffer[afx->buffer_pos + 6]];
+               b2  = asctobin[3][afx->buffer[afx->buffer_pos + 7]];
+               b2 |= asctobin[2][afx->buffer[afx->buffer_pos + 8]];
+               b2 |= asctobin[1][afx->buffer[afx->buffer_pos + 9]];
+               b2 |= asctobin[0][afx->buffer[afx->buffer_pos + 10]];
+               b3  = asctobin[3][afx->buffer[afx->buffer_pos + 11]];
+               b3 |= asctobin[2][afx->buffer[afx->buffer_pos + 12]];
+               b3 |= asctobin[1][afx->buffer[afx->buffer_pos + 13]];
+               b3 |= asctobin[0][afx->buffer[afx->buffer_pos + 14]];
+
+               /* Check if any of the input bytes were invalid. */
+               if( (b0 | b1 | b2 | b3) != 0xffffffffUL )
+                 {
+                   /* All 16 bytes are valid. */
+                   buf[n + 0] = b0 >> (2 * 8);
+                   buf[n + 1] = b0 >> (1 * 8);
+                   buf[n + 2] = b0 >> (0 * 8);
+                   buf[n + 3] = b1 >> (2 * 8);
+                   buf[n + 4] = b1 >> (1 * 8);
+                   buf[n + 5] = b1 >> (0 * 8);
+                   buf[n + 6] = b2 >> (2 * 8);
+                   buf[n + 7] = b2 >> (1 * 8);
+                   buf[n + 8] = b2 >> (0 * 8);
+                   buf[n + 9] = b3 >> (2 * 8);
+                   buf[n + 10] = b3 >> (1 * 8);
+                   buf[n + 11] = b3 >> (0 * 8);
+                   afx->buffer_pos += 16 - 1;
+                   n += 12;
+                   continue;
+                 }
+               else if( b0 == 0xffffffffUL )
+                 {
+                   /* byte[1..3] have invalid character(s).  Switch to slow
+                      path.  */
+                   skip_fast = 1;
+                 }
+               else if( b1 == 0xffffffffUL )
+                 {
+                   /* byte[4..7] have invalid character(s), first 4 bytes are
+                      valid.  */
+                   buf[n + 0] = b0 >> (2 * 8);
+                   buf[n + 1] = b0 >> (1 * 8);
+                   buf[n + 2] = b0 >> (0 * 8);
+                   afx->buffer_pos += 4 - 1;
+                   n += 3;
+                   skip_fast = 1;
+                   continue;
+                 }
+               else if( b2 == 0xffffffffUL )
+                 {
+                   /* byte[8..11] have invalid character(s), first 8 bytes are
+                      valid.  */
+                   buf[n + 0] = b0 >> (2 * 8);
+                   buf[n + 1] = b0 >> (1 * 8);
+                   buf[n + 2] = b0 >> (0 * 8);
+                   buf[n + 3] = b1 >> (2 * 8);
+                   buf[n + 4] = b1 >> (1 * 8);
+                   buf[n + 5] = b1 >> (0 * 8);
+                   afx->buffer_pos += 8 - 1;
+                   n += 6;
+                   skip_fast = 1;
+                   continue;
+                 }
+               else /*if( b3 == 0xffffffffUL )*/
+                 {
+                   /* byte[12..15] have invalid character(s), first 12 bytes
+                      are valid.  */
+                   buf[n + 0] = b0 >> (2 * 8);
+                   buf[n + 1] = b0 >> (1 * 8);
+                   buf[n + 2] = b0 >> (0 * 8);
+                   buf[n + 3] = b1 >> (2 * 8);
+                   buf[n + 4] = b1 >> (1 * 8);
+                   buf[n + 5] = b1 >> (0 * 8);
+                   buf[n + 6] = b2 >> (2 * 8);
+                   buf[n + 7] = b2 >> (1 * 8);
+                   buf[n + 8] = b2 >> (0 * 8);
+                   afx->buffer_pos += 12 - 1;
+                   n += 9;
+                   skip_fast = 1;
+                   continue;
+                 }
+             }
+
+           switch(idx)
+             {
+               case 0: val =  binc << 2; break;
+               case 1: val |= (binc>>4)&3; buf[n++]=val;val=(binc<<4)&0xf0;break;
+               case 2: val |= (binc>>2)&15; buf[n++]=val;val=(binc<<6)&0xc0;break;
+               case 3: val |= binc&0x3f; buf[n++] = val; break;
+             }
+           idx = (idx+1) % 4;
+
+           continue;
+         }
+
+       skip_fast = 0;
+
        if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
            continue;
        else if( c == '=' ) { /* pad character: stop */
@@ -850,10 +980,10 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
             if (afx->buffer_pos + 6 < afx->buffer_len
                 && afx->buffer[afx->buffer_pos + 0] == '3'
                 && afx->buffer[afx->buffer_pos + 1] == 'D'
-                && asctobin[afx->buffer[afx->buffer_pos + 2]] != 255
-                && asctobin[afx->buffer[afx->buffer_pos + 3]] != 255
-                && asctobin[afx->buffer[afx->buffer_pos + 4]] != 255
-                && asctobin[afx->buffer[afx->buffer_pos + 5]] != 255
+                && asctobin[0][afx->buffer[afx->buffer_pos + 2]] != 0xffffffffUL
+                && asctobin[0][afx->buffer[afx->buffer_pos + 3]] != 0xffffffffUL
+                && asctobin[0][afx->buffer[afx->buffer_pos + 4]] != 0xffffffffUL
+                && asctobin[0][afx->buffer[afx->buffer_pos + 5]] != 0xffffffffUL
                 && afx->buffer[afx->buffer_pos + 6] == '\n')
               {
                 afx->buffer_pos += 2;
@@ -868,27 +998,20 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
            checkcrc++;
            break;
        }
-       else if( (c = asctobin[(c2=c)]) == 255 ) {
-           log_error(_("invalid radix64 character %02X skipped\n"), c2);
+       else {
+           log_error(_("invalid radix64 character %02X skipped\n"), c);
            continue;
        }
-       switch(idx) {
-         case 0: val =  c << 2; break;
-         case 1: val |= (c>>4)&3; buf[n++]=val;val=(c<<4)&0xf0;break;
-         case 2: val |= (c>>2)&15; buf[n++]=val;val=(c<<6)&0xc0;break;
-         case 3: val |= c&0x3f; buf[n++] = val; break;
-       }
-       idx = (idx+1) % 4;
     }
 
-    for(i=0; i < n; i++ )
-       crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
-    crc &= 0x00ffffff;
-    afx->crc = crc;
     afx->idx = idx;
     afx->radbuf[0] = val;
 
+    if( n )
+      gcry_md_write (afx->crc_md, buf, n);
+
     if( checkcrc ) {
+       gcry_md_final (afx->crc_md);
        afx->any_data = 1;
        afx->inp_checked=0;
        afx->faked = 0;
@@ -911,19 +1034,19 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
                continue;
            break;
        }
-       if( c == -1 )
+       if( !afx->buffer_len )
            log_error(_("premature eof (no CRC)\n"));
        else {
            u32 mycrc = 0;
            idx = 0;
            do {
-               if( (c = asctobin[c]) == 255 )
+               if( (binc = asctobin[0][c]) == 0xffffffffUL )
                    break;
                switch(idx) {
-                 case 0: val =  c << 2; break;
-                 case 1: val |= (c>>4)&3; mycrc |= val << 16;val=(c<<4)&0xf0;break;
-                 case 2: val |= (c>>2)&15; mycrc |= val << 8;val=(c<<6)&0xc0;break;
-                 case 3: val |= c&0x3f; mycrc |= val; break;
+                 case 0: val =  binc << 2; break;
+                 case 1: val |= (binc>>4)&3; mycrc |= val << 16;val=(binc<<4)&0xf0;break;
+                 case 2: val |= (binc>>2)&15; mycrc |= val << 8;val=(binc<<6)&0xc0;break;
+                 case 3: val |= binc&0x3f; mycrc |= val; break;
                }
                for(;;) {
                    if( afx->buffer_pos < afx->buffer_len )
@@ -945,7 +1068,7 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
                if( !afx->buffer_len )
                    break; /* eof */
            } while( ++idx < 4 );
-           if( c == -1 ) {
+           if( !afx->buffer_len ) {
                log_info(_("premature eof (in CRC)\n"));
                rc = invalid_crc();
            }
@@ -957,10 +1080,10 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
                log_info(_("malformed CRC\n"));
                rc = invalid_crc();
            }
-           else if( mycrc != afx->crc ) {
-                log_info (_("CRC error; %06lX - %06lX\n"),
-                                   (ulong)afx->crc, (ulong)mycrc);
-                rc = invalid_crc();
+           else if( mycrc != get_afx_crc (afx) ) {
+               log_info (_("CRC error; %06lX - %06lX\n"),
+                                   (ulong)get_afx_crc (afx), (ulong)mycrc);
+               rc = invalid_crc();
            }
            else {
                rc = 0;
@@ -997,6 +1120,121 @@ radix64_read( armor_filter_context_t *afx, IOBUF a, size_t *retn,
     return rc;
 }
 
+static void
+armor_output_buf_as_radix64 (armor_filter_context_t *afx, IOBUF a,
+                            byte *buf, size_t size)
+{
+  byte radbuf[sizeof (afx->radbuf)];
+  byte outbuf[64 + sizeof (afx->eol)];
+  unsigned int eollen = strlen (afx->eol);
+  u32 in, in2;
+  int idx, idx2;
+  int i;
+
+  idx = afx->idx;
+  idx2 = afx->idx2;
+  memcpy (radbuf, afx->radbuf, sizeof (afx->radbuf));
+
+  if (size && (idx || idx2))
+    {
+      /* preload eol to outbuf buffer */
+      memcpy (outbuf + 4, afx->eol, sizeof (afx->eol));
+
+      for (; size && (idx || idx2); buf++, size--)
+       {
+         radbuf[idx++] = *buf;
+         if (idx > 2)
+           {
+             idx = 0;
+             in = (u32)radbuf[0] << (2 * 8);
+             in |= (u32)radbuf[1] << (1 * 8);
+             in |= (u32)radbuf[2] << (0 * 8);
+             outbuf[0] = bintoasc[(in >> 18) & 077];
+             outbuf[1] = bintoasc[(in >> 12) & 077];
+             outbuf[2] = bintoasc[(in >> 6) & 077];
+             outbuf[3] = bintoasc[(in >> 0) & 077];
+             if (++idx2 >= (64/4))
+               { /* pgp doesn't like 72 here */
+                 idx2=0;
+                 iobuf_write (a, outbuf, 4 + eollen);
+               }
+             else
+               {
+                 iobuf_write (a, outbuf, 4);
+               }
+           }
+       }
+    }
+
+  if (size >= (64/4)*3)
+    {
+      /* preload eol to outbuf buffer */
+      memcpy (outbuf + 64, afx->eol, sizeof(afx->eol));
+
+      do
+       {
+         /* idx and idx2 == 0 */
+
+         for (i = 0; i < (64/8); i++)
+           {
+             in = (u32)buf[0] << (2 * 8);
+             in |= (u32)buf[1] << (1 * 8);
+             in |= (u32)buf[2] << (0 * 8);
+             in2 = (u32)buf[3] << (2 * 8);
+             in2 |= (u32)buf[4] << (1 * 8);
+             in2 |= (u32)buf[5] << (0 * 8);
+             outbuf[i*8+0] = bintoasc[(in >> 18) & 077];
+             outbuf[i*8+1] = bintoasc[(in >> 12) & 077];
+             outbuf[i*8+2] = bintoasc[(in >> 6) & 077];
+             outbuf[i*8+3] = bintoasc[(in >> 0) & 077];
+             outbuf[i*8+4] = bintoasc[(in2 >> 18) & 077];
+             outbuf[i*8+5] = bintoasc[(in2 >> 12) & 077];
+             outbuf[i*8+6] = bintoasc[(in2 >> 6) & 077];
+             outbuf[i*8+7] = bintoasc[(in2 >> 0) & 077];
+             buf+=6;
+             size-=6;
+           }
+
+         /* pgp doesn't like 72 here */
+         iobuf_write (a, outbuf, 64 + eollen);
+       }
+      while (size >= (64/4)*3);
+
+      /* restore eol for tail handling */
+      if (size)
+       memcpy (outbuf + 4, afx->eol, sizeof (afx->eol));
+    }
+
+  for (; size; buf++, size--)
+    {
+      radbuf[idx++] = *buf;
+      if (idx > 2)
+       {
+         idx = 0;
+         in = (u32)radbuf[0] << (2 * 8);
+         in |= (u32)radbuf[1] << (1 * 8);
+         in |= (u32)radbuf[2] << (0 * 8);
+         outbuf[0] = bintoasc[(in >> 18) & 077];
+         outbuf[1] = bintoasc[(in >> 12) & 077];
+         outbuf[2] = bintoasc[(in >> 6) & 077];
+         outbuf[3] = bintoasc[(in >> 0) & 077];
+         if (++idx2 >= (64/4))
+           { /* pgp doesn't like 72 here */
+             idx2=0;
+             iobuf_write (a, outbuf, 4 + eollen);
+           }
+         else
+           {
+             iobuf_write (a, outbuf, 4);
+           }
+       }
+    }
+
+  memcpy (afx->radbuf, radbuf, sizeof (afx->radbuf));
+  afx->idx = idx;
+  afx->idx2 = idx2;
+}
+
 /****************
  * This filter is used to handle the armor stuff
  */
@@ -1006,7 +1244,7 @@ armor_filter( void *opaque, int control,
 {
     size_t size = *ret_len;
     armor_filter_context_t *afx = opaque;
-    int rc=0, i, c;
+    int rc=0, c;
     byte radbuf[3];
     int  idx, idx2;
     size_t n=0;
@@ -1188,43 +1426,13 @@ armor_filter( void *opaque, int control,
            afx->status++;
            afx->idx = 0;
            afx->idx2 = 0;
-           afx->crc = CRCINIT;
-
+           gcry_md_reset (afx->crc_md);
        }
-       crc = afx->crc;
-       idx = afx->idx;
-       idx2 = afx->idx2;
-       for(i=0; i < idx; i++ )
-           radbuf[i] = afx->radbuf[i];
-
-       for(i=0; i < size; i++ )
-           crc = (crc << 8) ^ crc_table[((crc >> 16)&0xff) ^ buf[i]];
-       crc &= 0x00ffffff;
-
-       for( ; size; buf++, size-- ) {
-           radbuf[idx++] = *buf;
-           if( idx > 2 ) {
-               idx = 0;
-               c = bintoasc[(*radbuf >> 2) & 077];
-               iobuf_put(a, c);
-               c = bintoasc[(((*radbuf<<4)&060)|((radbuf[1] >> 4)&017))&077];
-               iobuf_put(a, c);
-               c = bintoasc[(((radbuf[1]<<2)&074)|((radbuf[2]>>6)&03))&077];
-               iobuf_put(a, c);
-               c = bintoasc[radbuf[2]&077];
-               iobuf_put(a, c);
-               if( ++idx2 >= (64/4) )
-                 { /* pgp doesn't like 72 here */
-                   iobuf_writestr(a,afx->eol);
-                   idx2=0;
-                 }
-           }
-       }
-       for(i=0; i < idx; i++ )
-           afx->radbuf[i] = radbuf[i];
-       afx->idx = idx;
-       afx->idx2 = idx2;
-       afx->crc  = crc;
+
+       if( size ) {
+           gcry_md_write (afx->crc_md, buf, size);
+           armor_output_buf_as_radix64 (afx, a, buf, size);
+        }
     }
     else if( control == IOBUFCTRL_INIT )
       {
@@ -1250,7 +1458,8 @@ armor_filter( void *opaque, int control,
        if( afx->cancel )
            ;
        else if( afx->status ) { /* pad, write cecksum, and bottom line */
-           crc = afx->crc;
+           gcry_md_final (afx->crc_md);
+           crc = get_afx_crc (afx);
            idx = afx->idx;
            idx2 = afx->idx2;
            if( idx ) {
@@ -1350,221 +1559,3 @@ make_radix64_string( const byte *data, size_t len )
     *p = 0;
     return buffer;
 }
-
-
-/***********************************************
- *  For the pipemode command we can't use the armor filter for various
- *  reasons, so we use this new unarmor_pump stuff to remove the armor
- */
-
-enum unarmor_state_e {
-    STA_init = 0,
-    STA_bypass,
-    STA_wait_newline,
-    STA_wait_dash,
-    STA_first_dash,
-    STA_compare_header,
-    STA_found_header_wait_newline,
-    STA_skip_header_lines,
-    STA_skip_header_lines_non_ws,
-    STA_read_data,
-    STA_wait_crc,
-    STA_read_crc,
-    STA_ready
-};
-
-struct unarmor_pump_s {
-    enum unarmor_state_e state;
-    byte val;
-    int checkcrc;
-    int pos;   /* counts from 0..3 */
-    u32 crc;
-    u32 mycrc; /* the one store in the data */
-};
-
-
-
-UnarmorPump
-unarmor_pump_new (void)
-{
-    UnarmorPump x;
-
-    if( !is_initialized )
-        initialize();
-    x = xmalloc_clear (sizeof *x);
-    return x;
-}
-
-void
-unarmor_pump_release (UnarmorPump x)
-{
-    xfree (x);
-}
-
-/*
- * Get the next character from the ascii armor taken from the IOBUF
- * created earlier by unarmor_pump_new().
- * Return:  c = Character
- *        256 = ignore this value
- *         -1 = End of current armor
- *         -2 = Premature EOF (not used)
- *         -3 = Invalid armor
- */
-int
-unarmor_pump (UnarmorPump x, int c)
-{
-    int rval = 256; /* default is to ignore the return value */
-
-    switch (x->state) {
-      case STA_init:
-        {
-            byte tmp[2];
-            tmp[0] = c;
-            tmp[1] = 0;
-            if ( is_armored (tmp) )
-                x->state = c == '-'? STA_first_dash : STA_wait_newline;
-            else {
-                x->state = STA_bypass;
-                return c;
-            }
-        }
-        break;
-      case STA_bypass:
-        return c; /* return here to avoid crc calculation */
-      case STA_wait_newline:
-        if (c == '\n')
-            x->state = STA_wait_dash;
-        break;
-      case STA_wait_dash:
-        x->state = c == '-'? STA_first_dash : STA_wait_newline;
-        break;
-      case STA_first_dash: /* just need for initialization */
-        x->pos = 0;
-        x->state = STA_compare_header; /* fall through */
-      case STA_compare_header:
-        if ( "-----BEGIN PGP SIGNATURE-----"[++x->pos] == c ) {
-            if ( x->pos == 28 )
-                x->state = STA_found_header_wait_newline;
-        }
-        else
-            x->state = c == '\n'? STA_wait_dash : STA_wait_newline;
-        break;
-      case STA_found_header_wait_newline:
-        /* to make CR,LF issues easier we simply allow for white space
-           behind the 5 dashes */
-        if ( c == '\n' )
-            x->state = STA_skip_header_lines;
-        else if ( c != '\r' && c != ' ' && c != '\t' )
-            x->state = STA_wait_dash; /* garbage after the header line */
-        break;
-      case STA_skip_header_lines:
-        /* i.e. wait for one empty line */
-        if ( c == '\n' ) {
-            x->state = STA_read_data;
-            x->crc = CRCINIT;
-            x->val = 0;
-            x->pos = 0;
-        }
-        else if ( c != '\r' && c != ' ' && c != '\t' )
-            x->state = STA_skip_header_lines_non_ws;
-        break;
-      case STA_skip_header_lines_non_ws:
-        /* like above but we already encountered non white space */
-        if ( c == '\n' )
-            x->state = STA_skip_header_lines;
-        break;
-      case STA_read_data:
-        /* fixme: we don't check for the trailing dash lines but rely
-         * on the armor stop characters */
-        if( c == '\n' || c == ' ' || c == '\r' || c == '\t' )
-            break; /* skip all kind of white space */
-
-        if( c == '=' ) { /* pad character: stop */
-            if( x->pos == 1 ) /* in this case val has some value */
-                rval = x->val;
-            x->state = STA_wait_crc;
-            break;
-        }
-
-        {
-            int c2;
-            if( (c = asctobin[(c2=c)]) == 255 ) {
-                log_error(_("invalid radix64 character %02X skipped\n"), c2);
-                break;
-            }
-        }
-
-        switch(x->pos) {
-          case 0:
-            x->val = c << 2;
-            break;
-          case 1:
-            x->val |= (c>>4)&3;
-            rval = x->val;
-            x->val = (c<<4)&0xf0;
-            break;
-          case 2:
-            x->val |= (c>>2)&15;
-            rval = x->val;
-            x->val = (c<<6)&0xc0;
-            break;
-          case 3:
-            x->val |= c&0x3f;
-            rval = x->val;
-            break;
-        }
-        x->pos = (x->pos+1) % 4;
-        break;
-      case STA_wait_crc:
-        if( c == '\n' || c == ' ' || c == '\r' || c == '\t' || c == '=' )
-            break; /* skip ws and pad characters */
-        /* assume that we are at the next line */
-        x->state = STA_read_crc;
-        x->pos = 0;
-        x->mycrc = 0; /* fall through */
-      case STA_read_crc:
-        if( (c = asctobin[c]) == 255 ) {
-            rval = -1; /* ready */
-            if( x->crc != x->mycrc ) {
-                log_info (_("CRC error; %06lX - %06lX\n"),
-                          (ulong)x->crc, (ulong)x->mycrc);
-                if ( invalid_crc() )
-                    rval = -3;
-            }
-            x->state = STA_ready; /* not sure whether this is correct */
-            break;
-        }
-
-        switch(x->pos) {
-          case 0:
-            x->val = c << 2;
-            break;
-          case 1:
-            x->val |= (c>>4)&3;
-            x->mycrc |= x->val << 16;
-            x->val = (c<<4)&0xf0;
-            break;
-          case 2:
-            x->val |= (c>>2)&15;
-            x->mycrc |= x->val << 8;
-            x->val = (c<<6)&0xc0;
-            break;
-          case 3:
-            x->val |= c&0x3f;
-            x->mycrc |= x->val;
-            break;
-        }
-        x->pos = (x->pos+1) % 4;
-        break;
-      case STA_ready:
-        rval = -1;
-        break;
-    }
-
-    if ( !(rval & ~255) ) { /* compute the CRC */
-        x->crc = (x->crc << 8) ^ crc_table[((x->crc >> 16)&0xff) ^ rval];
-        x->crc &= 0x00ffffff;
-    }
-
-    return rval;
-}
index b4e03d0..dd4ad54 100644 (file)
@@ -1297,7 +1297,7 @@ string_to_notation(const char *string,int is_utf8)
     }
 
   notation->name=xmalloc((s-string)+1);
-  strncpy(notation->name,string,s-string);
+  memcpy(notation->name,string,s-string);
   notation->name[s-string]='\0';
 
   if(!saw_at && !opt.expert)
@@ -1536,7 +1536,7 @@ do_signature( IOBUF out, int ctb, PKT_signature *sig )
   else
     iobuf_put( a, sig->version );
   if ( sig->version < 4 )
-    iobuf_put (a, 5 ); /* Constant */
+    iobuf_put (a, 5 ); /* Constant used by pre-v4 signatures. */
   iobuf_put (a, sig->sig_class );
   if ( sig->version < 4 )
     {
index 1445f4e..e9ea82e 100644 (file)
@@ -388,22 +388,23 @@ unescape_status_string (const unsigned char *s)
 }
 
 
-/* Take a 20 byte hexencoded string and put it into the provided
-   20 byte buffer FPR in binary format. */
-static int
-unhexify_fpr (const char *hexstr, unsigned char *fpr)
+/* Take a 20 or 32 byte hexencoded string and put it into the provided
+ * FPRLEN byte long buffer FPR in binary format.  Returns the actual
+ * used length of the FPR buffer or 0 on error.  */
+static unsigned int
+unhexify_fpr (const char *hexstr, unsigned char *fpr, unsigned int fprlen)
 {
   const char *s;
   int n;
 
   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
     ;
-  if ((*s && *s != ' ') || (n != 40))
+  if ((*s && *s != ' ') || !(n == 40 || n == 64))
     return 0; /* no fingerprint (invalid or wrong length). */
-  for (s=hexstr, n=0; *s && n < 20; s += 2, n++)
+  for (s=hexstr, n=0; *s && n < fprlen; s += 2, n++)
     fpr[n] = xtoi_2 (s);
 
-  return 1; /* okay */
+  return (n == 20 || n == 32)? n : 0;
 }
 
 /* Take the serial number from LINE and return it verbatim in a newly
@@ -488,8 +489,8 @@ agent_release_card_info (struct agent_card_info_s *info)
   xfree (info->disp_lang); info->disp_lang = NULL;
   xfree (info->pubkey_url); info->pubkey_url = NULL;
   xfree (info->login_data); info->login_data = NULL;
-  info->cafpr1valid = info->cafpr2valid = info->cafpr3valid = 0;
-  info->fpr1valid = info->fpr2valid = info->fpr3valid = 0;
+  info->cafpr1len = info->cafpr2len = info->cafpr3len = 0;
+  info->fpr1len = info->fpr2len = info->fpr3len = 0;
   for (i=0; i < DIM(info->private_do); i++)
     {
       xfree (info->private_do[i]);
@@ -608,6 +609,8 @@ learn_status_cb (void *opaque, const char *line)
                     parm->extcap.ki = abool;
                   else if (!strcmp (p, "aac"))
                     parm->extcap.aac = abool;
+                  else if (!strcmp (p, "bt"))
+                    parm->extcap.bt = abool;
                   else if (!strcmp (p, "kdf"))
                     parm->extcap.kdf = abool;
                   else if (!strcmp (p, "si"))
@@ -625,11 +628,11 @@ learn_status_cb (void *opaque, const char *line)
       while (spacep (line))
         line++;
       if (no == 1)
-        parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
+        parm->fpr1len = unhexify_fpr (line, parm->fpr1, sizeof parm->fpr1);
       else if (no == 2)
-        parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
+        parm->fpr2len = unhexify_fpr (line, parm->fpr2, sizeof parm->fpr2);
       else if (no == 3)
-        parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
+        parm->fpr3len = unhexify_fpr (line, parm->fpr3, sizeof parm->fpr3);
     }
   else if (keywordlen == 8 && !memcmp (keyword, "KEY-TIME", keywordlen))
     {
@@ -657,11 +660,11 @@ learn_status_cb (void *opaque, const char *line)
       if (strncmp (line, "OPENPGP.", 8))
         ;
       else if ((no = atoi (line+8)) == 1)
-        unhexify_fpr (hexgrp, parm->grp1);
+        unhexify_fpr (hexgrp, parm->grp1, sizeof parm->grp1);
       else if (no == 2)
-        unhexify_fpr (hexgrp, parm->grp2);
+        unhexify_fpr (hexgrp, parm->grp2, sizeof parm->grp2);
       else if (no == 3)
-        unhexify_fpr (hexgrp, parm->grp3);
+        unhexify_fpr (hexgrp, parm->grp3, sizeof parm->grp3);
     }
   else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
     {
@@ -671,11 +674,11 @@ learn_status_cb (void *opaque, const char *line)
       while (spacep (line))
         line++;
       if (no == 1)
-        parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
+        parm->cafpr1len = unhexify_fpr (line, parm->cafpr1,sizeof parm->cafpr1);
       else if (no == 2)
-        parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
+        parm->cafpr2len = unhexify_fpr (line, parm->cafpr2,sizeof parm->cafpr2);
       else if (no == 3)
-        parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
+        parm->cafpr3len = unhexify_fpr (line, parm->cafpr3,sizeof parm->cafpr3);
     }
   else if (keywordlen == 8 && !memcmp (keyword, "KEY-ATTR", keywordlen))
     {
@@ -823,6 +826,8 @@ agent_keytocard (const char *hexgrip, int keyno, int force,
 
   return rc;
 }
+
+
 \f
 /* Call the agent to retrieve a data object.  This function returns
    the data in the same structure as used by the learn command.  It is
index 7314ae8..1055b5e 100644 (file)
@@ -39,15 +39,15 @@ struct agent_card_info_s
   char *pubkey_url;  /* malloced. */
   char *login_data;  /* malloced. */
   char *private_do[4]; /* malloced. */
-  char cafpr1valid;
-  char cafpr2valid;
-  char cafpr3valid;
+  char cafpr1len;     /* Length of the CA-fingerprint or 0 if invalid.  */
+  char cafpr2len;
+  char cafpr3len;
   char cafpr1[20];
   char cafpr2[20];
   char cafpr3[20];
-  char fpr1valid;
-  char fpr2valid;
-  char fpr3valid;
+  unsigned char fpr1len; /* Length of the fingerprint or 0 if invalid.  */
+  unsigned char fpr2len;
+  unsigned char fpr3len;
   char fpr1[20];
   char fpr2[20];
   char fpr3[20];
@@ -69,6 +69,7 @@ struct agent_card_info_s
     unsigned int ki:1;     /* Key import available.  */
     unsigned int aac:1;    /* Algorithm attributes are changeable.  */
     unsigned int kdf:1;    /* KDF object to support PIN hashing available.  */
+    unsigned int bt:1;     /* Button for confirmation available.  */
   } extcap;
   unsigned int status_indicator;
 };
index 9bc90fb..8f83c08 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
@@ -406,6 +412,8 @@ ks_status_cb (void *opaque, const char *line)
         warn = _("Tor is not running");
       else if ((s2 = has_leading_keyword (s, "tor_config_problem")))
         warn = _("Tor is not properly configured");
+      else if ((s2 = has_leading_keyword (s, "dns_config_problem")))
+        warn = _("DNS is not properly configured");
       else
         warn = NULL;
 
@@ -600,6 +608,12 @@ gpg_dirmngr_ks_search (ctrl_t ctrl, const char *searchstr,
                         NULL, NULL, ks_status_cb, &stparm);
   if (!err)
     err = cb (cb_value, 0, NULL);  /* Send EOF.  */
+  else if (parm.stparm->source)
+    {
+      /* Error but we received a SOURCE status.  Tell via callback but
+       * ignore errors.  */
+      parm.data_cb (parm.data_cb_value, 1, parm.stparm->source);
+    }
 
   xfree (get_membuf (&parm.saveddata, NULL));
   xfree (parm.helpbuf);
@@ -642,6 +656,7 @@ ks_get_data_cb (void *opaque, const void *data, size_t datalen)
 
    If R_SOURCE is not NULL the source of the data is stored as a
    malloced string there.  If a source is not known NULL is stored.
+   Note that this may even be returned after an error.
 
    If there are too many patterns the function returns an error.  That
    could be fixed by issuing several search commands or by
@@ -729,13 +744,13 @@ gpg_dirmngr_ks_get (ctrl_t ctrl, char **pattern,
   *r_fp = parm.memfp;
   parm.memfp = NULL;
 
-  if (r_source)
+
+ leave:
+  if (r_source && stparm.source)
     {
       *r_source = stparm.source;
       stparm.source = NULL;
     }
-
- leave:
   es_fclose (parm.memfp);
   xfree (stparm.source);
   xfree (line);
@@ -1068,7 +1083,7 @@ ks_put_inq_cb (void *opaque, const char *line)
 
 /* Send a key to the configured server.  {DATA,DATLEN} contains the
    key in OpenPGP binary transport format.  If KEYBLOCK is not NULL it
-   has the internal representaion of that key; this is for example
+   has the internal representation of that key; this is for example
    used to convey meta data to LDAP keyservers.  */
 gpg_error_t
 gpg_dirmngr_ks_put (ctrl_t ctrl, void *data, size_t datalen, kbnode_t keyblock)
@@ -1365,7 +1380,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 +1388,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 b7eedc0..a1a099d 100644 (file)
@@ -216,6 +216,7 @@ get_manufacturer (unsigned int no)
 
     case 0x1337: return "Warsaw Hackerspace";
     case 0x2342: return "warpzone"; /* hackerspace Muenster.  */
+    case 0x4354: return "Confidential Technologies";   /* cotech.de */
     case 0x63AF: return "Trustica";
     case 0xBD0E: return "Paranoidlabs";
     case 0xF517: return "FSIJ";
@@ -231,13 +232,14 @@ get_manufacturer (unsigned int no)
 
 
 static void
-print_sha1_fpr (estream_t fp, const unsigned char *fpr)
+print_shax_fpr (estream_t fp, const unsigned char *fpr, unsigned int fprlen)
 {
   int i;
 
   if (fpr)
     {
-      for (i=0; i < 20 ; i+=2, fpr += 2 )
+      /* FIXME: Fix formatting for FPRLEN != 20 */
+      for (i=0; i < fprlen ; i+=2, fpr += 2 )
         {
           if (i == 10 )
             tty_fprintf (fp, " ");
@@ -251,13 +253,14 @@ print_sha1_fpr (estream_t fp, const unsigned char *fpr)
 
 
 static void
-print_sha1_fpr_colon (estream_t fp, const unsigned char *fpr)
+print_shax_fpr_colon (estream_t fp,
+                      const unsigned char *fpr, unsigned int fprlen)
 {
   int i;
 
   if (fpr)
     {
-      for (i=0; i < 20 ; i++, fpr++)
+      for (i=0; i < fprlen ; i++, fpr++)
         es_fprintf (fp, "%02X", *fpr);
     }
   es_putc (':', fp);
@@ -273,7 +276,7 @@ print_keygrip (estream_t fp, const unsigned char *grp)
     {
       tty_fprintf (fp, "      keygrip ....: ");
       for (i=0; i < 20 ; i++, grp++)
-        es_fprintf (fp, "%02X", *grp);
+        tty_fprintf (fp, "%02X", *grp);
       tty_fprintf (fp, "\n");
     }
 }
@@ -356,25 +359,25 @@ print_isoname (estream_t fp, const char *text,
 
 /* Return true if the SHA1 fingerprint FPR consists only of zeroes. */
 static int
-fpr_is_zero (const char *fpr)
+fpr_is_zero (const char *fpr, unsigned int fprlen)
 {
   int i;
 
-  for (i=0; i < 20 && !fpr[i]; i++)
+  for (i=0; i < fprlen && !fpr[i]; i++)
     ;
-  return (i == 20);
+  return (i == fprlen);
 }
 
 
-/* Return true if the SHA1 fingerprint FPR consists only of 0xFF. */
+/* Return true if the fingerprint FPR consists only of 0xFF. */
 static int
-fpr_is_ff (const char *fpr)
+fpr_is_ff (const char *fpr, unsigned int fprlen)
 {
   int i;
 
-  for (i=0; i < 20 && fpr[i] == '\xff'; i++)
+  for (i=0; i < fprlen && fpr[i] == '\xff'; i++)
     ;
-  return (i == 20);
+  return (i == fprlen);
 }
 
 
@@ -389,6 +392,7 @@ current_card_status (ctrl_t ctrl, estream_t fp,
   int rc;
   unsigned int uval;
   const unsigned char *thefpr;
+  unsigned int thefprlen;
   int i;
 
   if (serialno && serialnobuflen)
@@ -521,22 +525,25 @@ current_card_status (ctrl_t ctrl, estream_t fp,
         }
 
       es_fputs ("cafpr:", fp);
-      print_sha1_fpr_colon (fp, info.cafpr1valid? info.cafpr1:NULL);
-      print_sha1_fpr_colon (fp, info.cafpr2valid? info.cafpr2:NULL);
-      print_sha1_fpr_colon (fp, info.cafpr3valid? info.cafpr3:NULL);
+      print_shax_fpr_colon (fp, info.cafpr1len? info.cafpr1:NULL,
+                            info.cafpr2len);
+      print_shax_fpr_colon (fp, info.cafpr2len? info.cafpr2:NULL,
+                            info.cafpr2len);
+      print_shax_fpr_colon (fp, info.cafpr3len? info.cafpr3:NULL,
+                            info.cafpr3len);
       es_putc ('\n', fp);
       es_fputs ("fpr:", fp);
-      print_sha1_fpr_colon (fp, info.fpr1valid? info.fpr1:NULL);
-      print_sha1_fpr_colon (fp, info.fpr2valid? info.fpr2:NULL);
-      print_sha1_fpr_colon (fp, info.fpr3valid? info.fpr3:NULL);
+      print_shax_fpr_colon (fp, info.fpr1len? info.fpr1:NULL, info.fpr1len);
+      print_shax_fpr_colon (fp, info.fpr2len? info.fpr2:NULL, info.fpr2len);
+      print_shax_fpr_colon (fp, info.fpr3len? info.fpr3:NULL, info.fpr3len);
       es_putc ('\n', fp);
       es_fprintf (fp, "fprtime:%lu:%lu:%lu:\n",
                (unsigned long)info.fpr1time, (unsigned long)info.fpr2time,
                (unsigned long)info.fpr3time);
       es_fputs ("grp:", fp);
-      print_sha1_fpr_colon (fp, info.grp1);
-      print_sha1_fpr_colon (fp, info.grp2);
-      print_sha1_fpr_colon (fp, info.grp3);
+      print_shax_fpr_colon (fp, info.grp1, sizeof info.grp1);
+      print_shax_fpr_colon (fp, info.grp2, sizeof info.grp2);
+      print_shax_fpr_colon (fp, info.grp3, sizeof info.grp3);
       es_putc ('\n', fp);
     }
   else
@@ -566,20 +573,20 @@ current_card_status (ctrl_t ctrl, estream_t fp,
         print_name (fp, "Private DO 3 .....: ", info.private_do[2]);
       if (info.private_do[3])
         print_name (fp, "Private DO 4 .....: ", info.private_do[3]);
-      if (info.cafpr1valid)
+      if (info.cafpr1len)
         {
           tty_fprintf (fp, "CA fingerprint %d .:", 1);
-          print_sha1_fpr (fp, info.cafpr1);
+          print_shax_fpr (fp, info.cafpr1, info.cafpr1len);
         }
-      if (info.cafpr2valid)
+      if (info.cafpr2len)
         {
           tty_fprintf (fp, "CA fingerprint %d .:", 2);
-          print_sha1_fpr (fp, info.cafpr2);
+          print_shax_fpr (fp, info.cafpr2, info.cafpr2len);
         }
-      if (info.cafpr3valid)
+      if (info.cafpr3len)
         {
           tty_fprintf (fp, "CA fingerprint %d .:", 3);
-          print_sha1_fpr (fp, info.cafpr3);
+          print_shax_fpr (fp, info.cafpr3, info.cafpr3len);
         }
       tty_fprintf (fp,    "Signature PIN ....: %s\n",
                    info.chv1_cached? _("not forced"): _("forced"));
@@ -612,24 +619,24 @@ current_card_status (ctrl_t ctrl, estream_t fp,
                    info.chvretry[0], info.chvretry[1], info.chvretry[2]);
       tty_fprintf (fp,    "Signature counter : %lu\n", info.sig_counter);
       tty_fprintf (fp, "Signature key ....:");
-      print_sha1_fpr (fp, info.fpr1valid? info.fpr1:NULL);
-      if (info.fpr1valid && info.fpr1time)
+      print_shax_fpr (fp, info.fpr1len? info.fpr1:NULL, info.fpr1len);
+      if (info.fpr1len && info.fpr1time)
         {
           tty_fprintf (fp, "      created ....: %s\n",
                        isotimestamp (info.fpr1time));
           print_keygrip (fp, info.grp1);
         }
       tty_fprintf (fp, "Encryption key....:");
-      print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL);
-      if (info.fpr2valid && info.fpr2time)
+      print_shax_fpr (fp, info.fpr2len? info.fpr2:NULL, info.fpr2len);
+      if (info.fpr2len && info.fpr2time)
         {
           tty_fprintf (fp, "      created ....: %s\n",
                        isotimestamp (info.fpr2time));
           print_keygrip (fp, info.grp2);
         }
       tty_fprintf (fp, "Authentication key:");
-      print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL);
-      if (info.fpr3valid && info.fpr3time)
+      print_shax_fpr (fp, info.fpr3len? info.fpr3:NULL, info.fpr3len);
+      if (info.fpr3len && info.fpr3time)
         {
           tty_fprintf (fp, "      created ....: %s\n",
                        isotimestamp (info.fpr3time));
@@ -637,12 +644,14 @@ current_card_status (ctrl_t ctrl, estream_t fp,
         }
       tty_fprintf (fp, "General key info..: ");
 
-      thefpr = (info.fpr1valid? info.fpr1 : info.fpr2valid? info.fpr2 :
-                info.fpr3valid? info.fpr3 : NULL);
-      /* If the fingerprint is all 0xff, the key has no asssociated
+      thefpr = (info.fpr1len? info.fpr1 : info.fpr2len? info.fpr2 :
+                info.fpr3len? info.fpr3 : NULL);
+      thefprlen = (info.fpr1len? info.fpr1len : info.fpr2len? info.fpr2len :
+                   info.fpr3len? info.fpr3len : 0);
+      /* If the fingerprint is all 0xff, the key has no associated
          OpenPGP certificate.  */
-      if ( thefpr && !fpr_is_ff (thefpr)
-           && !get_pubkey_byfprint (ctrl, pk, &keyblock, thefpr, 20))
+      if ( thefpr && !fpr_is_ff (thefpr, thefprlen)
+           && !get_pubkey_byfprint (ctrl, pk, &keyblock, thefpr, thefprlen))
         {
           print_pubkey_info (ctrl, fp, pk);
           if (keyblock)
@@ -666,7 +675,7 @@ card_status (ctrl_t ctrl, estream_t fp, const char *serialno)
 {
   int err;
   strlist_t card_list, sl;
-  char *serialno0;
+  char *serialno0, *serialno1;
   int all_cards = 0;
 
   if (serialno == NULL)
@@ -692,8 +701,6 @@ card_status (ctrl_t ctrl, estream_t fp, const char *serialno)
 
   for (sl = card_list; sl; sl = sl->next)
     {
-      char *serialno1;
-
       if (!all_cards && strcmp (serialno, sl->d))
         continue;
 
@@ -714,7 +721,8 @@ card_status (ctrl_t ctrl, estream_t fp, const char *serialno)
     }
 
   /* Select the original card again.  */
-  err = agent_scd_serialno (&serialno0, serialno0);
+  err = agent_scd_serialno (&serialno1, serialno0);
+  xfree (serialno1);
 
  leave:
   xfree (serialno0);
@@ -845,9 +853,10 @@ fetch_url (ctrl_t ctrl)
           rc = keyserver_fetch (ctrl, sl, KEYORG_URL);
           free_strlist (sl);
         }
-      else if (info.fpr1valid)
+      else if (info.fpr1len)
        {
-          rc = keyserver_import_fprint (ctrl, info.fpr1, 20, opt.keyserver, 0);
+          rc = keyserver_import_fprint (ctrl, info.fpr1, info.fpr1len,
+                                        opt.keyserver, 0);
        }
     }
 
@@ -1309,11 +1318,11 @@ static void
 show_card_key_info (struct agent_card_info_s *info)
 {
   tty_fprintf (NULL, "Signature key ....:");
-  print_sha1_fpr (NULL, info->fpr1valid? info->fpr1:NULL);
+  print_shax_fpr (NULL, info->fpr1len? info->fpr1:NULL, info->fpr1len);
   tty_fprintf (NULL, "Encryption key....:");
-  print_sha1_fpr (NULL, info->fpr2valid? info->fpr2:NULL);
+  print_shax_fpr (NULL, info->fpr2len? info->fpr2:NULL, info->fpr2len);
   tty_fprintf (NULL, "Authentication key:");
-  print_sha1_fpr (NULL, info->fpr3valid? info->fpr3:NULL);
+  print_shax_fpr (NULL, info->fpr3len? info->fpr3:NULL, info->fpr3len);
   tty_printf ("\n");
 }
 
@@ -1324,9 +1333,9 @@ replace_existing_key_p (struct agent_card_info_s *info, int keyno)
 {
   log_assert (keyno >= 0 && keyno <= 3);
 
-  if ((keyno == 1 && info->fpr1valid)
-      || (keyno == 2 && info->fpr2valid)
-      || (keyno == 3 && info->fpr3valid))
+  if ((keyno == 1 && info->fpr1len)
+      || (keyno == 2 && info->fpr2len)
+      || (keyno == 3 && info->fpr3len))
     {
       tty_printf ("\n");
       log_info ("WARNING: such a key has already been stored on the card!\n");
@@ -1620,9 +1629,9 @@ generate_card_keys (ctrl_t ctrl)
   else
     want_backup = 0;
 
-  if ( (info.fpr1valid && !fpr_is_zero (info.fpr1))
-       || (info.fpr2valid && !fpr_is_zero (info.fpr2))
-       || (info.fpr3valid && !fpr_is_zero (info.fpr3)))
+  if ( (info.fpr1len && !fpr_is_zero (info.fpr1, info.fpr1len))
+       || (info.fpr2len && !fpr_is_zero (info.fpr2, info.fpr2len))
+       || (info.fpr3len && !fpr_is_zero (info.fpr3, info.fpr3len)))
     {
       tty_printf ("\n");
       log_info (_("Note: keys are already stored on the card!\n"));
@@ -2101,6 +2110,49 @@ kdf_setup (const char *args)
  leave:
   agent_release_card_info (&info);
 }
+
+static void
+uif (int arg_number, const char *arg_rest)
+{
+  struct agent_card_info_s info;
+  int feature_available;
+  gpg_error_t err;
+  char name[100];
+  unsigned char data[2];
+
+  memset (&info, 0, sizeof info);
+
+  err = agent_scd_getattr ("EXTCAP", &info);
+  if (err)
+    {
+      log_error (_("error getting card info: %s\n"), gpg_strerror (err));
+      return;
+    }
+
+  feature_available = info.extcap.bt;
+  agent_release_card_info (&info);
+
+  if (!feature_available)
+    {
+      log_error (_("This command is not supported by this card\n"));
+      tty_printf ("\n");
+      return;
+    }
+
+  snprintf (name, sizeof name, "UIF-%d", arg_number);
+  if ( !strcmp (arg_rest, "off") )
+    data[0] = 0x00;
+  else if ( !strcmp (arg_rest, "on") )
+    data[0] = 0x01;
+  else if ( !strcmp (arg_rest, "permanent") )
+    data[0] = 0x02;
+
+  data[1] = 0x20;
+
+  err = agent_scd_setattr (name, data, 2, NULL);
+  if (err)
+    log_error (_("error for setup UIF: %s\n"), gpg_strerror (err));
+}
 \f
 /* Data used by the command parser.  This needs to be outside of the
    function scope to allow readline based command completion.  */
@@ -2111,7 +2163,7 @@ enum cmdids
     cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR,
     cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT,
     cmdREADCERT, cmdUNBLOCK, cmdFACTORYRESET, cmdKDFSETUP,
-    cmdKEYATTR,
+    cmdKEYATTR, cmdUIF,
     cmdINVCMD
   };
 
@@ -2143,10 +2195,11 @@ static struct
     { "generate", cmdGENERATE, 1, N_("generate new keys")},
     { "passwd"  , cmdPASSWD, 0, N_("menu to change or unblock the PIN")},
     { "verify"  , cmdVERIFY, 0, N_("verify the PIN and list all data")},
-    { "unblock" , cmdUNBLOCK,0, N_("unblock the PIN using a Reset Code") },
+    { "unblock" , cmdUNBLOCK,0, N_("unblock the PIN using a Reset Code")},
     { "factory-reset", cmdFACTORYRESET, 1, N_("destroy all keys and data")},
     { "kdf-setup", cmdKDFSETUP, 1, N_("setup KDF for PIN authentication")},
     { "key-attr", cmdKEYATTR, 1, N_("change the key attribute")},
+    { "uif", cmdUIF, 1, N_("change the User Interaction Flag")},
     /* Note, that we do not announce these command yet. */
     { "privatedo", cmdPRIVATEDO, 0, NULL },
     { "readcert", cmdREADCERT, 0, NULL },
@@ -2438,6 +2491,14 @@ card_edit (ctrl_t ctrl, strlist_t commands)
           key_attr ();
           break;
 
+        case cmdUIF:
+          if ( arg_number < 1 || arg_number > 3 )
+            tty_printf ("usage: uif N [on|off|permanent]\n"
+                        "       1 <= N <= 3\n");
+          else
+            uif (arg_number, arg_rest);
+          break;
+
         case cmdQUIT:
           goto leave;
 
index f9a996c..b14b854 100644 (file)
@@ -278,7 +278,7 @@ do_flush (cipher_filter_context_t *cfx, iobuf_t a, byte *buf, size_t size)
           if (DBG_FILTER)
             log_debug ("chunksize %ju reached;"
                        " cur buflen=%zu using %zu of %zu\n",
-                       (uintmax_t)cfx->chunksize, (uintmax_t)cfx->buflen,
+                       cfx->chunksize, cfx->buflen,
                        n1, n);
           n = n1;
         }
index 4354426..ed68b3f 100644 (file)
--- a/g10/cpr.c
+++ b/g10/cpr.c
@@ -187,7 +187,7 @@ write_status_text (int no, const char *text)
 }
 
 
-/* Write a status line with code NO followed by the outout of the
+/* Write a status line with code NO followed by the output of the
  * printf style FORMAT.  The caller needs to make sure that LFs and
  * CRs are not printed.  */
 void
index a3151b5..4d9dc86 100644 (file)
@@ -42,7 +42,7 @@ static int decode_filter ( void *opaque, int control, IOBUF a,
 /* Our context object.  */
 struct decode_filter_context_s
 {
-  /* Recounter (max value is 2).  We need it becuase we do not know
+  /* Recounter (max value is 2).  We need it because we do not know
    * whether the iobuf or the outer control code frees this object
    * first.  */
   int  refcount;
@@ -551,31 +551,42 @@ fill_buffer (decode_filter_ctx_t dfx, iobuf_t stream,
              byte *buffer, size_t nbytes, size_t offset)
 {
   size_t nread = offset;
-  int c;
+  size_t curr;
+  int ret;
 
   if (dfx->partial)
     {
-      for (; nread < nbytes; nread++ )
+      while (nread < nbytes)
         {
-          if ((c = iobuf_get (stream)) == -1)
+          curr = nbytes - nread;
+
+          ret = iobuf_read (stream, &buffer[nread], curr);
+          if (ret == -1)
             {
               dfx->eof_seen = 1; /* Normal EOF. */
               break;
             }
-          buffer[nread] = c;
+
+          nread += ret;
         }
     }
   else
     {
-      for (; nread < nbytes && dfx->length; nread++, dfx->length--)
+      while (nread < nbytes && dfx->length)
         {
-          c = iobuf_get (stream);
-          if (c == -1)
+          curr = nbytes - nread;
+          if (curr > dfx->length)
+            curr = dfx->length;
+
+          ret = iobuf_read (stream, &buffer[nread], curr);
+          if (ret == -1)
             {
               dfx->eof_seen = 3; /* Premature EOF. */
               break;
             }
-          buffer[nread] = c;
+
+          nread += ret;
+          dfx->length -= ret;
         }
       if (!dfx->length)
         dfx->eof_seen = 1; /* Normal EOF.  */
@@ -647,7 +658,7 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
    * case when a chunk ends within the buffer.  */
   if (DBG_FILTER)
     log_debug ("decrypt: chunklen=%ju total=%ju size=%zu len=%zu%s\n",
-               (uintmax_t)dfx->chunklen, (uintmax_t)dfx->total, size, len,
+               dfx->chunklen, dfx->total, size, len,
                dfx->eof_seen? " eof":"");
 
   while (len && dfx->chunklen + len >= dfx->chunksize)
@@ -683,7 +694,7 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
       len -= n;
 
       if (DBG_FILTER)
-        log_debug ("ndecrypted: %zu (nchunk=%zu) bytes left: %zu at off=%zu\n",
+        log_debug ("ndecrypted: %zu (nchunk=%ju) bytes left: %zu at off=%zu\n",
                    totallen, dfx->chunklen, len, off);
 
       /* Check the tag.  */
@@ -765,7 +776,7 @@ aead_underflow (decode_filter_ctx_t dfx, iobuf_t a, byte *buf, size_t *ret_len)
       dfx->chunklen += len;
       dfx->total += len;
       if (DBG_FILTER)
-        log_debug ("ndecrypted: %zu (nchunk=%zu)\n", totallen, dfx->chunklen);
+        log_debug ("ndecrypted: %zu (nchunk=%ju)\n", totallen, dfx->chunklen);
     }
 
   if (dfx->eof_seen)
@@ -873,7 +884,6 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
   decode_filter_ctx_t dfx = opaque;
   size_t n, size = *ret_len;
   int rc = 0;
-  int c;
 
   /* Note: We need to distinguish between a partial and a fixed length
      packet.  The first is the usual case as created by GPG.  However
@@ -894,25 +904,7 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
       log_assert (size > 44); /* Our code requires at least this size.  */
 
       /* Get at least 22 bytes and put it ahead in the buffer.  */
-      if (dfx->partial)
-        {
-          for (n=22; n < 44; n++)
-            {
-              if ( (c = iobuf_get(a)) == -1 )
-                break;
-              buf[n] = c;
-            }
-        }
-      else
-        {
-          for (n=22; n < 44 && dfx->length; n++, dfx->length--)
-            {
-              c = iobuf_get (a);
-              if (c == -1)
-                break; /* Premature EOF.  */
-              buf[n] = c;
-            }
-        }
+      n = fill_buffer (dfx, a, buf, 44, 22);
       if (n == 44)
         {
           /* We have enough stuff - flush the holdback buffer.  */
@@ -923,37 +915,11 @@ mdc_decode_filter (void *opaque, int control, IOBUF a,
            }
           else
             {
-
               memcpy (buf, dfx->holdback, 22);
            }
+
           /* Fill up the buffer. */
-          if (dfx->partial)
-            {
-              for (; n < size; n++ )
-                {
-                  if ( (c = iobuf_get(a)) == -1 )
-                    {
-                      dfx->eof_seen = 1; /* Normal EOF. */
-                      break;
-                    }
-                  buf[n] = c;
-                }
-            }
-          else
-            {
-              for (; n < size && dfx->length; n++, dfx->length--)
-                {
-                  c = iobuf_get(a);
-                  if (c == -1)
-                    {
-                      dfx->eof_seen = 3; /* Premature EOF. */
-                      break;
-                    }
-                  buf[n] = c;
-                }
-              if (!dfx->length)
-                dfx->eof_seen = 1; /* Normal EOF.  */
-            }
+          n = fill_buffer (dfx, a, buf, size, n);
 
           /* Move the trailing 22 bytes back to the holdback buffer.  We
              have at least 44 bytes thus a memmove is not needed.  */
@@ -1008,7 +974,7 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
   decode_filter_ctx_t fc = opaque;
   size_t size = *ret_len;
   size_t n;
-  int c, rc = 0;
+  int rc = 0;
 
 
   if ( control == IOBUFCTRL_UNDERFLOW && fc->eof_seen )
@@ -1020,34 +986,7 @@ decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
     {
       log_assert (a);
 
-      if (fc->partial)
-        {
-          for (n=0; n < size; n++ )
-            {
-              c = iobuf_get(a);
-              if (c == -1)
-                {
-                  fc->eof_seen = 1; /* Normal EOF. */
-                  break;
-                }
-              buf[n] = c;
-            }
-        }
-      else
-        {
-          for (n=0; n < size && fc->length; n++, fc->length--)
-            {
-              c = iobuf_get(a);
-              if (c == -1)
-                {
-                  fc->eof_seen = 3; /* Premature EOF. */
-                  break;
-                }
-              buf[n] = c;
-            }
-          if (!fc->length)
-            fc->eof_seen = 1; /* Normal EOF.  */
-        }
+      n = fill_buffer (fc, a, buf, size, 0);
       if (n)
         {
           if (fc->cipher_hd)
index 04a9ab2..972d13c 100644 (file)
@@ -732,7 +732,7 @@ encrypt_crypt (ctrl_t ctrl, int filefd, const char *filename,
 
       /* In case 3DES has been selected, print a warning if any key
          does not have a preference for AES.  This should help to
-         indentify why encrypting to several recipients falls back to
+         identify why encrypting to several recipients falls back to
          3DES. */
       if (opt.verbose && cfx.dek->algo == CIPHER_ALGO_3DES)
         warn_missing_aes_from_pklist (pk_list);
@@ -1003,7 +1003,7 @@ encrypt_filter (void *opaque, int control,
 
               /* In case 3DES has been selected, print a warning if
                  any key does not have a preference for AES.  This
-                 should help to indentify why encrypting to several
+                 should help to identify why encrypting to several
                  recipients falls back to 3DES. */
               if (opt.verbose
                   && efx->cfx.dek->algo == CIPHER_ALGO_3DES)
index c538dc1..d53be99 100644 (file)
@@ -41,6 +41,8 @@
 #include "../common/init.h"
 #include "trustdb.h"
 #include "call-agent.h"
+#include "key-clean.h"
+
 
 /* An object to keep track of subkeys. */
 struct subkey_list_s
@@ -95,7 +97,7 @@ cleanup_export_globals (void)
 }
 
 
-/* Option parser for export options.  See parse_options fro
+/* Option parser for export options.  See parse_options for
    details.  */
 int
 parse_export_options(char *str,unsigned int *options,int noisy)
@@ -112,6 +114,8 @@ parse_export_options(char *str,unsigned int *options,int noisy)
        N_("remove unusable parts from key during export")},
       {"export-minimal",EXPORT_MINIMAL|EXPORT_CLEAN,NULL,
        N_("remove as much as possible from key during export")},
+      {"export-drop-uids", EXPORT_DROP_UIDS, NULL,
+       N_("Do not export user id or attribute packets")},
 
       {"export-pka", EXPORT_PKA_FORMAT, NULL, NULL },
       {"export-dane", EXPORT_DANE_FORMAT, NULL, NULL },
@@ -134,14 +138,20 @@ parse_export_options(char *str,unsigned int *options,int noisy)
   int rc;
 
   rc = parse_options (str, options, export_opts, noisy);
-  if (rc && (*options & EXPORT_BACKUP))
+  if (!rc)
+    return 0;
+
+  /* Alter other options we want or don't want for restore.  */
+  if ((*options & EXPORT_BACKUP))
     {
-      /* Alter other options we want or don't want for restore.  */
       *options |= (EXPORT_LOCAL_SIGS | EXPORT_ATTRIBUTES
                    | EXPORT_SENSITIVE_REVKEYS);
       *options &= ~(EXPORT_CLEAN | EXPORT_MINIMAL
                     | EXPORT_PKA_FORMAT | EXPORT_DANE_FORMAT);
     }
+  /* Dropping uids also means to drop attributes.  */
+  if ((*options & EXPORT_DROP_UIDS))
+    *options &= ~(EXPORT_ATTRIBUTES);
   return rc;
 }
 
@@ -1169,7 +1179,7 @@ print_status_exported (PKT_public_key *pk)
  * passphrase-protected.  Otherwise, store secret key material in the
  * clear.
  *
- * CACHE_NONCE_ADDR is used to share nonce for multple key retrievals.
+ * CACHE_NONCE_ADDR is used to share nonce for multiple key retrievals.
  */
 gpg_error_t
 receive_seckey_from_agent (ctrl_t ctrl, gcry_cipher_hd_t cipherhd,
@@ -1459,7 +1469,7 @@ print_pka_or_dane_records (iobuf_t out, kbnode_t keyblock, PKT_public_key *pk,
         continue;
 
       xfree (mbox);
-      mbox = mailbox_from_userid (uid->name);
+      mbox = mailbox_from_userid (uid->name, 0);
       if (!mbox)
         continue;
 
@@ -1573,7 +1583,7 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
       if (node->pkt->pkttype == PKT_COMMENT)
         continue;
 
-      /* Skip ring trust packets - they should not ne here anyway.  */
+      /* Skip ring trust packets - they should not be here anyway.  */
       if (node->pkt->pkttype == PKT_RING_TRUST)
         continue;
 
@@ -1648,6 +1658,19 @@ do_export_one_keyblock (ctrl_t ctrl, kbnode_t keyblock, u32 *keyid,
             }
         }
 
+      /* Don't export user ids (and attributes)?  This is not RFC-4880
+       * compliant but we allow it anyway.  */
+      if ((options & EXPORT_DROP_UIDS)
+          && node->pkt->pkttype == PKT_USER_ID)
+        {
+          /* Skip until we get to something that is not a user id (or
+           * attrib) or a signature on it.  */
+          while (kbctx->next && kbctx->next->pkt->pkttype == PKT_SIGNATURE)
+            kbctx = kbctx->next;
+
+          continue;
+        }
+
       /* Don't export attribs? */
       if (!(options & EXPORT_ATTRIBUTES)
           && node->pkt->pkttype == PKT_USER_ID
@@ -2001,12 +2024,19 @@ do_export_stream (ctrl_t ctrl, iobuf_t out, strlist_t users, int secret,
         }
 
       /* Always do the cleaning on the public key part if requested.
-       * Note that both export-clean and export-minimal only apply to
-       * UID sigs (0x10, 0x11, 0x12, and 0x13).  A designated
-       * revocation is never stripped, even with export-minimal set.  */
+       * A designated revocation is never stripped, even with
+       * export-minimal set.  */
       if ((options & EXPORT_CLEAN))
-        clean_key (ctrl, keyblock, opt.verbose,
-                   (options&EXPORT_MINIMAL), NULL, NULL);
+        {
+          merge_keys_and_selfsig (ctrl, keyblock);
+          clean_all_uids (ctrl, keyblock, opt.verbose,
+                          (options&EXPORT_MINIMAL), NULL, NULL);
+          clean_all_subkeys (ctrl, keyblock, opt.verbose,
+                             (options&EXPORT_MINIMAL)? KEY_CLEAN_ALL
+                             /**/                    : KEY_CLEAN_AUTHENCR,
+                             NULL, NULL);
+          commit_kbnode (&keyblock);
+        }
 
       if (export_keep_uid)
         {
index 6daf273..b2ef382 100644 (file)
@@ -61,7 +61,7 @@ typedef struct {
 
     byte radbuf[4];
     int idx, idx2;
-    u32 crc;
+    gcry_md_hd_t crc_md;
 
     int status;            /* an internal state flag */
     int cancel;
@@ -69,8 +69,6 @@ typedef struct {
     int pending_lf;        /* used together with faked */
 } armor_filter_context_t;
 
-struct unarmor_pump_s;
-typedef struct unarmor_pump_s *UnarmorPump;
 
 
 struct compress_filter_context_s {
@@ -172,9 +170,6 @@ armor_filter_context_t *new_armor_context (void);
 void release_armor_context (armor_filter_context_t *afx);
 int push_armor_filter (armor_filter_context_t *afx, iobuf_t iobuf);
 int use_armor_filter( iobuf_t a );
-UnarmorPump unarmor_pump_new (void);
-void        unarmor_pump_release (UnarmorPump x);
-int         unarmor_pump (UnarmorPump x, int c);
 
 /*-- compress.c --*/
 gpg_error_t push_compress_filter (iobuf_t out, compress_filter_context_t *zfx,
index f0132bb..c776a61 100644 (file)
@@ -60,7 +60,7 @@ struct getkey_ctx_s
      search or not.  A search that is exact requires that a key or
      subkey meet all of the specified criteria.  A search that is not
      exact allows selecting a different key or subkey from the
-     keyblock that matched the critera.  Further, an exact search
+     keyblock that matched the criteria.  Further, an exact search
      returns the key or subkey that matched whereas a non-exact search
      typically returns the primary key.  See finish_lookup for
      details.  */
@@ -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)
 {
@@ -677,6 +421,24 @@ pk_from_block (PKT_public_key *pk, kbnode_t keyblock, kbnode_t found_key)
 }
 
 
+/* Specialized version of get_pubkey which retrieves the key based on
+ * information in SIG.  In contrast to get_pubkey PK is required.  */
+gpg_error_t
+get_pubkey_for_sig (ctrl_t ctrl, PKT_public_key *pk, PKT_signature *sig)
+{
+  const byte *fpr;
+  size_t fprlen;
+
+  /* First try the new ISSUER_FPR info.  */
+  fpr = issuer_fpr_raw (sig, &fprlen);
+  if (fpr && !get_pubkey_byfprint (ctrl, pk, NULL, fpr, fprlen))
+    return 0;
+
+  /* Fallback to use the ISSUER_KEYID.  */
+  return get_pubkey (ctrl, pk, sig->keyid);
+}
+
+
 /* Return the public key with the key id KEYID and store it at PK.
  * The resources in *PK should be released using
  * release_public_key_parts().  This function also stores a copy of
@@ -739,8 +501,9 @@ get_pubkey (ctrl_t ctrl, PKT_public_key * pk, u32 * keyid)
   /* Do a lookup.  */
   {
     struct getkey_ctx_s ctx;
-    KBNODE kb = NULL;
-    KBNODE found_key = NULL;
+    kbnode_t kb = NULL;
+    kbnode_t found_key = NULL;
+
     memset (&ctx, 0, sizeof ctx);
     ctx.exact = 1; /* Use the key ID exactly as given.  */
     ctx.not_allocated = 1;
@@ -863,6 +626,28 @@ get_pubkey_fast (PKT_public_key * pk, u32 * keyid)
 }
 
 
+/* Return the entire keyblock used to create SIG.  This is a
+ * specialized version of get_pubkeyblock.
+ *
+ * FIXME: This is a hack because get_pubkey_for_sig was already called
+ * and it could have used a cache to hold the key.  */
+kbnode_t
+get_pubkeyblock_for_sig (ctrl_t ctrl, PKT_signature *sig)
+{
+  const byte *fpr;
+  size_t fprlen;
+  kbnode_t keyblock;
+
+  /* First try the new ISSUER_FPR info.  */
+  fpr = issuer_fpr_raw (sig, &fprlen);
+  if (fpr && !get_pubkey_byfprint (ctrl, NULL, &keyblock, fpr, fprlen))
+    return keyblock;
+
+  /* Fallback to use the ISSUER_KEYID.  */
+  return get_pubkeyblock (ctrl, sig->keyid);
+}
+
+
 /* Return the key block for the key with key id KEYID or NULL, if an
  * error occurs.  Use release_kbnode() to release the key block.
  *
@@ -1224,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);
@@