Imported Upstream version 2.1.13
[platform/upstream/gpg2.git] / dirmngr / server.c
index 0794509..6eb6f1b 100644 (file)
@@ -1,7 +1,7 @@
 /* server.c - LDAP and Keyserver access server
  * Copyright (C) 2002 Klarälvdalens Datakonsult AB
  * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2011, 2015 g10 Code GmbH
- * Copyright (C) 2014 Werner Koch
+ * Copyright (C) 2014, 2015, 2016 Werner Koch
  *
  * This file is part of GnuPG.
  *
@@ -53,6 +53,7 @@
 #include "dns-stuff.h"
 #include "mbox-util.h"
 #include "zb32.h"
+#include "server-help.h"
 
 /* To avoid DoS attacks we limit the size of a certificate to
    something reasonable.  The DoS was actually only an issue back when
@@ -273,78 +274,6 @@ strcpy_escaped_plus (char *d, const unsigned char *s)
 }
 
 
-/* Check whether the option NAME appears in LINE */
-static int
-has_option (const char *line, const char *name)
-{
-  const char *s;
-  int n = strlen (name);
-
-  s = strstr (line, name);
-  return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
-}
-
-/* Same as has_option but only considers options at the begin of the
-   line.  This is useful for commands which allow arbitrary strings on
-   the line.  */
-static int
-has_leading_option (const char *line, const char *name)
-{
-  const char *s;
-  int n;
-
-  if (name[0] != '-' || name[1] != '-' || !name[2] || spacep (name+2))
-    return 0;
-  n = strlen (name);
-  while ( *line == '-' && line[1] == '-' )
-    {
-      s = line;
-      while (*line && !spacep (line))
-        line++;
-      if (n == (line - s) && !strncmp (s, name, n))
-        return 1;
-      while (spacep (line))
-        line++;
-    }
-  return 0;
-}
-
-
-/* Same as has_option but does only test for the name of the option
-   and ignores an argument, i.e. with NAME being "--hash" it would
-   return a pointer for "--hash" as well as for "--hash=foo".  If
-   thhere is no such option NULL is returned.  The pointer returned
-   points right behind the option name, this may be an equal sign, Nul
-   or a space.  */
-/* static const char * */
-/* has_option_name (const char *line, const char *name) */
-/* { */
-/*   const char *s; */
-/*   int n = strlen (name); */
-
-/*   s = strstr (line, name); */
-/*   return (s && (s == line || spacep (s-1)) */
-/*           && (!s[n] || spacep (s+n) || s[n] == '=')) ? (s+n) : NULL; */
-/* } */
-
-
-/* Skip over options.  It is assumed that leading spaces have been
-   removed (this is the case for lines passed to a handler from
-   assuan).  Blanks after the options are also removed. */
-static char *
-skip_options (char *line)
-{
-  while ( *line == '-' && line[1] == '-' )
-    {
-      while (*line && !spacep (line))
-        line++;
-      while (spacep (line))
-        line++;
-    }
-  return line;
-}
-
-
 /* This fucntion returns true if a Tor server is running.  The sattus
    is cached for the current conenction.  */
 static int
@@ -692,7 +621,7 @@ static const char hlp_dns_cert[] =
   "  *     Return the first record of any supported subtype\n"
   "  PGP   Return the first record of subtype PGP (3)\n"
   "  IPGP  Return the first record of subtype IPGP (6)\n"
-  "If the content of a certifciate is available (PGP) it is returned\n"
+  "If the content of a certificate is available (PGP) it is returned\n"
   "by data lines.  Fingerprints and URLs are returned via status lines.\n"
   "In --pka mode the fingerprint and if available an URL is returned.\n"
   "In --dane mode the key is returned from RR type 61";
@@ -869,6 +798,73 @@ cmd_dns_cert (assuan_context_t ctx, char *line)
 
 
 \f
