doc: Typo fix in a comment.
[gnupg.git] / g10 / keyserver.c
index 4239469..a8c222d 100644 (file)
@@ -16,7 +16,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
 #include <errno.h>
 
 #include "gpg.h"
-#include "iobuf.h"
+#include "../common/iobuf.h"
 #include "filter.h"
 #include "keydb.h"
-#include "status.h"
+#include "../common/status.h"
 #include "exec.h"
 #include "main.h"
-#include "i18n.h"
-#include "ttyio.h"
+#include "../common/i18n.h"
+#include "../common/ttyio.h"
 #include "options.h"
 #include "packet.h"
 #include "trustdb.h"
 #include "keyserver-internal.h"
-#include "util.h"
-#include "membuf.h"
-#include "mbox-util.h"
+#include "../common/util.h"
+#include "../common/membuf.h"
+#include "../common/mbox-util.h"
 #include "call-dirmngr.h"
 
 #ifdef HAVE_W32_SYSTEM
@@ -108,6 +108,7 @@ static struct parse_options keyserver_opts[]=
 static gpg_error_t keyserver_get (ctrl_t ctrl,
                                   KEYDB_SEARCH_DESC *desc, int ndesc,
                                   struct keyserver_spec *override_keyserver,
+                                  int quick,
                                   unsigned char **r_fpr, size_t *r_fprlen);
 static gpg_error_t keyserver_put (ctrl_t ctrl, strlist_t keyspecs);
 
@@ -467,7 +468,7 @@ parse_preferred_keyserver(PKT_signature *sig)
 }
 
 static void
-print_keyrec(int number,struct keyrec *keyrec)
+print_keyrec (ctrl_t ctrl, int number,struct keyrec *keyrec)
 {
   int i;
 
@@ -521,7 +522,7 @@ print_keyrec(int number,struct keyrec *keyrec)
     case KEYDB_SEARCH_MODE_FPR20:
       {
        u32 kid[2];
-       keyid_from_fingerprint(keyrec->desc.u.fpr,20,kid);
+       keyid_from_fingerprint (ctrl, keyrec->desc.u.fpr,20,kid);
        es_printf("key %s",keystr(kid));
       }
       break;
@@ -793,7 +794,7 @@ show_prompt (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int numdesc,
           }
         for (idx = 0; idx < numidx; idx++)
           selarray[idx] = desc[numarray[idx]-1];
-        err = keyserver_get (ctrl, selarray, numidx, NULL, NULL, NULL);
+        err = keyserver_get (ctrl, selarray, numidx, NULL, 0, NULL, NULL);
         xfree (selarray);
       }
     }
@@ -959,7 +960,7 @@ search_line_handler (void *opaque, int special, char *line)
               parm->numlines = 0;
             }
 
-          print_keyrec (parm->nkeys+1, keyrec);
+          print_keyrec (parm->ctrl, parm->nkeys+1, keyrec);
         }
 
       parm->numlines += keyrec->lines;
@@ -1125,7 +1126,7 @@ keyserver_import (ctrl_t ctrl, strlist_t users)
     }
 
   if(count>0)
-    rc=keyserver_get (ctrl, desc, count, NULL, NULL, NULL);
+    rc = keyserver_get (ctrl, desc, count, NULL, 0, NULL, NULL);
 
   xfree(desc);
 
@@ -1154,13 +1155,13 @@ keyserver_import_name (ctrl_t ctrl, const char *name,
   desc.mode = KEYDB_SEARCH_MODE_EXACT;
   desc.u.name = name;
 
-  return keyserver_get (ctrl, &desc, 1, keyserver, fpr, fprlen);
+  return keyserver_get (ctrl, &desc, 1, keyserver, 0, fpr, fprlen);
 }
 
 
 int
 keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
