gpg: Try hard to use MDC also for sign+symenc.
[gnupg.git] / g10 / keyserver.c
index 477ff17..a6257e5 100644 (file)
@@ -41,8 +41,6 @@
 #include "trustdb.h"
 #include "keyserver-internal.h"
 #include "util.h"
-#include "dns-cert.h"
-#include "pka.h"
 #ifdef USE_DNS_SRV
 #include "srv.h"
 #endif
@@ -91,13 +89,14 @@ static struct parse_options keyserver_opts[]=
   {
     /* some of these options are not real - just for the help
        message */
-    {"max-cert-size",0,NULL,NULL},
+    {"max-cert-size",0,NULL,NULL},  /* MUST be the first in this array! */
+    {"http-proxy", KEYSERVER_HTTP_PROXY, NULL, /* MUST be the second!  */
+     N_("override proxy options set for dirmngr")},
+
     {"include-revoked",0,NULL,N_("include revoked keys in search results")},
     {"include-subkeys",0,NULL,N_("include subkeys when searching by key ID")},
-    {"use-temp-files",0,NULL,
-     N_("use temporary files to pass data to keyserver helpers")},
-    {"keep-temp-files",KEYSERVER_KEEP_TEMP_FILES,NULL,
-     N_("do not delete temporary files after using them")},
+    {"timeout", KEYSERVER_TIMEOUT, NULL,
+     N_("override timeout options set for dirmngr")},
     {"refresh-add-fake-v3-keyids",KEYSERVER_ADD_FAKE_V3,NULL,
      NULL},
     {"auto-key-retrieve",KEYSERVER_AUTO_KEY_RETRIEVE,NULL,
@@ -111,7 +110,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 *keyserver,
+                                  struct keyserver_spec *override_keyserver,
                                   unsigned char **r_fpr, size_t *r_fprlen);
 static gpg_error_t keyserver_put (ctrl_t ctrl, strlist_t keyspecs,
                                   struct keyserver_spec *keyserver);
@@ -123,8 +122,9 @@ static gpg_error_t keyserver_put (ctrl_t ctrl, strlist_t keyspecs,
 
 static size_t max_cert_size=DEFAULT_MAX_CERT_SIZE;
 
+
 static void
-warn_kshelper_option(char *option)
+warn_kshelper_option(char *option, int noisy)
 {
   char *p;
 
@@ -138,9 +138,12 @@ warn_kshelper_option(char *option)
   else if (!strcmp (option, "check-cert")
            || !strcmp (option, "broken-http-proxy"))
     log_info ("keyserver option '%s' is obsolete\n", option);
+  else if (noisy || opt.verbose)
+    log_info ("keyserver option '%s' is unknown\n", option);
 }
 
 
+/* Called from main to parse the args for --keyserver-options.  */
 int
 parse_keyserver_options(char *options)
 {
@@ -149,47 +152,24 @@ parse_keyserver_options(char *options)
   char *max_cert=NULL;
 
   keyserver_opts[0].value=&max_cert;
+  keyserver_opts[1].value=&opt.keyserver_options.http_proxy;
 
   while((tok=optsep(&options)))
     {
       if(tok[0]=='\0')
        continue;
 
-      /* For backwards compatibility.  1.2.x used honor-http-proxy and
-        there are a good number of documents published that recommend
-        it. */
-      if(ascii_strcasecmp(tok,"honor-http-proxy")==0)
-       tok="http-proxy";
-      else if(ascii_strcasecmp(tok,"no-honor-http-proxy")==0)
-       tok="no-http-proxy";
-
       /* We accept quite a few possible options here - some options to
         handle specially, the keyserver_options list, and import and
-        export options that pertain to keyserver operations.  Note
-        that you must use strncasecmp here as there might be an
-        =argument attached which will foil the use of strcasecmp. */
-
-#ifdef EXEC_TEMPFILE_ONLY
-      if(ascii_strncasecmp(tok,"use-temp-files",14)==0 ||
-             ascii_strncasecmp(tok,"no-use-temp-files",17)==0)
-       log_info(_("WARNING: keyserver option '%s' is not used"
-                  " on this platform\n"),tok);
-#else
-      if(ascii_strncasecmp(tok,"use-temp-files",14)==0)
-       opt.keyserver_options.options|=KEYSERVER_USE_TEMP_FILES;
-      else if(ascii_strncasecmp(tok,"no-use-temp-files",17)==0)
-       opt.keyserver_options.options&=~KEYSERVER_USE_TEMP_FILES;
-#endif
-      else if(!parse_options(tok,&opt.keyserver_options.options,
-                            keyserver_opts,0)
-        && !parse_import_options(tok,
-                                 &opt.keyserver_options.import_options,0)
-        && !parse_export_options(tok,
-                                 &opt.keyserver_options.export_options,0))
+        export options that pertain to keyserver operations.  */
+
+      if (!parse_options (tok,&opt.keyserver_options.options, keyserver_opts,0)
+          && !parse_import_options(tok,&opt.keyserver_options.import_options,0)
+          && !parse_export_options(tok,&opt.keyserver_options.export_options,0))
        {
          /* All of the standard options have failed, so the option was
             destined for a keyserver plugin as used by GnuPG < 2.1 */
-         warn_kshelper_option (tok);
+         warn_kshelper_option (tok, 1);
        }
     }
 
@@ -204,6 +184,7 @@ parse_keyserver_options(char *options)
   return ret;
 }
 
+
 void
 free_keyserver_spec(struct keyserver_spec *keyserver)
 {
@@ -281,7 +262,7 @@ parse_keyserver_uri (const char *string,int require_scheme)
       options++;
 
       while((tok=optsep(&options)))
-       warn_kshelper_option (tok);
+       warn_kshelper_option (tok, 0);
     }
 
   /* Get the scheme */
@@ -1376,10 +1357,12 @@ keyidlist(strlist_t users,KEYDB_SEARCH_DESC **klist,int *count,int fakev3)
 /* Note this is different than the original HKP refresh.  It allows
    usernames to refresh only part of the keyring. */
 
-int
+gpg_error_t
 keyserver_refresh (ctrl_t ctrl, strlist_t users)
 {
-  int rc,count,numdesc,fakev3=0;
+  gpg_error_t err;
+  int count, numdesc;
+  int fakev3 = 0;
   KEYDB_SEARCH_DESC *desc;
   unsigned int options=opt.keyserver_options.import_options;
 
@@ -1400,9 +1383,9 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
         ascii_strcasecmp(opt.keyserver->scheme,"mailto")==0))
     fakev3=1;
 
-  rc=keyidlist(users,&desc,&numdesc,fakev3);
-  if(rc)
-    return rc;
+  err = keyidlist (users, &desc, &numdesc, fakev3);
+  if (err)
+    return err;
 
   count=numdesc;
   if(count>0)
@@ -1416,14 +1399,17 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
            {
              struct keyserver_spec *keyserver=desc[i].skipfncvalue;
 
+              if (!opt.quiet)
+                log_info (_("refreshing 1 key from %s\n"), keyserver->uri);
+
              /* We use the keyserver structure we parsed out before.
                 Note that a preferred keyserver without a scheme://
                 will be interpreted as hkp:// */
-             rc = keyserver_get (ctrl, &desc[i], 1, keyserver, NULL, NULL);
-             if(rc)
+             err = keyserver_get (ctrl, &desc[i], 1, keyserver, NULL, NULL);
+             if (err)
                log_info(_("WARNING: unable to refresh key %s"
                           " via %s: %s\n"),keystr_from_desc(&desc[i]),
-                        keyserver->uri,gpg_strerror (rc));
+                        keyserver->uri,gpg_strerror (err));
              else
                {
                  /* We got it, so mark it as NONE so we don't try and
@@ -1440,16 +1426,22 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
 
   if(count>0)
     {
-      if(opt.keyserver)
-       {
-         if(count==1)
-           log_info(_("refreshing 1 key from %s\n"),opt.keyserver->uri);
-         else
-           log_info(_("refreshing %d keys from %s\n"),
-                    count,opt.keyserver->uri);
-       }
+      char *tmpuri;
+
+      err = gpg_dirmngr_ks_list (ctrl, &tmpuri);
+      if (!err)
+        {
+          if (!opt.quiet)
+            {
+              if(count==1)
+                log_info(_("refreshing 1 key from %s\n"), tmpuri);
+              else
+                log_info(_("refreshing %d keys from %s\n"), count, tmpuri);
+            }
+          xfree (tmpuri);
 
-      rc=keyserver_get (ctrl, desc, numdesc, NULL, NULL, NULL);
+          err = keyserver_get (ctrl, desc, numdesc, NULL, NULL, NULL);
+        }
     }
 
   xfree(desc);
@@ -1461,7 +1453,7 @@ keyserver_refresh (ctrl_t ctrl, strlist_t users)
   if(!(opt.keyserver_options.import_options&IMPORT_FAST))
     check_or_update_trustdb ();
 
-  return rc;
+  return err;
 }
 
 
@@ -1479,12 +1471,6 @@ keyserver_search (ctrl_t ctrl, strlist_t tokens)
   if (!tokens)
     return 0;  /* Return success if no patterns are given.  */
 
-  if (!opt.keyserver)
-    {
-      log_error (_("no keyserver known (use option --keyserver)\n"));
-      return gpg_error (GPG_ERR_NO_KEYSERVER);
-    }
-
   /* Write global options */
 
   /* for(temp=opt.keyserver_options.other;temp;temp=temp->next) */
@@ -1578,7 +1564,7 @@ static gpg_error_t
 keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
                      int *r_ndesc_used,
                      void *stats_handle,
-                     struct keyserver_spec *keyserver,
+                     struct keyserver_spec *override_keyserver,
                      unsigned char **r_fpr, size_t *r_fprlen)
 
 {
@@ -1694,15 +1680,15 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
           return err;
         }
 
-      if (!quiet && keyserver)
+      if (!quiet && override_keyserver)
         {
-          if (keyserver->host)
+          if (override_keyserver->host)
             log_info (_("requesting key %s from %s server %s\n"),
                       keystr_from_desc (&desc[idx]),
-                      keyserver->scheme, keyserver->host);
+                      override_keyserver->scheme, override_keyserver->host);
           else
             log_info (_("requesting key %s from %s\n"),
-                      keystr_from_desc (&desc[idx]), keyserver->uri);
+                      keystr_from_desc (&desc[idx]), override_keyserver->uri);
         }
     }
 
