dirmngr: Add basic libdns support
[gnupg.git] / dirmngr / ks-engine-hkp.c
index e458899..8f53432 100644 (file)
@@ -15,7 +15,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>
@@ -426,11 +426,9 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
       int refidx;
       int is_pool = 0;
       char *cname;
-#ifdef USE_DNS_SRV
       char *srvrecord;
       struct srventry *srvs;
       int srvscount;
-#endif /* USE_DNS_SRV */
 
       reftblsize = 100;
       reftbl = xtrymalloc (reftblsize * sizeof *reftbl);
@@ -447,45 +445,46 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
         }
       hi = hosttable[idx];
 
-#ifdef USE_DNS_SRV
-      /* Check for SRV records.  */
-      srvrecord = xtryasprintf ("_hkp._tcp.%s", name);
-      if (srvrecord == NULL)
+      if (!is_ip_address (name))
         {
-          err = gpg_error_from_syserror ();
-          xfree (reftbl);
-          return err;
-        }
-
-      srvscount = getsrv (srvrecord, &srvs);
-      xfree (srvrecord);
-      if (srvscount < 0)
-        {
-          err = gpg_error_from_syserror ();
-          xfree (reftbl);
-          return err;
-        }
-
-      if (srvscount > 0)
-        {
-          int i;
-          is_pool = srvscount > 1;
+          /* Check for SRV records.  */
+          srvrecord = xtryasprintf ("_hkp._tcp.%s", name);
+          if (srvrecord == NULL)
+            {
+              err = gpg_error_from_syserror ();
+              xfree (reftbl);
+              return err;
+            }
 
-          for (i = 0; i < srvscount; i++)
+          srvscount = getsrv (srvrecord, &srvs);
+          xfree (srvrecord);
+          if (srvscount < 0)
             {
-              err = resolve_dns_name (srvs[i].target, 0,
-                                      AF_UNSPEC, SOCK_STREAM,
-                                      &ai, &cname);
-              if (err)
-                continue;
-              dirmngr_tick (ctrl);
-              add_host (name, is_pool, ai, srvs[i].port,
-                        reftbl, reftblsize, &refidx);
+              err = gpg_error_from_syserror ();
+              xfree (reftbl);
+              return err;
             }
 
-          xfree (srvs);
+          if (srvscount > 0)
+            {
+              int i;
+              is_pool = srvscount > 1;
+
+              for (i = 0; i < srvscount; i++)
+                {
+                  err = resolve_dns_name (srvs[i].target, 0,
+                                          AF_UNSPEC, SOCK_STREAM,
+                                          &ai, &cname);
+                  if (err)
+                    continue;
+                  dirmngr_tick (ctrl);
+                  add_host (name, is_pool, ai, srvs[i].port,
+                            reftbl, reftblsize, &refidx);
+                }
+
+              xfree (srvs);
+            }
         }
-#endif /* USE_DNS_SRV */
 
       /* Find all A records for this entry and put them into the pool
          list - if any.  */
@@ -545,9 +544,9 @@ map_host (ctrl_t ctrl, const char *name, int force_reselect,
   if (hi->pool)
     {
       /* Deal with the pool name before selecting a host. */
-      if (r_poolname && hi->cname)
+      if (r_poolname)
         {
-          *r_poolname = xtrystrdup (hi->cname);
+          *r_poolname = xtrystrdup (hi->cname? hi->cname : hi->name);
           if (!*r_poolname)
             return gpg_error_from_syserror ();
         }
@@ -974,12 +973,13 @@ ks_hkp_housekeeping (time_t curtime)
    R_FP.  HOSTPORTSTR is only used for diagnostics.  If HTTPHOST is
    not NULL it will be used as HTTP "Host" header.  If POST_CB is not
    NULL a post request is used and that callback is called to allow
-   writing the post data.  */
+   writing the post data.  If R_HTTP_STATUS is not NULL, the http
+   status code will be stored there.  */
 static gpg_error_t
 send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
               const char *httphost, unsigned int httpflags,
               gpg_error_t (*post_cb)(void *, http_t), void *post_cb_value,
-              estream_t *r_fp)
+              estream_t *r_fp, unsigned int *r_http_status)
 {
   gpg_error_t err;
   http_session_t session = NULL;
@@ -990,7 +990,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
 
   *r_fp = NULL;
 
-  err = http_session_new (&session, NULL);
+  err = http_session_new (&session, NULL, httphost, HTTP_FLAG_TRUST_DEF);
   if (err)
     goto leave;
   http_session_set_log_cb (session, cert_log_cb);
@@ -1050,6 +1050,9 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
       httpflags |= HTTP_FLAG_FORCE_TLS;
     }
 
+  if (r_http_status)
+    *r_http_status = http_get_status_code (http);
+
   switch (http_get_status_code (http))
     {
     case 200:
@@ -1083,6 +1086,10 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
       }
       goto leave;
 
+    case 501:
+      err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+      goto leave;
+
     default:
       log_error (_("error accessing '%s': http status %u\n"),
                  request, http_get_status_code (http));
@@ -1154,10 +1161,12 @@ handle_send_request_error (gpg_error_t err, const char *request,
 
 \f
 /* Search the keyserver identified by URI for keys matching PATTERN.
-   On success R_FP has an open stream to read the data.  */
+   On success R_FP has an open stream to read the data.  If
+   R_HTTP_STATUS is not NULL, the http status code will be stored
+   there.  */
 gpg_error_t
 ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
-               estream_t *r_fp)
+               estream_t *r_fp, unsigned int *r_http_status)
 {
   gpg_error_t err;
   KEYDB_SEARCH_DESC desc;
@@ -1197,12 +1206,16 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
       pattern = fprbuf;
       break;
     case KEYDB_SEARCH_MODE_FPR16:
-      bin2hex (desc.u.fpr, 16, fprbuf);
+      fprbuf[0] = '0';
+      fprbuf[1] = 'x';
+      bin2hex (desc.u.fpr, 16, fprbuf+2);
       pattern = fprbuf;
       break;
     case KEYDB_SEARCH_MODE_FPR20:
     case KEYDB_SEARCH_MODE_FPR:
-      bin2hex (desc.u.fpr, 20, fprbuf);
+      fprbuf[0] = '0';
+      fprbuf[1] = 'x';
+      bin2hex (desc.u.fpr, 20, fprbuf+2);
       pattern = fprbuf;
       break;
     default:
@@ -1244,7 +1257,7 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
 
   /* Send the request.  */
   err = send_request (ctrl, request, hostport, httphost, httpflags,
-                      NULL, NULL, &fp);
+                      NULL, NULL, &fp, r_http_status);
   if (handle_send_request_error (err, request, &tries))
     {
       reselect = 1;
@@ -1377,7 +1390,7 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
 
   /* Send the request.  */
   err = send_request (ctrl, request, hostport, httphost, httpflags,
-                      NULL, NULL, &fp);
+                      NULL, NULL, &fp, NULL);
   if (handle_send_request_error (err, request, &tries))
     {
       reselect = 1;
@@ -1485,7 +1498,7 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
 
   /* Send the request.  */
   err = send_request (ctrl, request, hostport, httphost, 0,
-                      put_post_cb, &parm, &fp);
+                      put_post_cb, &parm, &fp, NULL);
   if (handle_send_request_error (err, request, &tries))
     {
       reselect = 1;