-                        struct keyserver_spec *keyserver)
+                        struct keyserver_spec *keyserver, int quick)
 {
   KEYDB_SEARCH_DESC desc;
 
@@ -1177,12 +1178,12 @@ keyserver_import_fprint (ctrl_t ctrl, const byte *fprint,size_t fprint_len,
 
   /* TODO: Warn here if the fingerprint we got doesn't match the one
      we asked for? */
-  return keyserver_get (ctrl, &desc, 1, keyserver, NULL, NULL);
+  return keyserver_get (ctrl, &desc, 1, keyserver, quick, NULL, NULL);
 }
 
 int
 keyserver_import_keyid (ctrl_t ctrl,
-                        u32 *keyid,struct keyserver_spec *keyserver)
+                        u32 *keyid,struct keyserver_spec *keyserver, int quick)
 {
   KEYDB_SEARCH_DESC desc;
 
@@ -1192,12 +1193,14 @@ keyserver_import_keyid (ctrl_t ctrl,
   desc.u.kid[0]=keyid[0];
   desc.u.kid[1]=keyid[1];
 
-  return keyserver_get (ctrl, &desc,1, keyserver, NULL, NULL);
+  return keyserver_get (ctrl, &desc, 1, keyserver, quick, NULL, NULL);
 }
 
+
 /* code mostly stolen from do_export_stream */
 static int
-keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
+keyidlist (ctrl_t ctrl, strlist_t users, KEYDB_SEARCH_DESC **klist,
+           int *count, int fakev3)
 {
   int rc = 0;
   int num = 100;
@@ -1317,12 +1320,12 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
              PKT_user_id *uid=NULL;
              PKT_signature *sig=NULL;
 
-             merge_keys_and_selfsig(keyblock);
+             merge_keys_and_selfsig (ctrl, keyblock);
 
              for(node=node->next;node;node=node->next)
                {
                  if(node->pkt->pkttype==PKT_USER_ID
-                    && node->pkt->pkt.user_id->is_primary)
+                    && node->pkt->pkt.user_id->flags.primary)
                    uid=node->pkt->pkt.user_id;
                  else if(node->pkt->pkttype==PKT_SIGNATURE
                          && node->pkt->pkt.signature->
@@ -1400,7 +1403,7 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
         ascii_strcasecmp(opt.keyserver->scheme,"mailto")==0))
     fakev3=1;
 
-  err = keyidlist (users, &desc, &numdesc, fakev3);
+  err = keyidlist (ctrl, users, &desc, &numdesc, fakev3);
   if (err)
     return err;
 
@@ -1422,7 +1425,7 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
              /* We use the keyserver structure we parsed out before.
                 Note that a preferred keyserver without a scheme://
                 will be interpreted as hkp:// */
-             err = keyserver_get (ctrl, &desc[i], 1, keyserver, NULL, NULL);
+             err = keyserver_get (ctrl, &desc[i], 1, keyserver, 0, NULL, NULL);
              if (err)
                log_info(_("WARNING: unable to refresh key %s"
                           " via %s: %s\n"),keystr_from_desc(&desc[i]),
@@ -1456,7 +1459,7 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
             }
           xfree (tmpuri);
 
-          err = keyserver_get (ctrl, desc, numdesc, NULL, NULL, NULL);
+          err = keyserver_get (ctrl, desc, numdesc, NULL, 0, NULL, NULL);
         }
     }
 
@@ -1581,16 +1584,18 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
                      int *r_ndesc_used,
                      import_stats_t stats_handle,
                      struct keyserver_spec *override_keyserver,
+                     int quick,
                      unsigned char **r_fpr, size_t *r_fprlen)
 
 {
   gpg_error_t err = 0;
   char **pattern;
-  int idx, npat;
+  int idx, npat, npat_fpr;
   estream_t datastream;
   char *source = NULL;
   size_t linelen;  /* Estimated linelen for KS_GET.  */
   size_t n;
+  int only_fprs;
 
 #define MAX_KS_GET_LINELEN 950  /* Somewhat lower than the real limit.  */
 
@@ -1604,12 +1609,12 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
 
   /* Note that we break the loop as soon as our estimation of the to
      be used line length reaches the limit.  But we do this only if we
-     have processed at leas one search requests so that an overlong
+     have processed at least one search requests so that an overlong
      single request will be rejected only later by gpg_dirmngr_ks_get
      but we are sure that R_NDESC_USED has been updated.  This avoids
      a possible indefinite loop.  */
-  linelen = 9; /* "KS_GET --" */
-  for (npat=idx=0; idx < ndesc; idx++)
+  linelen = 17; /* "KS_GET --quick --" */
+  for (npat=npat_fpr=0, idx=0; idx < ndesc; idx++)
     {
       int quiet = 0;
 
@@ -1631,6 +1636,8 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
                        desc[idx].mode == KEYDB_SEARCH_MODE_FPR20? 20 : 16,
                        pattern[npat]+2);
               npat++;
+              if (desc[idx].mode == KEYDB_SEARCH_MODE_FPR20)
+                npat_fpr++;
             }
         }
       else if(desc[idx].mode == KEYDB_SEARCH_MODE_LONG_KID)