@@ -1710,7 +1696,8 @@ 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, &datastream, &source);
+  err = gpg_dirmngr_ks_get (ctrl, pattern, override_keyserver,
+                            &datastream, &source);
   for (idx=0; idx < npat; idx++)
     xfree (pattern[idx]);
   xfree (pattern);
@@ -1750,12 +1737,12 @@ keyserver_get_chunk (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
 
 /* Retrieve a key from a keyserver.  The search pattern are in
    (DESC,NDESC).  Allowed search modes are keyid, fingerprint, and
-   exact searches.  KEYSERVER gives an optional override keyserver. If
-   (R_FPR,R_FPRLEN) are not NULL, they may return the fingerprint of a
-   single imported key.  */
+   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.  */
 static gpg_error_t
 keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
-               struct keyserver_spec *keyserver,
+               struct keyserver_spec *override_keyserver,
                unsigned char **r_fpr, size_t *r_fprlen)
 {
   gpg_error_t err;
@@ -1768,7 +1755,7 @@ keyserver_get (ctrl_t ctrl, KEYDB_SEARCH_DESC *desc, int ndesc,
   for (;;)
     {
       err = keyserver_get_chunk (ctrl, desc, ndesc, &ndesc_used, stats_handle,
-                                 keyserver, r_fpr, r_fprlen);
+                                 override_keyserver, r_fpr, r_fprlen);
       if (!err)
         any_good = 1;
       if (err || ndesc_used >= ndesc)
@@ -1894,30 +1881,34 @@ keyserver_fetch (ctrl_t ctrl, strlist_t urilist)
 }
 
 
-/* Import key in a CERT or pointed to by a CERT */
+/* Import key in a CERT or pointed to by a CERT.  In DANE_MODE fetch
+   the certificate using the DANE method.  */
 int
-keyserver_import_cert (ctrl_t ctrl,
-                       const char *name,unsigned char **fpr,size_t *fpr_len)
+keyserver_import_cert (ctrl_t ctrl, const char *name, int dane_mode,
+                       unsigned char **fpr,size_t *fpr_len)
 {
   gpg_error_t err;
-  char *domain,*look,*url;
+  char *look,*url;
   estream_t key;
 
+  look = xstrdup(name);
 
-  look=xstrdup(name);
-
-  domain=strrchr(look,'@');
-  if(domain)
-    *domain='.';
+  if (!dane_mode)
+    {
+      char *domain = strrchr (look,'@');
+      if (domain)
+        *domain='.';
+    }
 
-  err = get_dns_cert (look, DNS_CERTTYPE_ANY, &key, fpr, fpr_len, &url);
+  err = gpg_dirmngr_dns_cert (ctrl, look, dane_mode? NULL : "*",
+                              &key, fpr, fpr_len, &url);
   if (err)
     ;
   else if (key)
     {
       int armor_status=opt.no_armor;
 
-      /* CERTs are always in binary format */
+      /* CERTs and DANE records are always in binary format */
       opt.no_armor=1;
 
       err = import_keys_es_stream (ctrl, key, NULL, fpr, fpr_len,
@@ -1970,37 +1961,35 @@ keyserver_import_cert (ctrl_t ctrl,
 
 /* Import key pointed to by a PKA record. Return the requested
    fingerprint in fpr. */
-int
-keyserver_import_pka (ctrl_t ctrl,
-                      const char *name,unsigned char **fpr,size_t *fpr_len)
+gpg_error_t
+keyserver_import_pka (ctrl_t ctrl, const char *name,
+                      unsigned char **fpr, size_t *fpr_len)
 {
-  char *uri;
-  int rc = GPG_ERR_NO_PUBKEY;
-
-  *fpr = xmalloc (20);
-  *fpr_len = 20;
+  gpg_error_t err;
+  char *url;
 
-  uri = get_pka_info (name, *fpr, 20);
-  if (uri && *uri)
+  err = gpg_dirmngr_get_pka (ctrl, name, fpr, fpr_len, &url);
+  if (url && *url && fpr && fpr_len)
     {
-      /* An URI is available.  Lookup the key. */
+      /* An URL is available.  Lookup the key. */
       struct keyserver_spec *spec;
-      spec = parse_keyserver_uri (uri, 1);
+      spec = parse_keyserver_uri (url, 1);
       if (spec)
        {
-         rc = keyserver_import_fprint (ctrl, *fpr, 20, spec);
+         err = keyserver_import_fprint (ctrl, *fpr, *fpr_len, spec);
          free_keyserver_spec (spec);
        }
-      xfree (uri);
     }
+  xfree (url);
 
-  if (rc)
+  if (err)
     {
       xfree(*fpr);
       *fpr = NULL;
+      *fpr_len = 0;
     }
 
-  return rc;
+  return err;
 }