dirmngr: Put brackets around IP addresses in the hosttable.
[gnupg.git] / dirmngr / ks-action.c
index f376c27..dfeb862 100644 (file)
@@ -1,5 +1,6 @@
 /* ks-action.c - OpenPGP keyserver actions
  * Copyright (C) 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2011, 2014 Werner Koch
  *
  * This file is part of GnuPG.
  *
@@ -49,6 +50,95 @@ copy_stream (estream_t in, estream_t out)
 }
 
 
+/* Called by the engine's help functions to print the actual help.  */
+gpg_error_t
+ks_print_help (ctrl_t ctrl, const char *text)
+{
+  return dirmngr_status_help (ctrl, text);
+}
+
+
+/* Called by the engine's help functions to print the actual help.  */
+gpg_error_t
+ks_printf_help (ctrl_t ctrl, const char *format, ...)
+{
+  va_list arg_ptr;
+  gpg_error_t err;
+  char *buf;
+
+  va_start (arg_ptr, format);
+  buf = es_vasprintf (format, arg_ptr);
+  err = buf? 0 : gpg_error_from_syserror ();
+  va_end (arg_ptr);
+  if (!err)
+    err = dirmngr_status_help (ctrl, buf);
+  es_free (buf);
+  return err;
+}
+
+
+/* Run the help command for the engine responsible for URI.  */
+gpg_error_t
+ks_action_help (ctrl_t ctrl, const char *url)
+{
+  gpg_error_t err;
+  parsed_uri_t parsed_uri;  /* The broken down URI.  */
+
+  if (!url || !*url)
+    {
+      ks_print_help (ctrl, "Known schemata:\n");
+      parsed_uri = NULL;
+    }
+  else
+    {
+      err = http_parse_uri (&parsed_uri, url, 1);
+      if (err)
+        return err;
+    }
+
+  /* Call all engines to give them a chance to print a help sting.  */
+  err = ks_hkp_help (ctrl, parsed_uri);
+  if (!err)
+    err = ks_http_help (ctrl, parsed_uri);
+  if (!err)
+    err = ks_finger_help (ctrl, parsed_uri);
+  if (!err)
+    err = ks_kdns_help (ctrl, parsed_uri);
+
+  if (!parsed_uri)
+    ks_print_help (ctrl,
+                   "(Use an URL for engine specific help.)");
+  else
+    http_release_parsed_uri (parsed_uri);
+  return err;
+}
+
+
+/* Resolve all host names.  This is useful for looking at the status
+   of configured keyservers.  */
+gpg_error_t
+ks_action_resolve (ctrl_t ctrl)
+{
+  gpg_error_t err = 0;
+  int any = 0;
+  uri_item_t uri;
+
+  for (uri = ctrl->keyservers; !err && uri; uri = uri->next)
+    {
+      if (uri->parsed_uri->is_http)
+        {
+          any = 1;
+          err = ks_hkp_resolve (ctrl, uri->parsed_uri);
+          if (err)
+            break;
+        }
+    }
+
+  if (!any)
+    err = gpg_error (GPG_ERR_NO_KEYSERVER);
+  return err;
+}
+
 
 /* Search all configured keyservers for keys matching PATTERNS and
    write the result to the provided output stream.  */
@@ -90,7 +180,7 @@ ks_action_search (ctrl_t ctrl, strlist_t patterns, estream_t outfp)
 }
 
 
-/* Get the requested keys (macthing PATTERNS) using all configured
+/* Get the requested keys (matching PATTERNS) using all configured
    keyservers and write the result to the provided output stream.  */
 gpg_error_t
 ks_action_get (ctrl_t ctrl, strlist_t patterns, estream_t outfp)
@@ -132,7 +222,7 @@ ks_action_get (ctrl_t ctrl, strlist_t patterns, estream_t outfp)
               else
                 {
                   err = copy_stream (infp, outfp);
-                  /* Reading from the keyserver should nver fail, thus
+                  /* Reading from the keyserver should never fail, thus
                      return this error.  */
                   es_fclose (infp);
                   infp = NULL;
@@ -148,3 +238,90 @@ ks_action_get (ctrl_t ctrl, strlist_t patterns, estream_t outfp)
   return err;
 }
 
+
+/* Retrieve keys from URL and write the result to the provided output
+   stream OUTFP.  */
+gpg_error_t
+ks_action_fetch (ctrl_t ctrl, const char *url, estream_t outfp)
+{
+  gpg_error_t err = 0;
+  estream_t infp;
+  parsed_uri_t parsed_uri;  /* The broken down URI.  */
+
+  if (!url)
+    return gpg_error (GPG_ERR_INV_URI);
+
+  err = http_parse_uri (&parsed_uri, url, 1);
+  if (err)
+    return err;
+
+  if (parsed_uri->is_http)
+    {
+      err = ks_http_fetch (ctrl, url, &infp);
+      if (!err)
+        {
+          err = copy_stream (infp, outfp);
+          es_fclose (infp);
+        }
+    }
+  else if (!parsed_uri->opaque)
+    {
+      err = gpg_error (GPG_ERR_INV_URI);
+    }
+  else if (!strcmp (parsed_uri->scheme, "finger"))
+    {
+      err = ks_finger_fetch (ctrl, parsed_uri, &infp);
+      if (!err)
+        {
+          err = copy_stream (infp, outfp);
+          es_fclose (infp);
+        }
+    }
+  else if (!strcmp (parsed_uri->scheme, "kdns"))
+    {
+      err = ks_kdns_fetch (ctrl, parsed_uri, &infp);
+      if (!err)
+        {
+          err = copy_stream (infp, outfp);
+          es_fclose (infp);
+        }
+    }
+  else
+    err = gpg_error (GPG_ERR_INV_URI);
+
+  http_release_parsed_uri (parsed_uri);
+  return err;
+}
+
+
+
+/* Send an OpenPGP key to all keyservers.  The key in {DATA,DATALEN}
+   is expected in OpenPGP binary transport format.  */
+gpg_error_t
+ks_action_put (ctrl_t ctrl, const void *data, size_t datalen)
+{
+  gpg_error_t err = 0;
+  gpg_error_t first_err = 0;
+  int any = 0;
+  uri_item_t uri;
+
+  for (uri = ctrl->keyservers; !err && uri; uri = uri->next)
+    {
+      if (uri->parsed_uri->is_http)
+        {
+          any = 1;
+          err = ks_hkp_put (ctrl, uri->parsed_uri, data, datalen);
+          if (err)
+            {
+              first_err = err;
+              err = 0;
+            }
+        }
+    }
+
+  if (!any)
+    err = gpg_error (GPG_ERR_NO_KEYSERVER);
+  else if (!err && first_err)
+    err = first_err; /* fixme: Do we really want to do that?  */
+  return err;
+}