@@ -1712,7 +1719,9 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
      this is different from NPAT.  */
   *r_ndesc_used = idx;
 
-  err = gpg_dirmngr_ks_get (ctrl, pattern, override_keyserver,
+  only_fprs = (npat && npat == npat_fpr);
+
+  err = gpg_dirmngr_ks_get (ctrl, pattern, override_keyserver, quick,
                             &datastream, &source);
   for (idx=0; idx < npat; idx++)
     xfree (pattern[idx]);
@@ -1742,7 +1751,9 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
                              r_fpr, r_fprlen,
                              (opt.keyserver_options.import_options
                               | IMPORT_NO_SECKEY),
-                             keyserver_retrieval_screener, &screenerarg);
+                             keyserver_retrieval_screener, &screenerarg,
+                             only_fprs? KEYORG_KS : 0,
+                             source);
     }
   es_fclose (datastream);
   xfree (source);
@@ -1755,10 +1766,11 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
    (DESC,NDESC).  Allowed search modes are keyid, fingerprint, and
    exact searches.  OVERRIDE_KEYSERVER gives an optional override
    keyserver. If (R_FPR,R_FPRLEN) are not NULL, they may return the
-   fingerprint of a single imported key.  */
+   fingerprint of a single imported key.  If QUICK is set, dirmngr is
+   advised to use a shorter timeout. */
 static gpg_error_t
 keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