+static const char hlp_wkd_get[] =
+  "WKD_GET <user_id>\n"
+  "\n"
+  "Return the key for <user_id> from a Web Key Directory.\n";
+static gpg_error_t
+cmd_wkd_get (assuan_context_t ctx, char *line)
+{
+  ctrl_t ctrl = assuan_get_pointer (ctx);
+  gpg_error_t err = 0;
+  char *mbox = NULL;
+  char *domain;     /* Points to mbox.  */
+  char sha1buf[20];
+  char *uri = NULL;
+  char *encodedhash = NULL;
+
+  line = skip_options (line);
+
+  mbox = mailbox_from_userid (line);
+  if (!mbox || !(domain = strchr (mbox, '@')))
+    {
+      err = set_error (GPG_ERR_INV_USER_ID, "no mailbox in user id");
+      goto leave;
+    }
+  *domain++ = 0;
+
+  gcry_md_hash_buffer (GCRY_MD_SHA1, sha1buf, mbox, strlen (mbox));
+  encodedhash = zb32_encode (sha1buf, 8*20);
+  if (!encodedhash)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+
+  uri = strconcat ("https://",
+                   domain,
+                   "/.well-known/openpgpkey/hu/",
+                   encodedhash,
+                   NULL);
+  if (!uri)
+    {
+      err = gpg_error_from_syserror ();
+      goto leave;
+    }
+
+  /* Setup an output stream and perform the get.  */
+  {
+    estream_t outfp;
+
+    outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
+    if (!outfp)
+      err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
+    else
+      {
+        err = ks_action_fetch (ctrl, uri, outfp);
+        es_fclose (outfp);
+      }
+  }
+
+ leave:
+  xfree (uri);
+  xfree (encodedhash);
+  xfree (mbox);
+  return leave_cmd (ctx, err);
+}
+
+
+\f
 static const char hlp_ldapserver[] =
   "LDAPSERVER <data>\n"
   "\n"
@@ -1147,7 +1143,7 @@ static const char hlp_checkocsp[] =
   "Processing then takes place without further interaction; in\n"
   "particular dirmngr tries to locate other required certificates by\n"
   "its own mechanism which includes a local certificate store as well\n"
-  "as a list of trusted root certifciates.\n"
+  "as a list of trusted root certificates.\n"
   "\n"
   "If the option --force-default-responder is given, only the default\n"
   "OCSP responder will be used and any other methods of obtaining an\n"
@@ -2089,7 +2085,7 @@ cmd_ks_fetch (assuan_context_t ctx, char *line)
   /* No options for now.  */
   line = skip_options (line);
 
-  err = ensure_keyserver (ctrl);
+  err = ensure_keyserver (ctrl);  /* FIXME: Why do we needs this here?  */
   if (err)
     goto leave;
 
@@ -2332,6 +2328,7 @@ register_commands (assuan_context_t ctx)
     const char * const help;
   } table[] = {
     { "DNS_CERT",   cmd_dns_cert,   hlp_dns_cert },
+    { "WKD_GET",    cmd_wkd_get,    hlp_wkd_get },
     { "LDAPSERVER", cmd_ldapserver, hlp_ldapserver },
     { "ISVALID",    cmd_isvalid,    hlp_isvalid },
     { "CHECKCRL",   cmd_checkcrl,   hlp_checkcrl },
@@ -2443,22 +2440,13 @@ start_command_handler (assuan_fd_t fd)
 
   if (!hello_line)
     {
-      size_t n;
-      const char *cfgname;
-
-      cfgname = opt.config_filename? opt.config_filename : "[none]";
-
-      n = (30 + strlen (opt.homedir) + strlen (cfgname)
-           + strlen (hello) + 1);
-      hello_line = xmalloc (n+1);
-      snprintf (hello_line, n,
-                "Home: %s\n"
-                "Config: %s\n"
-                "%s",
-                opt.homedir,
-                cfgname,
-                hello);
-      hello_line[n] = 0;
+      hello_line = xtryasprintf
+        ("Home: %s\n"
+         "Config: %s\n"
+         "%s",
+         gnupg_homedir (),
+         opt.config_filename? opt.config_filename : "[none]",
+         hello);
     }
 
   ctrl->server_local->assuan_ctx = ctx;