-               struct keyserver_spec *override_keyserver,
+               struct keyserver_spec *override_keyserver, int quick,
                unsigned char **r_fpr, size_t *r_fprlen)
 {
   gpg_error_t err;
@@ -1771,7 +1783,7 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
   for (;;)
     {
       err = keyserver_get_chunk (ctrl, desc, ndesc, &ndesc_used, stats_handle,
-                                 override_keyserver, r_fpr, r_fprlen);
+                                 override_keyserver, quick, r_fpr, r_fprlen);
       if (!err)
         any_good = 1;
       if (err || ndesc_used >= ndesc)
@@ -1847,7 +1859,7 @@ keyserver_put (ctrl_t ctrl, strlist_t keyspecs)
    that the fetch operation ignores the configured keyservers and
    instead directly retrieves the keys.  */
 int
-keyserver_fetch (ctrl_t ctrl, strlist_t urilist)
+keyserver_fetch (ctrl_t ctrl, strlist_t urilist, int origin)
 {
   gpg_error_t err;
   strlist_t sl;
@@ -1872,7 +1884,7 @@ keyserver_fetch (ctrl_t ctrl, strlist_t urilist)
           stats_handle = import_new_stats_handle();
           import_keys_es_stream (ctrl, datastream, stats_handle, NULL, NULL,
                                  opt.keyserver_options.import_options,
-                                 NULL, NULL);
+                                 NULL, NULL, origin, sl->d);
 
           import_print_stats (stats_handle);
           import_release_stats_handle (stats_handle);
@@ -1920,14 +1932,36 @@ keyserver_import_cert (ctrl_t ctrl, const char *name, int dane_mode,
   else if (key)
     {
       int armor_status=opt.no_armor;
+      import_filter_t save_filt;
 
       /* CERTs and DANE records are always in binary format */
       opt.no_armor=1;
-
-      err = import_keys_es_stream (ctrl, key, NULL, fpr, fpr_len,
-                                   (opt.keyserver_options.import_options
-                                    | IMPORT_NO_SECKEY),
-                                   NULL, NULL);
+      if (dane_mode)
+        {
+          save_filt = save_and_clear_import_filter ();
+          if (!save_filt)
+            err = gpg_error_from_syserror ();
+          else
+            {
+              char *filtstr = es_bsprintf ("keep-uid=mbox = %s", look);
+              err = filtstr? 0 : gpg_error_from_syserror ();
+              if (!err)
+                err = parse_and_set_import_filter (filtstr);
+              xfree (filtstr);
+              if (!err)
+                err = import_keys_es_stream (ctrl, key, NULL, fpr, fpr_len,
+                                             IMPORT_NO_SECKEY,
+                                             NULL, NULL, KEYORG_DANE, NULL);
+              restore_import_filter (save_filt);
+            }
+        }
+      else
+        {
+          err = import_keys_es_stream (ctrl, key, NULL, fpr, fpr_len,
+                                       (opt.keyserver_options.import_options
+                                        | IMPORT_NO_SECKEY),
+                                       NULL, NULL, 0, NULL);
+        }
 
       opt.no_armor=armor_status;
 
@@ -1946,7 +1980,7 @@ keyserver_import_cert (ctrl_t ctrl, const char *name, int dane_mode,
          spec = parse_keyserver_uri (url, 1);
          if(spec)
            {
-             err = keyserver_import_fprint (ctrl, *fpr,*fpr_len,spec);
+             err = keyserver_import_fprint (ctrl, *fpr, *fpr_len, spec, 0);
              free_keyserver_spec(spec);
            }
        }
@@ -1955,7 +1989,8 @@ keyserver_import_cert (ctrl_t ctrl, const char *name, int dane_mode,
          /* If only a fingerprint is provided, try and fetch it from
             the configured keyserver. */
 
-         err = keyserver_import_fprint (ctrl, *fpr,*fpr_len,opt.keyserver);
+         err = keyserver_import_fprint (ctrl,
+                                         *fpr, *fpr_len, opt.keyserver, 0);
        }
       else
        log_info(_("no keyserver known\n"));
@@ -1989,7 +2024,7 @@ keyserver_import_pka (ctrl_t ctrl, const char *name,
       spec = parse_keyserver_uri (url, 1);
       if (spec)
        {
-         err = keyserver_import_fprint (ctrl, *fpr, *fpr_len, spec);
+         err = keyserver_import_fprint (ctrl, *fpr, *fpr_len, spec, 0);
          free_keyserver_spec (spec);
        }
     }
@@ -2008,12 +2043,13 @@ keyserver_import_pka (ctrl_t ctrl, const char *name,
 
 /* Import a key using the Web Key Directory protocol.  */
 gpg_error_t
-keyserver_import_wkd (ctrl_t ctrl, const char *name,
+keyserver_import_wkd (ctrl_t ctrl, const char *name, int quick,
                       unsigned char **fpr, size_t *fpr_len)
 {
   gpg_error_t err;
   char *mbox;
   estream_t key;
+  char *url = NULL;
 
   /* We want to work on the mbox.  That is what dirmngr will do anyway
    * and we need the mbox for the import filter anyway.  */
@@ -2026,7 +2062,7 @@ keyserver_import_wkd (ctrl_t ctrl, const char *name,
       return err;
     }
 
-  err = gpg_dirmngr_wkd_get (ctrl, mbox, &key);
+  err = gpg_dirmngr_wkd_get (ctrl, mbox, quick, &key, &url);
   if (err)
     ;
   else if (key)
@@ -2049,7 +2085,7 @@ keyserver_import_wkd (ctrl_t ctrl, const char *name,
           if (!err)
             err = import_keys_es_stream (ctrl, key, NULL, fpr, fpr_len,
                                          IMPORT_NO_SECKEY,
-                                         NULL, NULL);
+                                         NULL, NULL, KEYORG_WKD, url);
 
         }
 
@@ -2060,6 +2096,7 @@ keyserver_import_wkd (ctrl_t ctrl, const char *name,
       key = NULL;
     }
 
+  xfree (url);
   xfree (mbox);
   return err;
 }
@@ -2080,11 +2117,9 @@ keyserver_import_ldap (ctrl_t ctrl,
   struct keyserver_spec *keyserver;
   strlist_t list=NULL;
   int rc,hostlen=1;
-#ifdef USE_DNS_SRV
   struct srventry *srvlist=NULL;
   int srvcount,i;
   char srvname[MAXDNAME];
-#endif
 
   /* Parse out the domain */
   domain=strrchr(name,'@');
@@ -2098,7 +2133,6 @@ keyserver_import_ldap (ctrl_t ctrl,
   keyserver->host=xmalloc(1);
   keyserver->host[0]='\0';
 
-#ifdef USE_DNS_SRV
   snprintf(srvname,MAXDNAME,"_pgpkey-ldap._tcp.%s",domain);
 
   FIXME("network related - move to dirmngr or drop the code");
@@ -2126,7 +2160,6 @@ keyserver_import_ldap (ctrl_t ctrl,
     }
 
   free(srvlist);
-#endif
 
   /* If all else fails, do the PGP Universal trick of
      ldap://keys.(domain) */