LCOV - code coverage report
Current view: top level - dirmngr - server.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 1057 0.0 %
Date: 2016-09-12 12:29:17 Functions: 0 49 0.0 %

          Line data    Source code
       1             : /* server.c - LDAP and Keyserver access server
       2             :  * Copyright (C) 2002 Klarälvdalens Datakonsult AB
       3             :  * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2011, 2015 g10 Code GmbH
       4             :  * Copyright (C) 2014, 2015, 2016 Werner Koch
       5             :  *
       6             :  * This file is part of GnuPG.
       7             :  *
       8             :  * GnuPG is free software; you can redistribute it and/or modify
       9             :  * it under the terms of the GNU General Public License as published by
      10             :  * the Free Software Foundation; either version 3 of the License, or
      11             :  * (at your option) any later version.
      12             :  *
      13             :  * GnuPG is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  * GNU General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU General Public License
      19             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include <config.h>
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <stddef.h>
      26             : #include <string.h>
      27             : #include <assert.h>
      28             : #include <sys/types.h>
      29             : #include <sys/stat.h>
      30             : #include <unistd.h>
      31             : #include <errno.h>
      32             : 
      33             : #include "dirmngr.h"
      34             : #include <assuan.h>
      35             : 
      36             : #include "crlcache.h"
      37             : #include "crlfetch.h"
      38             : #if USE_LDAP
      39             : # include "ldapserver.h"
      40             : #endif
      41             : #include "ocsp.h"
      42             : #include "certcache.h"
      43             : #include "validate.h"
      44             : #include "misc.h"
      45             : #if USE_LDAP
      46             : # include "ldap-wrapper.h"
      47             : #endif
      48             : #include "ks-action.h"
      49             : #include "ks-engine.h"  /* (ks_hkp_print_hosttable) */
      50             : #if USE_LDAP
      51             : # include "ldap-parse-uri.h"
      52             : #endif
      53             : #include "dns-stuff.h"
      54             : #include "mbox-util.h"
      55             : #include "zb32.h"
      56             : #include "server-help.h"
      57             : 
      58             : /* To avoid DoS attacks we limit the size of a certificate to
      59             :    something reasonable.  The DoS was actually only an issue back when
      60             :    Dirmngr was a system service and not a user service. */
      61             : #define MAX_CERT_LENGTH (16*1024)
      62             : 
      63             : /* The same goes for OpenPGP keyblocks, but here we need to allow for
      64             :    much longer blocks; a 200k keyblock is not too unusual for keys
      65             :    with a lot of signatures (e.g. 0x5b0358a2).  9C31503C6D866396 even
      66             :    has 770 KiB as of 2015-08-23.  To avoid adding a runtime option we
      67             :    now use 20MiB which should really be enough.  Well, a key with
      68             :    several pictures could be larger (the parser as a 18MiB limit for
      69             :    attribute packets) but it won't be nice to the keyservers to send
      70             :    them such large blobs.  */
      71             : #define MAX_KEYBLOCK_LENGTH (20*1024*1024)
      72             : 
      73             : 
      74             : #define PARM_ERROR(t) assuan_set_error (ctx, \
      75             :                                         gpg_error (GPG_ERR_ASS_PARAMETER), (t))
      76             : #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
      77             : 
      78             : 
      79             : 
      80             : /* Control structure per connection. */
      81             : struct server_local_s
      82             : {
      83             :   /* Data used to associate an Assuan context with local server data */
      84             :   assuan_context_t assuan_ctx;
      85             : 
      86             :   /* Per-session LDAP servers.  */
      87             :   ldap_server_t ldapservers;
      88             : 
      89             :   /* Per-session list of keyservers.  */
      90             :   uri_item_t keyservers;
      91             : 
      92             :   /* If this flag is set to true this dirmngr process will be
      93             :      terminated after the end of this session.  */
      94             :   int stopme;
      95             : 
      96             :   /* State variable private to is_tor_running.  */
      97             :   int tor_state;
      98             : 
      99             :   /* If the first both flags are set the assuan logging of data lines
     100             :    * is suppressed.  The count variable is used to show the number of
     101             :    * non-logged bytes.  */
     102             :   size_t inhibit_data_logging_count;
     103             :   unsigned int inhibit_data_logging : 1;
     104             :   unsigned int inhibit_data_logging_now : 1;
     105             : };
     106             : 
     107             : 
     108             : /* Cookie definition for assuan data line output.  */
     109             : static gpgrt_ssize_t data_line_cookie_write (void *cookie,
     110             :                                              const void *buffer, size_t size);
     111             : static int data_line_cookie_close (void *cookie);
     112             : static es_cookie_io_functions_t data_line_cookie_functions =
     113             :   {
     114             :     NULL,
     115             :     data_line_cookie_write,
     116             :     NULL,
     117             :     data_line_cookie_close
     118             :   };
     119             : 
     120             : 
     121             : 
     122             : 
     123             : 
     124             : /* Accessor for the local ldapservers variable. */
     125             : ldap_server_t
     126           0 : get_ldapservers_from_ctrl (ctrl_t ctrl)
     127             : {
     128           0 :   if (ctrl && ctrl->server_local)
     129           0 :     return ctrl->server_local->ldapservers;
     130             :   else
     131           0 :     return NULL;
     132             : }
     133             : 
     134             : /* Release an uri_item_t list.  */
     135             : static void
     136           0 : release_uri_item_list (uri_item_t list)
     137             : {
     138           0 :   while (list)
     139             :     {
     140           0 :       uri_item_t tmp = list->next;
     141           0 :       http_release_parsed_uri (list->parsed_uri);
     142           0 :       xfree (list);
     143           0 :       list = tmp;
     144             :     }
     145           0 : }
     146             : 
     147             : /* Release all configured keyserver info from CTRL.  */
     148             : void
     149           0 : release_ctrl_keyservers (ctrl_t ctrl)
     150             : {
     151           0 :   if (! ctrl->server_local)
     152           0 :     return;
     153             : 
     154           0 :   release_uri_item_list (ctrl->server_local->keyservers);
     155           0 :   ctrl->server_local->keyservers = NULL;
     156             : }
     157             : 
     158             : 
     159             : 
     160             : /* Helper to print a message while leaving a command.  */
     161             : static gpg_error_t
     162           0 : leave_cmd (assuan_context_t ctx, gpg_error_t err)
     163             : {
     164           0 :   if (err)
     165             :     {
     166           0 :       const char *name = assuan_get_command_name (ctx);
     167           0 :       if (!name)
     168           0 :         name = "?";
     169           0 :       if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
     170           0 :         log_error ("command '%s' failed: %s\n", name,
     171             :                    gpg_strerror (err));
     172             :       else
     173           0 :         log_error ("command '%s' failed: %s <%s>\n", name,
     174             :                    gpg_strerror (err), gpg_strsource (err));
     175             :     }
     176           0 :   return err;
     177             : }
     178             : 
     179             : 
     180             : /* This is a wrapper around assuan_send_data which makes debugging the
     181             :    output in verbose mode easier.  */
     182             : static gpg_error_t
     183           0 : data_line_write (assuan_context_t ctx, const void *buffer_arg, size_t size)
     184             : {
     185           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
     186           0 :   const char *buffer = buffer_arg;
     187             :   gpg_error_t err;
     188             : 
     189             :   /* If we do not want logging, enable it it here.  */
     190           0 :   if (ctrl && ctrl->server_local && ctrl->server_local->inhibit_data_logging)
     191           0 :     ctrl->server_local->inhibit_data_logging_now = 1;
     192             : 
     193           0 :   if (opt.verbose && buffer && size)
     194           0 :     {
     195             :       /* Ease reading of output by sending a physical line at each LF.  */
     196             :       const char *p;
     197             :       size_t n, nbytes;
     198             : 
     199           0 :       nbytes = size;
     200             :       do
     201             :         {
     202           0 :           p = memchr (buffer, '\n', nbytes);
     203           0 :           n = p ? (p - buffer) + 1 : nbytes;
     204           0 :           err = assuan_send_data (ctx, buffer, n);
     205           0 :           if (err)
     206             :             {
     207           0 :               gpg_err_set_errno (EIO);
     208           0 :               goto leave;
     209             :             }
     210           0 :           buffer += n;
     211           0 :           nbytes -= n;
     212           0 :           if (nbytes && (err=assuan_send_data (ctx, NULL, 0))) /* Flush line. */
     213             :             {
     214           0 :               gpg_err_set_errno (EIO);
     215           0 :               goto leave;
     216             :             }
     217             :         }
     218           0 :       while (nbytes);
     219             :     }
     220             :   else
     221             :     {
     222           0 :       err = assuan_send_data (ctx, buffer, size);
     223           0 :       if (err)
     224             :         {
     225           0 :           gpg_err_set_errno (EIO);  /* For use by data_line_cookie_write.  */
     226           0 :           goto leave;
     227             :         }
     228             :     }
     229             : 
     230             :  leave:
     231           0 :   if (ctrl && ctrl->server_local && ctrl->server_local->inhibit_data_logging)
     232             :     {
     233           0 :       ctrl->server_local->inhibit_data_logging_now = 0;
     234           0 :       ctrl->server_local->inhibit_data_logging_count += size;
     235             :     }
     236             : 
     237           0 :   return err;
     238             : }
     239             : 
     240             : 
     241             : /* A write handler used by es_fopencookie to write assuan data
     242             :    lines.  */
     243             : static gpgrt_ssize_t
     244           0 : data_line_cookie_write (void *cookie, const void *buffer, size_t size)
     245             : {
     246           0 :   assuan_context_t ctx = cookie;
     247             : 
     248           0 :   if (data_line_write (ctx, buffer, size))
     249           0 :     return -1;
     250           0 :   return (gpgrt_ssize_t)size;
     251             : }
     252             : 
     253             : 
     254             : static int
     255           0 : data_line_cookie_close (void *cookie)
     256             : {
     257           0 :   assuan_context_t ctx = cookie;
     258             : 
     259           0 :   if (DBG_IPC)
     260             :     {
     261           0 :       ctrl_t ctrl = assuan_get_pointer (ctx);
     262             : 
     263           0 :       if (ctrl && ctrl->server_local
     264           0 :           && ctrl->server_local->inhibit_data_logging
     265           0 :           && ctrl->server_local->inhibit_data_logging_count)
     266           0 :         log_debug ("(%zu bytes sent via D lines not shown)\n",
     267           0 :                    ctrl->server_local->inhibit_data_logging_count);
     268             :     }
     269           0 :   if (assuan_send_data (ctx, NULL, 0))
     270             :     {
     271           0 :       gpg_err_set_errno (EIO);
     272           0 :       return -1;
     273             :     }
     274             : 
     275           0 :   return 0;
     276             : }
     277             : 
     278             : 
     279             : /* Copy the % and + escaped string S into the buffer D and replace the
     280             :    escape sequences.  Note, that it is sufficient to allocate the
     281             :    target string D as long as the source string S, i.e.: strlen(s)+1.
     282             :    Note further that if S contains an escaped binary Nul the resulting
     283             :    string D will contain the 0 as well as all other characters but it
     284             :    will be impossible to know whether this is the original EOS or a
     285             :    copied Nul. */
     286             : static void
     287           0 : strcpy_escaped_plus (char *d, const unsigned char *s)
     288             : {
     289           0 :   while (*s)
     290             :     {
     291           0 :       if (*s == '%' && s[1] && s[2])
     292             :         {
     293           0 :           s++;
     294           0 :           *d++ = xtoi_2 ( s);
     295           0 :           s += 2;
     296             :         }
     297           0 :       else if (*s == '+')
     298           0 :         *d++ = ' ', s++;
     299             :       else
     300           0 :         *d++ = *s++;
     301             :     }
     302           0 :   *d = 0;
     303           0 : }
     304             : 
     305             : 
     306             : /* This function returns true if a Tor server is running.  The sattus
     307             :    is cached for the current conenction.  */
     308             : static int
     309           0 : is_tor_running (ctrl_t ctrl)
     310             : {
     311             :   /* Check whether we can connect to the proxy.  */
     312             : 
     313           0 :   if (!ctrl || !ctrl->server_local)
     314           0 :     return 0; /* Ooops.  */
     315             : 
     316           0 :   if (!ctrl->server_local->tor_state)
     317             :     {
     318             :       assuan_fd_t sock;
     319             : 
     320           0 :       sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
     321           0 :       if (sock == ASSUAN_INVALID_FD)
     322           0 :         ctrl->server_local->tor_state = -1; /* Not running.  */
     323             :       else
     324             :         {
     325           0 :           assuan_sock_close (sock);
     326           0 :           ctrl->server_local->tor_state = 1; /* Running.  */
     327             :         }
     328             :     }
     329           0 :   return (ctrl->server_local->tor_state > 0);
     330             : }
     331             : 
     332             : 
     333             : /* Return an error if the assuan context does not belong to the owner
     334             :    of the process or to root.  On error FAILTEXT is set as Assuan
     335             :    error string.  */
     336             : static gpg_error_t
     337           0 : check_owner_permission (assuan_context_t ctx, const char *failtext)
     338             : {
     339             : #ifdef HAVE_W32_SYSTEM
     340             :   /* Under Windows the dirmngr is always run under the control of the
     341             :      user.  */
     342             :   (void)ctx;
     343             :   (void)failtext;
     344             : #else
     345             :   gpg_err_code_t ec;
     346             :   assuan_peercred_t cred;
     347             : 
     348           0 :   ec = gpg_err_code (assuan_get_peercred (ctx, &cred));
     349           0 :   if (!ec && cred->uid && cred->uid != getuid ())
     350           0 :     ec = GPG_ERR_EPERM;
     351           0 :   if (ec)
     352           0 :     return set_error (ec, failtext);
     353             : #endif
     354           0 :   return 0;
     355             : }
     356             : 
     357             : 
     358             : 
     359             : /* Common code for get_cert_local and get_issuer_cert_local. */
     360             : static ksba_cert_t
     361           0 : do_get_cert_local (ctrl_t ctrl, const char *name, const char *command)
     362             : {
     363             :   unsigned char *value;
     364             :   size_t valuelen;
     365             :   int rc;
     366             :   char *buf;
     367             :   ksba_cert_t cert;
     368             : 
     369           0 :   if (name)
     370             :     {
     371           0 :       buf = xmalloc ( strlen (command) + 1 + strlen(name) + 1);
     372           0 :       strcpy (stpcpy (stpcpy (buf, command), " "), name);
     373             :     }
     374             :   else
     375           0 :     buf = xstrdup (command);
     376             : 
     377           0 :   rc = assuan_inquire (ctrl->server_local->assuan_ctx, buf,
     378             :                        &value, &valuelen, MAX_CERT_LENGTH);
     379           0 :   xfree (buf);
     380           0 :   if (rc)
     381             :     {
     382           0 :       log_error (_("assuan_inquire(%s) failed: %s\n"),
     383             :                  command, gpg_strerror (rc));
     384           0 :       return NULL;
     385             :     }
     386             : 
     387           0 :   if (!valuelen)
     388             :     {
     389           0 :       xfree (value);
     390           0 :       return NULL;
     391             :     }
     392             : 
     393           0 :   rc = ksba_cert_new (&cert);
     394           0 :   if (!rc)
     395             :     {
     396           0 :       rc = ksba_cert_init_from_mem (cert, value, valuelen);
     397           0 :       if (rc)
     398             :         {
     399           0 :           ksba_cert_release (cert);
     400           0 :           cert = NULL;
     401             :         }
     402             :     }
     403           0 :   xfree (value);
     404           0 :   return cert;
     405             : }
     406             : 
     407             : 
     408             : 
     409             : /* Ask back to return a certificate for name, given as a regular
     410             :    gpgsm certificate indentificates (e.g. fingerprint or one of the
     411             :    other methods).  Alternatively, NULL may be used for NAME to
     412             :    return the current target certificate. Either return the certificate
     413             :    in a KSBA object or NULL if it is not available.
     414             : */
     415             : ksba_cert_t
     416           0 : get_cert_local (ctrl_t ctrl, const char *name)
     417             : {
     418           0 :   if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
     419             :     {
     420           0 :       if (opt.debug)
     421           0 :         log_debug ("get_cert_local called w/o context\n");
     422           0 :       return NULL;
     423             :     }
     424           0 :   return do_get_cert_local (ctrl, name, "SENDCERT");
     425             : 
     426             : }
     427             : 
     428             : /* Ask back to return the issuing certificate for name, given as a
     429             :    regular gpgsm certificate indentificates (e.g. fingerprint or one
     430             :    of the other methods).  Alternatively, NULL may be used for NAME to
     431             :    return thecurrent target certificate. Either return the certificate
     432             :    in a KSBA object or NULL if it is not available.
     433             : 
     434             : */
     435             : ksba_cert_t
     436           0 : get_issuing_cert_local (ctrl_t ctrl, const char *name)
     437             : {
     438           0 :   if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
     439             :     {
     440           0 :       if (opt.debug)
     441           0 :         log_debug ("get_issuing_cert_local called w/o context\n");
     442           0 :       return NULL;
     443             :     }
     444           0 :   return do_get_cert_local (ctrl, name, "SENDISSUERCERT");
     445             : }
     446             : 
     447             : /* Ask back to return a certificate with subject NAME and a
     448             :    subjectKeyIdentifier of KEYID. */
     449             : ksba_cert_t
     450           0 : get_cert_local_ski (ctrl_t ctrl, const char *name, ksba_sexp_t keyid)
     451             : {
     452             :   unsigned char *value;
     453             :   size_t valuelen;
     454             :   int rc;
     455             :   char *buf;
     456             :   ksba_cert_t cert;
     457             :   char *hexkeyid;
     458             : 
     459           0 :   if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
     460             :     {
     461           0 :       if (opt.debug)
     462           0 :         log_debug ("get_cert_local_ski called w/o context\n");
     463           0 :       return NULL;
     464             :     }
     465           0 :   if (!name || !keyid)
     466             :     {
     467           0 :       log_debug ("get_cert_local_ski called with insufficient arguments\n");
     468           0 :       return NULL;
     469             :     }
     470             : 
     471           0 :   hexkeyid = serial_hex (keyid);
     472           0 :   if (!hexkeyid)
     473             :     {
     474           0 :       log_debug ("serial_hex() failed\n");
     475           0 :       return NULL;
     476             :     }
     477             : 
     478           0 :   buf = xtrymalloc (15 + strlen (hexkeyid) + 2 + strlen(name) + 1);
     479           0 :   if (!buf)
     480             :     {
     481             : 
     482           0 :       log_error ("can't allocate enough memory: %s\n", strerror (errno));
     483           0 :       xfree (hexkeyid);
     484           0 :       return NULL;
     485             :     }
     486           0 :   strcpy (stpcpy (stpcpy (stpcpy (buf, "SENDCERT_SKI "), hexkeyid)," /"),name);
     487           0 :   xfree (hexkeyid);
     488             : 
     489           0 :   rc = assuan_inquire (ctrl->server_local->assuan_ctx, buf,
     490             :                        &value, &valuelen, MAX_CERT_LENGTH);
     491           0 :   xfree (buf);
     492           0 :   if (rc)
     493             :     {
     494           0 :       log_error (_("assuan_inquire(%s) failed: %s\n"), "SENDCERT_SKI",
     495             :                  gpg_strerror (rc));
     496           0 :       return NULL;
     497             :     }
     498             : 
     499           0 :   if (!valuelen)
     500             :     {
     501           0 :       xfree (value);
     502           0 :       return NULL;
     503             :     }
     504             : 
     505           0 :   rc = ksba_cert_new (&cert);
     506           0 :   if (!rc)
     507             :     {
     508           0 :       rc = ksba_cert_init_from_mem (cert, value, valuelen);
     509           0 :       if (rc)
     510             :         {
     511           0 :           ksba_cert_release (cert);
     512           0 :           cert = NULL;
     513             :         }
     514             :     }
     515           0 :   xfree (value);
     516           0 :   return cert;
     517             : }
     518             : 
     519             : 
     520             : /* Ask the client via an inquiry to check the istrusted status of the
     521             :    certificate specified by the hexified fingerprint HEXFPR.  Returns
     522             :    0 if the certificate is trusted by the client or an error code.  */
     523             : gpg_error_t
     524           0 : get_istrusted_from_client (ctrl_t ctrl, const char *hexfpr)
     525             : {
     526             :   unsigned char *value;
     527             :   size_t valuelen;
     528             :   int rc;
     529             :   char request[100];
     530             : 
     531           0 :   if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx
     532           0 :       || !hexfpr)
     533           0 :     return gpg_error (GPG_ERR_INV_ARG);
     534             : 
     535           0 :   snprintf (request, sizeof request, "ISTRUSTED %s", hexfpr);
     536           0 :   rc = assuan_inquire (ctrl->server_local->assuan_ctx, request,
     537             :                        &value, &valuelen, 100);
     538           0 :   if (rc)
     539             :     {
     540           0 :       log_error (_("assuan_inquire(%s) failed: %s\n"),
     541             :                  request, gpg_strerror (rc));
     542           0 :       return rc;
     543             :     }
     544             :   /* The expected data is: "1" or "1 cruft" (not a C-string).  */
     545           0 :   if (valuelen && *value == '1' && (valuelen == 1 || spacep (value+1)))
     546           0 :     rc = 0;
     547             :   else
     548           0 :     rc = gpg_error (GPG_ERR_NOT_TRUSTED);
     549           0 :   xfree (value);
     550           0 :   return rc;
     551             : }
     552             : 
     553             : 
     554             : 
     555             : 
     556             : /* Ask the client to return the certificate associated with the
     557             :    current command. This is sometimes needed because the client usually
     558             :    sends us just the cert ID, assuming that the request can be
     559             :    satisfied from the cache, where the cert ID is used as key. */
     560             : static int
     561           0 : inquire_cert_and_load_crl (assuan_context_t ctx)
     562             : {
     563           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
     564             :   gpg_error_t err;
     565           0 :   unsigned char *value = NULL;
     566             :   size_t valuelen;
     567           0 :   ksba_cert_t cert = NULL;
     568             : 
     569           0 :   err = assuan_inquire( ctx, "SENDCERT", &value, &valuelen, 0);
     570           0 :   if (err)
     571           0 :     return err;
     572             : 
     573             : /*   { */
     574             : /*     FILE *fp = fopen ("foo.der", "r"); */
     575             : /*     value = xmalloc (2000); */
     576             : /*     valuelen = fread (value, 1, 2000, fp); */
     577             : /*     fclose (fp); */
     578             : /*   } */
     579             : 
     580           0 :   if (!valuelen) /* No data returned; return a comprehensible error. */
     581           0 :     return gpg_error (GPG_ERR_MISSING_CERT);
     582             : 
     583           0 :   err = ksba_cert_new (&cert);
     584           0 :   if (err)
     585           0 :     goto leave;
     586           0 :   err = ksba_cert_init_from_mem (cert, value, valuelen);
     587           0 :   if(err)
     588           0 :     goto leave;
     589           0 :   xfree (value); value = NULL;
     590             : 
     591           0 :   err = crl_cache_reload_crl (ctrl, cert);
     592             : 
     593             :  leave:
     594           0 :   ksba_cert_release (cert);
     595           0 :   xfree (value);
     596           0 :   return err;
     597             : }
     598             : 
     599             : 
     600             : /* Handle OPTION commands. */
     601             : static gpg_error_t
     602           0 : option_handler (assuan_context_t ctx, const char *key, const char *value)
     603             : {
     604           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
     605           0 :   gpg_error_t err = 0;
     606             : 
     607           0 :   if (!strcmp (key, "force-crl-refresh"))
     608             :     {
     609           0 :       int i = *value? atoi (value) : 0;
     610           0 :       ctrl->force_crl_refresh = i;
     611             :     }
     612           0 :   else if (!strcmp (key, "audit-events"))
     613             :     {
     614           0 :       int i = *value? atoi (value) : 0;
     615           0 :       ctrl->audit_events = i;
     616             :     }
     617           0 :   else if (!strcmp (key, "http-proxy"))
     618             :     {
     619           0 :       xfree (ctrl->http_proxy);
     620           0 :       if (!*value || !strcmp (value, "none"))
     621           0 :         ctrl->http_proxy = NULL;
     622           0 :       else if (!(ctrl->http_proxy = xtrystrdup (value)))
     623           0 :         err = gpg_error_from_syserror ();
     624             :     }
     625           0 :   else if (!strcmp (key, "honor-keyserver-url-used"))
     626             :     {
     627             :       /* Return an error if we are running in Tor mode.  */
     628           0 :       if (opt.use_tor)
     629           0 :         err = gpg_error (GPG_ERR_FORBIDDEN);
     630             :     }
     631             :   else
     632           0 :     err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
     633             : 
     634           0 :   return err;
     635             : }
     636             : 
     637             : 
     638             : 
     639             : static const char hlp_dns_cert[] =
     640             :   "DNS_CERT <subtype> <name>\n"
     641             :   "DNS_CERT --pka <user_id>\n"
     642             :   "DNS_CERT --dane <user_id>\n"
     643             :   "\n"
     644             :   "Return the CERT record for <name>.  <subtype> is one of\n"
     645             :   "  *     Return the first record of any supported subtype\n"
     646             :   "  PGP   Return the first record of subtype PGP (3)\n"
     647             :   "  IPGP  Return the first record of subtype IPGP (6)\n"
     648             :   "If the content of a certificate is available (PGP) it is returned\n"
     649             :   "by data lines.  Fingerprints and URLs are returned via status lines.\n"
     650             :   "In --pka mode the fingerprint and if available an URL is returned.\n"
     651             :   "In --dane mode the key is returned from RR type 61";
     652             : static gpg_error_t
     653           0 : cmd_dns_cert (assuan_context_t ctx, char *line)
     654             : {
     655             :   /* ctrl_t ctrl = assuan_get_pointer (ctx); */
     656           0 :   gpg_error_t err = 0;
     657             :   int pka_mode, dane_mode;
     658           0 :   char *mbox = NULL;
     659           0 :   char *namebuf = NULL;
     660           0 :   char *encodedhash = NULL;
     661             :   const char *name;
     662             :   int certtype;
     663             :   char *p;
     664           0 :   void *key = NULL;
     665             :   size_t keylen;
     666           0 :   unsigned char *fpr = NULL;
     667             :   size_t fprlen;
     668           0 :   char *url = NULL;
     669             : 
     670           0 :   pka_mode = has_option (line, "--pka");
     671           0 :   dane_mode = has_option (line, "--dane");
     672           0 :   line = skip_options (line);
     673             : 
     674           0 :   if (pka_mode && dane_mode)
     675             :     {
     676           0 :       err = PARM_ERROR ("either --pka or --dane may be given");
     677           0 :       goto leave;
     678             :     }
     679             : 
     680           0 :   if (pka_mode || dane_mode)
     681             :     ; /* No need to parse here - we do this later.  */
     682             :   else
     683             :     {
     684           0 :       p = strchr (line, ' ');
     685           0 :       if (!p)
     686             :         {
     687           0 :           err = PARM_ERROR ("missing arguments");
     688           0 :           goto leave;
     689             :         }
     690           0 :       *p++ = 0;
     691           0 :       if (!strcmp (line, "*"))
     692           0 :         certtype = DNS_CERTTYPE_ANY;
     693           0 :       else if (!strcmp (line, "IPGP"))
     694           0 :         certtype = DNS_CERTTYPE_IPGP;
     695           0 :       else if (!strcmp (line, "PGP"))
     696           0 :         certtype = DNS_CERTTYPE_PGP;
     697             :       else
     698             :         {
     699           0 :           err = PARM_ERROR ("unknown subtype");
     700           0 :           goto leave;
     701             :         }
     702           0 :       while (spacep (p))
     703           0 :         p++;
     704           0 :       line = p;
     705           0 :       if (!*line)
     706             :         {
     707           0 :           err = PARM_ERROR ("name missing");
     708           0 :           goto leave;
     709             :         }
     710             :     }
     711             : 
     712           0 :   if (opt.use_tor && (err = enable_dns_tormode (0)))
     713             :     {
     714             :       /* Tor mode is requested but the DNS code can't enable it.  */
     715           0 :       assuan_set_error (ctx, err, "error enabling Tor mode");
     716           0 :       goto leave;
     717             :     }
     718             : 
     719           0 :   if (pka_mode || dane_mode)
     720           0 :     {
     721             :       char *domain;     /* Points to mbox.  */
     722             :       char hashbuf[32]; /* For SHA-1 and SHA-256. */
     723             : 
     724             :       /* We lowercase ascii characters but the DANE I-D does not allow
     725             :          this.  FIXME: Check after the release of the RFC whether to
     726             :          change this.  */
     727           0 :       mbox = mailbox_from_userid (line);
     728           0 :       if (!mbox || !(domain = strchr (mbox, '@')))
     729             :         {
     730           0 :           err = set_error (GPG_ERR_INV_USER_ID, "no mailbox in user id");
     731           0 :           goto leave;
     732             :         }
     733           0 :       *domain++ = 0;
     734             : 
     735           0 :       if (pka_mode)
     736             :         {
     737           0 :           gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf, mbox, strlen (mbox));
     738           0 :           encodedhash = zb32_encode (hashbuf, 8*20);
     739           0 :           if (!encodedhash)
     740             :             {
     741           0 :               err = gpg_error_from_syserror ();
     742           0 :               goto leave;
     743             :             }
     744           0 :           namebuf = strconcat (encodedhash, "._pka.", domain, NULL);
     745           0 :           if (!namebuf)
     746             :             {
     747           0 :               err = gpg_error_from_syserror ();
     748           0 :               goto leave;
     749             :             }
     750           0 :           name = namebuf;
     751           0 :           certtype = DNS_CERTTYPE_IPGP;
     752             :         }
     753             :       else
     754             :         {
     755             :           /* Note: The hash is truncated to 28 bytes and we lowercase
     756             :              the result only for aesthetic reasons.  */
     757           0 :           gcry_md_hash_buffer (GCRY_MD_SHA256, hashbuf, mbox, strlen (mbox));
     758           0 :           encodedhash = bin2hex (hashbuf, 28, NULL);
     759           0 :           if (!encodedhash)
     760             :             {
     761           0 :               err = gpg_error_from_syserror ();
     762           0 :               goto leave;
     763             :             }
     764           0 :           ascii_strlwr (encodedhash);
     765           0 :           namebuf = strconcat (encodedhash, "._openpgpkey.", domain, NULL);
     766           0 :           if (!namebuf)
     767             :             {
     768           0 :               err = gpg_error_from_syserror ();
     769           0 :               goto leave;
     770             :             }
     771           0 :           name = namebuf;
     772           0 :           certtype = DNS_CERTTYPE_RR61;
     773             :         }
     774             :     }
     775             :   else
     776           0 :     name = line;
     777             : 
     778           0 :   err = get_dns_cert (name, certtype, &key, &keylen, &fpr, &fprlen, &url);
     779           0 :   if (err)
     780           0 :     goto leave;
     781             : 
     782           0 :   if (key)
     783             :     {
     784           0 :       err = data_line_write (ctx, key, keylen);
     785           0 :       if (err)
     786           0 :         goto leave;
     787             :     }
     788             : 
     789           0 :   if (fpr)
     790             :     {
     791             :       char *tmpstr;
     792             : 
     793           0 :       tmpstr = bin2hex (fpr, fprlen, NULL);
     794           0 :       if (!tmpstr)
     795           0 :         err = gpg_error_from_syserror ();
     796             :       else
     797             :         {
     798           0 :           err = assuan_write_status (ctx, "FPR", tmpstr);
     799           0 :           xfree (tmpstr);
     800             :         }
     801           0 :       if (err)
     802           0 :         goto leave;
     803             :     }
     804             : 
     805           0 :   if (url)
     806             :     {
     807           0 :       err = assuan_write_status (ctx, "URL", url);
     808           0 :       if (err)
     809           0 :         goto leave;
     810             :     }
     811             : 
     812             : 
     813             :  leave:
     814           0 :   xfree (key);
     815           0 :   xfree (fpr);
     816           0 :   xfree (url);
     817           0 :   xfree (mbox);
     818           0 :   xfree (namebuf);
     819           0 :   xfree (encodedhash);
     820           0 :   return leave_cmd (ctx, err);
     821             : }
     822             : 
     823             : 
     824             : 
     825             : static const char hlp_wkd_get[] =
     826             :   "WKD_GET [--submission-address|--policy-flags] <user_id>\n"
     827             :   "\n"
     828             :   "Return the key or other info for <user_id>\n"
     829             :   "from the Web Key Directory.";
     830             : static gpg_error_t
     831           0 : cmd_wkd_get (assuan_context_t ctx, char *line)
     832             : {
     833           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
     834           0 :   gpg_error_t err = 0;
     835           0 :   char *mbox = NULL;
     836             :   char *domain;     /* Points to mbox.  */
     837             :   char sha1buf[20];
     838           0 :   char *uri = NULL;
     839           0 :   char *encodedhash = NULL;
     840             :   int opt_submission_addr;
     841             :   int opt_policy_flags;
     842           0 :   int no_log = 0;
     843             : 
     844           0 :   opt_submission_addr = has_option (line, "--submission-address");
     845           0 :   opt_policy_flags = has_option (line, "--policy-flags");
     846           0 :   line = skip_options (line);
     847             : 
     848           0 :   mbox = mailbox_from_userid (line);
     849           0 :   if (!mbox || !(domain = strchr (mbox, '@')))
     850             :     {
     851           0 :       err = set_error (GPG_ERR_INV_USER_ID, "no mailbox in user id");
     852           0 :       goto leave;
     853             :     }
     854           0 :   *domain++ = 0;
     855             : 
     856           0 :   gcry_md_hash_buffer (GCRY_MD_SHA1, sha1buf, mbox, strlen (mbox));
     857           0 :   encodedhash = zb32_encode (sha1buf, 8*20);
     858           0 :   if (!encodedhash)
     859             :     {
     860           0 :       err = gpg_error_from_syserror ();
     861           0 :       goto leave;
     862             :     }
     863             : 
     864           0 :   if (opt_submission_addr)
     865             :     {
     866           0 :       uri = strconcat ("https://",
     867             :                        domain,
     868             :                        "/.well-known/openpgpkey/submission-address",
     869             :                        NULL);
     870             :     }
     871           0 :   else if (opt_policy_flags)
     872             :     {
     873           0 :       uri = strconcat ("https://",
     874             :                        domain,
     875             :                        "/.well-known/openpgpkey/policy",
     876             :                        NULL);
     877             :     }
     878             :   else
     879             :     {
     880           0 :       uri = strconcat ("https://",
     881             :                        domain,
     882             :                        "/.well-known/openpgpkey/hu/",
     883             :                        encodedhash,
     884             :                        NULL);
     885           0 :       no_log = 1;
     886             :     }
     887           0 :   if (!uri)
     888             :     {
     889           0 :       err = gpg_error_from_syserror ();
     890           0 :       goto leave;
     891             :     }
     892             : 
     893             :   /* Setup an output stream and perform the get.  */
     894             :   {
     895             :     estream_t outfp;
     896             : 
     897           0 :     outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
     898           0 :     if (!outfp)
     899           0 :       err = set_error (GPG_ERR_ASS_GENERAL,
     900             :                        "error setting up a data stream");
     901             :     else
     902             :       {
     903           0 :         if (no_log)
     904           0 :           ctrl->server_local->inhibit_data_logging = 1;
     905           0 :         ctrl->server_local->inhibit_data_logging_now = 0;
     906           0 :         ctrl->server_local->inhibit_data_logging_count = 0;
     907           0 :         err = ks_action_fetch (ctrl, uri, outfp);
     908           0 :         es_fclose (outfp);
     909           0 :         ctrl->server_local->inhibit_data_logging = 0;
     910             :       }
     911             :   }
     912             : 
     913             :  leave:
     914           0 :   xfree (uri);
     915           0 :   xfree (encodedhash);
     916           0 :   xfree (mbox);
     917           0 :   return leave_cmd (ctx, err);
     918             : }
     919             : 
     920             : 
     921             : 
     922             : static const char hlp_ldapserver[] =
     923             :   "LDAPSERVER <data>\n"
     924             :   "\n"
     925             :   "Add a new LDAP server to the list of configured LDAP servers.\n"
     926             :   "DATA is in the same format as expected in the configure file.";
     927             : static gpg_error_t
     928           0 : cmd_ldapserver (assuan_context_t ctx, char *line)
     929             : {
     930             : #if USE_LDAP
     931           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
     932             :   ldap_server_t server;
     933             :   ldap_server_t *last_next_p;
     934             : 
     935           0 :   while (spacep (line))
     936           0 :     line++;
     937           0 :   if (*line == '\0')
     938           0 :     return leave_cmd (ctx, PARM_ERROR (_("ldapserver missing")));
     939             : 
     940           0 :   server = ldapserver_parse_one (line, "", 0);
     941           0 :   if (! server)
     942           0 :     return leave_cmd (ctx, gpg_error (GPG_ERR_INV_ARG));
     943             : 
     944           0 :   last_next_p = &ctrl->server_local->ldapservers;
     945           0 :   while (*last_next_p)
     946           0 :     last_next_p = &(*last_next_p)->next;
     947           0 :   *last_next_p = server;
     948           0 :   return leave_cmd (ctx, 0);
     949             : #else
     950             :   (void)line;
     951             :   return leave_cmd (ctx, gpg_error (GPG_ERR_NOT_IMPLEMENTED));
     952             : #endif
     953             : }
     954             : 
     955             : 
     956             : static const char hlp_isvalid[] =
     957             :   "ISVALID [--only-ocsp] [--force-default-responder]"
     958             :   " <certificate_id>|<certificate_fpr>\n"
     959             :   "\n"
     960             :   "This command checks whether the certificate identified by the\n"
     961             :   "certificate_id is valid.  This is done by consulting CRLs or\n"
     962             :   "whatever has been configured.  Note, that the returned error codes\n"
     963             :   "are from gpg-error.h.  The command may callback using the inquire\n"
     964             :   "function.  See the manual for details.\n"
     965             :   "\n"
     966             :   "The CERTIFICATE_ID is a hex encoded string consisting of two parts,\n"
     967             :   "delimited by a single dot.  The first part is the SHA-1 hash of the\n"
     968             :   "issuer name and the second part the serial number.\n"
     969             :   "\n"
     970             :   "Alternatively the certificate's fingerprint may be given in which\n"
     971             :   "case an OCSP request is done before consulting the CRL.\n"
     972             :   "\n"
     973             :   "If the option --only-ocsp is given, no fallback to a CRL check will\n"
     974             :   "be used.\n"
     975             :   "\n"
     976             :   "If the option --force-default-responder is given, only the default\n"
     977             :   "OCSP responder will be used and any other methods of obtaining an\n"
     978             :   "OCSP responder URL won't be used.";
     979             : static gpg_error_t
     980           0 : cmd_isvalid (assuan_context_t ctx, char *line)
     981             : {
     982           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
     983             :   char *issuerhash, *serialno;
     984             :   gpg_error_t err;
     985           0 :   int did_inquire = 0;
     986           0 :   int ocsp_mode = 0;
     987             :   int only_ocsp;
     988             :   int force_default_responder;
     989             : 
     990           0 :   only_ocsp = has_option (line, "--only-ocsp");
     991           0 :   force_default_responder = has_option (line, "--force-default-responder");
     992           0 :   line = skip_options (line);
     993             : 
     994           0 :   issuerhash = xstrdup (line); /* We need to work on a copy of the
     995             :                                   line because that same Assuan
     996             :                                   context may be used for an inquiry.
     997             :                                   That is because Assuan reuses its
     998             :                                   line buffer.
     999             :                                    */
    1000             : 
    1001           0 :   serialno = strchr (issuerhash, '.');
    1002           0 :   if (serialno)
    1003           0 :     *serialno++ = 0;
    1004             :   else
    1005             :     {
    1006           0 :       char *endp = strchr (issuerhash, ' ');
    1007           0 :       if (endp)
    1008           0 :         *endp = 0;
    1009           0 :       if (strlen (issuerhash) != 40)
    1010             :         {
    1011           0 :           xfree (issuerhash);
    1012           0 :           return leave_cmd (ctx, PARM_ERROR (_("serialno missing in cert ID")));
    1013             :         }
    1014           0 :       ocsp_mode = 1;
    1015             :     }
    1016             : 
    1017             : 
    1018             :  again:
    1019           0 :   if (ocsp_mode)
    1020             :     {
    1021             :       /* Note, that we ignore the given issuer hash and instead rely
    1022             :          on the current certificate semantics used with this
    1023             :          command. */
    1024           0 :       if (!opt.allow_ocsp)
    1025           0 :         err = gpg_error (GPG_ERR_NOT_SUPPORTED);
    1026             :       else
    1027           0 :         err = ocsp_isvalid (ctrl, NULL, NULL, force_default_responder);
    1028             :       /* Fixme: If we got no ocsp response and --only-ocsp is not used
    1029             :          we should fall back to CRL mode.  Thus we need to clear
    1030             :          OCSP_MODE, get the issuerhash and the serialno from the
    1031             :          current certificate and jump to again. */
    1032             :     }
    1033           0 :   else if (only_ocsp)
    1034           0 :     err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
    1035             :   else
    1036             :     {
    1037           0 :       switch (crl_cache_isvalid (ctrl,
    1038             :                                  issuerhash, serialno,
    1039             :                                  ctrl->force_crl_refresh))
    1040             :         {
    1041             :         case CRL_CACHE_VALID:
    1042           0 :           err = 0;
    1043           0 :           break;
    1044             :         case CRL_CACHE_INVALID:
    1045           0 :           err = gpg_error (GPG_ERR_CERT_REVOKED);
    1046           0 :           break;
    1047             :         case CRL_CACHE_DONTKNOW:
    1048           0 :           if (did_inquire)
    1049           0 :             err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
    1050           0 :           else if (!(err = inquire_cert_and_load_crl (ctx)))
    1051             :             {
    1052           0 :               did_inquire = 1;
    1053           0 :               goto again;
    1054             :             }
    1055           0 :           break;
    1056             :         case CRL_CACHE_CANTUSE:
    1057           0 :           err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
    1058           0 :           break;
    1059             :         default:
    1060           0 :           log_fatal ("crl_cache_isvalid returned invalid code\n");
    1061             :         }
    1062             :     }
    1063             : 
    1064           0 :   xfree (issuerhash);
    1065           0 :   return leave_cmd (ctx, err);
    1066             : }
    1067             : 
    1068             : 
    1069             : /* If the line contains a SHA-1 fingerprint as the first argument,
    1070             :    return the FPR vuffer on success.  The function checks that the
    1071             :    fingerprint consists of valid characters and prints and error
    1072             :    message if it does not and returns NULL.  Fingerprints are
    1073             :    considered optional and thus no explicit error is returned. NULL is
    1074             :    also returned if there is no fingerprint at all available.
    1075             :    FPR must be a caller provided buffer of at least 20 bytes.
    1076             : 
    1077             :    Note that colons within the fingerprint are allowed to separate 2
    1078             :    hex digits; this allows for easier cutting and pasting using the
    1079             :    usual fingerprint rendering.
    1080             : */
    1081             : static unsigned char *
    1082           0 : get_fingerprint_from_line (const char *line, unsigned char *fpr)
    1083             : {
    1084             :   const char *s;
    1085             :   int i;
    1086             : 
    1087           0 :   for (s=line, i=0; *s && *s != ' '; s++ )
    1088             :     {
    1089           0 :       if ( hexdigitp (s) && hexdigitp (s+1) )
    1090             :         {
    1091           0 :           if ( i >= 20 )
    1092           0 :             return NULL;  /* Fingerprint too long.  */
    1093           0 :           fpr[i++] = xtoi_2 (s);
    1094           0 :           s++;
    1095             :         }
    1096           0 :       else if ( *s != ':' )
    1097           0 :         return NULL; /* Invalid.  */
    1098             :     }
    1099           0 :   if ( i != 20 )
    1100           0 :     return NULL; /* Fingerprint to short.  */
    1101           0 :   return fpr;
    1102             : }
    1103             : 
    1104             : 
    1105             : 
    1106             : static const char hlp_checkcrl[] =
    1107             :   "CHECKCRL [<fingerprint>]\n"
    1108             :   "\n"
    1109             :   "Check whether the certificate with FINGERPRINT (SHA-1 hash of the\n"
    1110             :   "entire X.509 certificate blob) is valid or not by consulting the\n"
    1111             :   "CRL responsible for this certificate.  If the fingerprint has not\n"
    1112             :   "been given or the certificate is not known, the function \n"
    1113             :   "inquires the certificate using an\n"
    1114             :   "\n"
    1115             :   "  INQUIRE TARGETCERT\n"
    1116             :   "\n"
    1117             :   "and the caller is expected to return the certificate for the\n"
    1118             :   "request (which should match FINGERPRINT) as a binary blob.\n"
    1119             :   "Processing then takes place without further interaction; in\n"
    1120             :   "particular dirmngr tries to locate other required certificate by\n"
    1121             :   "its own mechanism which includes a local certificate store as well\n"
    1122             :   "as a list of trusted root certificates.\n"
    1123             :   "\n"
    1124             :   "The return value is the usual gpg-error code or 0 for ducesss;\n"
    1125             :   "i.e. the certificate validity has been confirmed by a valid CRL.";
    1126             : static gpg_error_t
    1127           0 : cmd_checkcrl (assuan_context_t ctx, char *line)
    1128             : {
    1129           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    1130             :   gpg_error_t err;
    1131             :   unsigned char fprbuffer[20], *fpr;
    1132             :   ksba_cert_t cert;
    1133             : 
    1134           0 :   fpr = get_fingerprint_from_line (line, fprbuffer);
    1135           0 :   cert = fpr? get_cert_byfpr (fpr) : NULL;
    1136             : 
    1137           0 :   if (!cert)
    1138             :     {
    1139             :       /* We do not have this certificate yet or the fingerprint has
    1140             :          not been given.  Inquire it from the client.  */
    1141           0 :       unsigned char *value = NULL;
    1142             :       size_t valuelen;
    1143             : 
    1144           0 :       err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
    1145             :                            &value, &valuelen, MAX_CERT_LENGTH);
    1146           0 :       if (err)
    1147             :         {
    1148           0 :           log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
    1149           0 :           goto leave;
    1150             :         }
    1151             : 
    1152           0 :       if (!valuelen) /* No data returned; return a comprehensible error. */
    1153           0 :         err = gpg_error (GPG_ERR_MISSING_CERT);
    1154             :       else
    1155             :         {
    1156           0 :           err = ksba_cert_new (&cert);
    1157           0 :           if (!err)
    1158           0 :             err = ksba_cert_init_from_mem (cert, value, valuelen);
    1159             :         }
    1160           0 :       xfree (value);
    1161           0 :       if(err)
    1162           0 :         goto leave;
    1163             :     }
    1164             : 
    1165           0 :   assert (cert);
    1166             : 
    1167           0 :   err = crl_cache_cert_isvalid (ctrl, cert, ctrl->force_crl_refresh);
    1168           0 :   if (gpg_err_code (err) == GPG_ERR_NO_CRL_KNOWN)
    1169             :     {
    1170           0 :       err = crl_cache_reload_crl (ctrl, cert);
    1171           0 :       if (!err)
    1172           0 :         err = crl_cache_cert_isvalid (ctrl, cert, 0);
    1173             :     }
    1174             : 
    1175             :  leave:
    1176           0 :   ksba_cert_release (cert);
    1177           0 :   return leave_cmd (ctx, err);
    1178             : }
    1179             : 
    1180             : 
    1181             : static const char hlp_checkocsp[] =
    1182             :   "CHECKOCSP [--force-default-responder] [<fingerprint>]\n"
    1183             :   "\n"
    1184             :   "Check whether the certificate with FINGERPRINT (SHA-1 hash of the\n"
    1185             :   "entire X.509 certificate blob) is valid or not by asking an OCSP\n"
    1186             :   "responder responsible for this certificate.  The optional\n"
    1187             :   "fingerprint may be used for a quick check in case an OCSP check has\n"
    1188             :   "been done for this certificate recently (we always cache OCSP\n"
    1189             :   "responses for a couple of minutes). If the fingerprint has not been\n"
    1190             :   "given or there is no cached result, the function inquires the\n"
    1191             :   "certificate using an\n"
    1192             :   "\n"
    1193             :   "   INQUIRE TARGETCERT\n"
    1194             :   "\n"
    1195             :   "and the caller is expected to return the certificate for the\n"
    1196             :   "request (which should match FINGERPRINT) as a binary blob.\n"
    1197             :   "Processing then takes place without further interaction; in\n"
    1198             :   "particular dirmngr tries to locate other required certificates by\n"
    1199             :   "its own mechanism which includes a local certificate store as well\n"
    1200             :   "as a list of trusted root certificates.\n"
    1201             :   "\n"
    1202             :   "If the option --force-default-responder is given, only the default\n"
    1203             :   "OCSP responder will be used and any other methods of obtaining an\n"
    1204             :   "OCSP responder URL won't be used.\n"
    1205             :   "\n"
    1206             :   "The return value is the usual gpg-error code or 0 for ducesss;\n"
    1207             :   "i.e. the certificate validity has been confirmed by a valid CRL.";
    1208             : static gpg_error_t
    1209           0 : cmd_checkocsp (assuan_context_t ctx, char *line)
    1210             : {
    1211           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    1212             :   gpg_error_t err;
    1213             :   unsigned char fprbuffer[20], *fpr;
    1214             :   ksba_cert_t cert;
    1215             :   int force_default_responder;
    1216             : 
    1217           0 :   force_default_responder = has_option (line, "--force-default-responder");
    1218           0 :   line = skip_options (line);
    1219             : 
    1220           0 :   fpr = get_fingerprint_from_line (line, fprbuffer);
    1221           0 :   cert = fpr? get_cert_byfpr (fpr) : NULL;
    1222             : 
    1223           0 :   if (!cert)
    1224             :     {
    1225             :       /* We do not have this certificate yet or the fingerprint has
    1226             :          not been given.  Inquire it from the client.  */
    1227           0 :       unsigned char *value = NULL;
    1228             :       size_t valuelen;
    1229             : 
    1230           0 :       err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
    1231             :                            &value, &valuelen, MAX_CERT_LENGTH);
    1232           0 :       if (err)
    1233             :         {
    1234           0 :           log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
    1235           0 :           goto leave;
    1236             :         }
    1237             : 
    1238           0 :       if (!valuelen) /* No data returned; return a comprehensible error. */
    1239           0 :         err = gpg_error (GPG_ERR_MISSING_CERT);
    1240             :       else
    1241             :         {
    1242           0 :           err = ksba_cert_new (&cert);
    1243           0 :           if (!err)
    1244           0 :             err = ksba_cert_init_from_mem (cert, value, valuelen);
    1245             :         }
    1246           0 :       xfree (value);
    1247           0 :       if(err)
    1248           0 :         goto leave;
    1249             :     }
    1250             : 
    1251           0 :   assert (cert);
    1252             : 
    1253           0 :   if (!opt.allow_ocsp)
    1254           0 :     err = gpg_error (GPG_ERR_NOT_SUPPORTED);
    1255             :   else
    1256           0 :     err = ocsp_isvalid (ctrl, cert, NULL, force_default_responder);
    1257             : 
    1258             :  leave:
    1259           0 :   ksba_cert_release (cert);
    1260           0 :   return leave_cmd (ctx, err);
    1261             : }
    1262             : 
    1263             : 
    1264             : 
    1265             : static int
    1266           0 : lookup_cert_by_url (assuan_context_t ctx, const char *url)
    1267             : {
    1268           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    1269           0 :   gpg_error_t err = 0;
    1270           0 :   unsigned char *value = NULL;
    1271             :   size_t valuelen;
    1272             : 
    1273             :   /* Fetch single certificate given it's URL.  */
    1274           0 :   err = fetch_cert_by_url (ctrl, url, &value, &valuelen);
    1275           0 :   if (err)
    1276             :     {
    1277           0 :       log_error (_("fetch_cert_by_url failed: %s\n"), gpg_strerror (err));
    1278           0 :       goto leave;
    1279             :     }
    1280             : 
    1281             :   /* Send the data, flush the buffer and then send an END. */
    1282           0 :   err = assuan_send_data (ctx, value, valuelen);
    1283           0 :   if (!err)
    1284           0 :     err = assuan_send_data (ctx, NULL, 0);
    1285           0 :   if (!err)
    1286           0 :     err = assuan_write_line (ctx, "END");
    1287           0 :   if (err)
    1288             :     {
    1289           0 :       log_error (_("error sending data: %s\n"), gpg_strerror (err));
    1290           0 :       goto leave;
    1291             :     }
    1292             : 
    1293             :  leave:
    1294             : 
    1295           0 :   return err;
    1296             : }
    1297             : 
    1298             : 
    1299             : /* Send the certificate, flush the buffer and then send an END. */
    1300             : static gpg_error_t
    1301           0 : return_one_cert (void *opaque, ksba_cert_t cert)
    1302             : {
    1303           0 :   assuan_context_t ctx = opaque;
    1304             :   gpg_error_t err;
    1305             :   const unsigned char *der;
    1306             :   size_t derlen;
    1307             : 
    1308           0 :   der = ksba_cert_get_image (cert, &derlen);
    1309           0 :   if (!der)
    1310           0 :     err = gpg_error (GPG_ERR_INV_CERT_OBJ);
    1311             :   else
    1312             :     {
    1313           0 :       err = assuan_send_data (ctx, der, derlen);
    1314           0 :       if (!err)
    1315           0 :         err = assuan_send_data (ctx, NULL, 0);
    1316           0 :       if (!err)
    1317           0 :         err = assuan_write_line (ctx, "END");
    1318             :     }
    1319           0 :   if (err)
    1320           0 :     log_error (_("error sending data: %s\n"), gpg_strerror (err));
    1321           0 :   return err;
    1322             : }
    1323             : 
    1324             : 
    1325             : /* Lookup certificates from the internal cache or using the ldap
    1326             :    servers. */
    1327             : static int
    1328           0 : lookup_cert_by_pattern (assuan_context_t ctx, char *line,
    1329             :                         int single, int cache_only)
    1330             : {
    1331           0 :   gpg_error_t err = 0;
    1332             :   char *p;
    1333           0 :   strlist_t sl, list = NULL;
    1334           0 :   int truncated = 0, truncation_forced = 0;
    1335           0 :   int count = 0;
    1336           0 :   int local_count = 0;
    1337             : #if USE_LDAP
    1338           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    1339           0 :   unsigned char *value = NULL;
    1340             :   size_t valuelen;
    1341             :   struct ldapserver_iter ldapserver_iter;
    1342             :   cert_fetch_context_t fetch_context;
    1343             : #endif /*USE_LDAP*/
    1344           0 :   int any_no_data = 0;
    1345             : 
    1346             :   /* Break the line down into an STRLIST */
    1347           0 :   for (p=line; *p; line = p)
    1348             :     {
    1349           0 :       while (*p && *p != ' ')
    1350           0 :         p++;
    1351           0 :       if (*p)
    1352           0 :         *p++ = 0;
    1353             : 
    1354           0 :       if (*line)
    1355             :         {
    1356           0 :           sl = xtrymalloc (sizeof *sl + strlen (line));
    1357           0 :           if (!sl)
    1358             :             {
    1359           0 :               err = gpg_error_from_errno (errno);
    1360           0 :               goto leave;
    1361             :             }
    1362           0 :           memset (sl, 0, sizeof *sl);
    1363           0 :           strcpy_escaped_plus (sl->d, line);
    1364           0 :           sl->next = list;
    1365           0 :           list = sl;
    1366             :         }
    1367             :     }
    1368             : 
    1369             :   /* First look through the internal cache.  The certifcates retruned
    1370             :      here are not counted towards the truncation limit.  */
    1371           0 :   if (single && !cache_only)
    1372             :     ; /* Do not read from the local cache in this case.  */
    1373             :   else
    1374             :     {
    1375           0 :       for (sl=list; sl; sl = sl->next)
    1376             :         {
    1377           0 :           err = get_certs_bypattern (sl->d, return_one_cert, ctx);
    1378           0 :           if (!err)
    1379           0 :             local_count++;
    1380           0 :           if (!err && single)
    1381           0 :             goto ready;
    1382             : 
    1383           0 :           if (gpg_err_code (err) == GPG_ERR_NO_DATA)
    1384             :             {
    1385           0 :               err = 0;
    1386           0 :               if (cache_only)
    1387           0 :                 any_no_data = 1;
    1388             :             }
    1389           0 :           else if (gpg_err_code (err) == GPG_ERR_INV_NAME && !cache_only)
    1390             :             {
    1391             :               /* No real fault because the internal pattern lookup
    1392             :                  can't yet cope with all types of pattern.  */
    1393           0 :               err = 0;
    1394             :             }
    1395           0 :           if (err)
    1396           0 :             goto ready;
    1397             :         }
    1398             :     }
    1399             : 
    1400             :   /* Loop over all configured servers unless we want only the
    1401             :      certificates from the cache.  */
    1402             : #if USE_LDAP
    1403           0 :   for (ldapserver_iter_begin (&ldapserver_iter, ctrl);
    1404           0 :        !cache_only && !ldapserver_iter_end_p (&ldapserver_iter)
    1405           0 :          && ldapserver_iter.server->host && !truncation_forced;
    1406           0 :        ldapserver_iter_next (&ldapserver_iter))
    1407             :     {
    1408           0 :       ldap_server_t ldapserver = ldapserver_iter.server;
    1409             : 
    1410           0 :       if (DBG_LOOKUP)
    1411           0 :         log_debug ("cmd_lookup: trying %s:%d base=%s\n",
    1412             :                    ldapserver->host, ldapserver->port,
    1413           0 :                    ldapserver->base?ldapserver->base : "[default]");
    1414             : 
    1415             :       /* Fetch certificates matching pattern */
    1416           0 :       err = start_cert_fetch (ctrl, &fetch_context, list, ldapserver);
    1417           0 :       if ( gpg_err_code (err) == GPG_ERR_NO_DATA )
    1418             :         {
    1419           0 :           if (DBG_LOOKUP)
    1420           0 :             log_debug ("cmd_lookup: no data\n");
    1421           0 :           err = 0;
    1422           0 :           any_no_data = 1;
    1423           0 :           continue;
    1424             :         }
    1425           0 :       if (err)
    1426             :         {
    1427           0 :           log_error (_("start_cert_fetch failed: %s\n"), gpg_strerror (err));
    1428           0 :           goto leave;
    1429             :         }
    1430             : 
    1431             :       /* Fetch the certificates for this query. */
    1432           0 :       while (!truncation_forced)
    1433             :         {
    1434           0 :           xfree (value); value = NULL;
    1435           0 :           err = fetch_next_cert (fetch_context, &value, &valuelen);
    1436           0 :           if (gpg_err_code (err) == GPG_ERR_NO_DATA )
    1437             :             {
    1438           0 :               err = 0;
    1439           0 :               any_no_data = 1;
    1440           0 :               break; /* Ready. */
    1441             :             }
    1442           0 :           if (gpg_err_code (err) == GPG_ERR_TRUNCATED)
    1443             :             {
    1444           0 :               truncated = 1;
    1445           0 :               err = 0;
    1446           0 :               break;  /* Ready.  */
    1447             :             }
    1448           0 :           if (gpg_err_code (err) == GPG_ERR_EOF)
    1449             :             {
    1450           0 :               err = 0;
    1451           0 :               break; /* Ready. */
    1452             :             }
    1453           0 :           if (!err && !value)
    1454             :             {
    1455           0 :               err = gpg_error (GPG_ERR_BUG);
    1456           0 :               goto leave;
    1457             :             }
    1458           0 :           if (err)
    1459             :             {
    1460           0 :               log_error (_("fetch_next_cert failed: %s\n"),
    1461             :                          gpg_strerror (err));
    1462           0 :               end_cert_fetch (fetch_context);
    1463           0 :               goto leave;
    1464             :             }
    1465             : 
    1466           0 :           if (DBG_LOOKUP)
    1467           0 :             log_debug ("cmd_lookup: returning one cert%s\n",
    1468             :                        truncated? " (truncated)":"");
    1469             : 
    1470             :           /* Send the data, flush the buffer and then send an END line
    1471             :              as a certificate delimiter. */
    1472           0 :           err = assuan_send_data (ctx, value, valuelen);
    1473           0 :           if (!err)
    1474           0 :             err = assuan_send_data (ctx, NULL, 0);
    1475           0 :           if (!err)
    1476           0 :             err = assuan_write_line (ctx, "END");
    1477           0 :           if (err)
    1478             :             {
    1479           0 :               log_error (_("error sending data: %s\n"), gpg_strerror (err));
    1480           0 :               end_cert_fetch (fetch_context);
    1481           0 :               goto leave;
    1482             :             }
    1483             : 
    1484           0 :           if (++count >= opt.max_replies )
    1485             :             {
    1486           0 :               truncation_forced = 1;
    1487           0 :               log_info (_("max_replies %d exceeded\n"), opt.max_replies );
    1488             :             }
    1489           0 :           if (single)
    1490           0 :             break;
    1491             :         }
    1492             : 
    1493           0 :       end_cert_fetch (fetch_context);
    1494             :     }
    1495             : #endif /*USE_LDAP*/
    1496             : 
    1497             :  ready:
    1498           0 :   if (truncated || truncation_forced)
    1499             :     {
    1500             :       char str[50];
    1501             : 
    1502           0 :       sprintf (str, "%d", count);
    1503           0 :       assuan_write_status (ctx, "TRUNCATED", str);
    1504             :     }
    1505             : 
    1506           0 :   if (!err && !count && !local_count && any_no_data)
    1507           0 :     err = gpg_error (GPG_ERR_NO_DATA);
    1508             : 
    1509             :  leave:
    1510           0 :   free_strlist (list);
    1511           0 :   return err;
    1512             : }
    1513             : 
    1514             : 
    1515             : static const char hlp_lookup[] =
    1516             :   "LOOKUP [--url] [--single] [--cache-only] <pattern>\n"
    1517             :   "\n"
    1518             :   "Lookup certificates matching PATTERN. With --url the pattern is\n"
    1519             :   "expected to be one URL.\n"
    1520             :   "\n"
    1521             :   "If --url is not given:  To allow for multiple patterns (which are ORed)\n"
    1522             :   "quoting is required: Spaces are translated to \"+\" or \"%20\";\n"
    1523             :   "obviously this requires that the usual escape quoting rules are applied.\n"
    1524             :   "\n"
    1525             :   "If --url is given no special escaping is required because URLs are\n"
    1526             :   "already escaped this way.\n"
    1527             :   "\n"
    1528             :   "If --single is given the first and only the first match will be\n"
    1529             :   "returned.  If --cache-only is _not_ given, no local query will be\n"
    1530             :   "done.\n"
    1531             :   "\n"
    1532             :   "If --cache-only is given no external lookup is done so that only\n"
    1533             :   "certificates from the cache may get returned.";
    1534             : static gpg_error_t
    1535           0 : cmd_lookup (assuan_context_t ctx, char *line)
    1536             : {
    1537             :   gpg_error_t err;
    1538             :   int lookup_url, single, cache_only;
    1539             : 
    1540           0 :   lookup_url = has_leading_option (line, "--url");
    1541           0 :   single = has_leading_option (line, "--single");
    1542           0 :   cache_only = has_leading_option (line, "--cache-only");
    1543           0 :   line = skip_options (line);
    1544             : 
    1545           0 :   if (lookup_url && cache_only)
    1546           0 :     err = gpg_error (GPG_ERR_NOT_FOUND);
    1547           0 :   else if (lookup_url && single)
    1548           0 :     err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
    1549           0 :   else if (lookup_url)
    1550           0 :     err = lookup_cert_by_url (ctx, line);
    1551             :   else
    1552           0 :     err = lookup_cert_by_pattern (ctx, line, single, cache_only);
    1553             : 
    1554           0 :   return leave_cmd (ctx, err);
    1555             : }
    1556             : 
    1557             : 
    1558             : static const char hlp_loadcrl[] =
    1559             :   "LOADCRL [--url] <filename|url>\n"
    1560             :   "\n"
    1561             :   "Load the CRL in the file with name FILENAME into our cache.  Note\n"
    1562             :   "that FILENAME should be given with an absolute path because\n"
    1563             :   "Dirmngrs cwd is not known.  With --url the CRL is directly loaded\n"
    1564             :   "from the given URL.\n"
    1565             :   "\n"
    1566             :   "This command is usually used by gpgsm using the invocation \"gpgsm\n"
    1567             :   "--call-dirmngr loadcrl <filename>\".  A direct invocation of Dirmngr\n"
    1568             :   "is not useful because gpgsm might need to callback gpgsm to ask for\n"
    1569             :   "the CA's certificate.";
    1570             : static gpg_error_t
    1571           0 : cmd_loadcrl (assuan_context_t ctx, char *line)
    1572             : {
    1573           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    1574           0 :   gpg_error_t err = 0;
    1575           0 :   int use_url = has_leading_option (line, "--url");
    1576             : 
    1577           0 :   line = skip_options (line);
    1578             : 
    1579           0 :   if (use_url)
    1580             :     {
    1581             :       ksba_reader_t reader;
    1582             : 
    1583           0 :       err = crl_fetch (ctrl, line, &reader);
    1584           0 :       if (err)
    1585           0 :         log_error (_("fetching CRL from '%s' failed: %s\n"),
    1586             :                    line, gpg_strerror (err));
    1587             :       else
    1588             :         {
    1589           0 :           err = crl_cache_insert (ctrl, line, reader);
    1590           0 :           if (err)
    1591           0 :             log_error (_("processing CRL from '%s' failed: %s\n"),
    1592             :                        line, gpg_strerror (err));
    1593           0 :           crl_close_reader (reader);
    1594             :         }
    1595             :     }
    1596             :   else
    1597             :     {
    1598             :       char *buf;
    1599             : 
    1600           0 :       buf = xtrymalloc (strlen (line)+1);
    1601           0 :       if (!buf)
    1602           0 :         err = gpg_error_from_syserror ();
    1603             :       else
    1604             :         {
    1605           0 :           strcpy_escaped_plus (buf, line);
    1606           0 :           err = crl_cache_load (ctrl, buf);
    1607           0 :           xfree (buf);
    1608             :         }
    1609             :     }
    1610             : 
    1611           0 :   return leave_cmd (ctx, err);
    1612             : }
    1613             : 
    1614             : 
    1615             : static const char hlp_listcrls[] =
    1616             :   "LISTCRLS\n"
    1617             :   "\n"
    1618             :   "List the content of all CRLs in a readable format.  This command is\n"
    1619             :   "usually used by gpgsm using the invocation \"gpgsm --call-dirmngr\n"
    1620             :   "listcrls\".  It may also be used directly using \"dirmngr\n"
    1621             :   "--list-crls\".";
    1622             : static gpg_error_t
    1623           0 : cmd_listcrls (assuan_context_t ctx, char *line)
    1624             : {
    1625             :   gpg_error_t err;
    1626             :   estream_t fp;
    1627             : 
    1628             :   (void)line;
    1629             : 
    1630           0 :   fp = es_fopencookie (ctx, "w", data_line_cookie_functions);
    1631           0 :   if (!fp)
    1632           0 :     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
    1633             :   else
    1634             :     {
    1635           0 :       err = crl_cache_list (fp);
    1636           0 :       es_fclose (fp);
    1637             :     }
    1638           0 :   return leave_cmd (ctx, err);
    1639             : }
    1640             : 
    1641             : 
    1642             : static const char hlp_cachecert[] =
    1643             :   "CACHECERT\n"
    1644             :   "\n"
    1645             :   "Put a certificate into the internal cache.  This command might be\n"
    1646             :   "useful if a client knows in advance certificates required for a\n"
    1647             :   "test and wants to make sure they get added to the internal cache.\n"
    1648             :   "It is also helpful for debugging.  To get the actual certificate,\n"
    1649             :   "this command immediately inquires it using\n"
    1650             :   "\n"
    1651             :   "  INQUIRE TARGETCERT\n"
    1652             :   "\n"
    1653             :   "and the caller is expected to return the certificate for the\n"
    1654             :   "request as a binary blob.";
    1655             : static gpg_error_t
    1656           0 : cmd_cachecert (assuan_context_t ctx, char *line)
    1657             : {
    1658           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    1659             :   gpg_error_t err;
    1660           0 :   ksba_cert_t cert = NULL;
    1661           0 :   unsigned char *value = NULL;
    1662             :   size_t valuelen;
    1663             : 
    1664             :   (void)line;
    1665             : 
    1666           0 :   err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
    1667             :                        &value, &valuelen, MAX_CERT_LENGTH);
    1668           0 :   if (err)
    1669             :     {
    1670           0 :       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
    1671           0 :       goto leave;
    1672             :     }
    1673             : 
    1674           0 :   if (!valuelen) /* No data returned; return a comprehensible error. */
    1675           0 :     err = gpg_error (GPG_ERR_MISSING_CERT);
    1676             :   else
    1677             :     {
    1678           0 :       err = ksba_cert_new (&cert);
    1679           0 :       if (!err)
    1680           0 :         err = ksba_cert_init_from_mem (cert, value, valuelen);
    1681             :     }
    1682           0 :   xfree (value);
    1683           0 :   if(err)
    1684           0 :     goto leave;
    1685             : 
    1686           0 :   err = cache_cert (cert);
    1687             : 
    1688             :  leave:
    1689           0 :   ksba_cert_release (cert);
    1690           0 :   return leave_cmd (ctx, err);
    1691             : }
    1692             : 
    1693             : 
    1694             : static const char hlp_validate[] =
    1695             :   "VALIDATE\n"
    1696             :   "\n"
    1697             :   "Validate a certificate using the certificate validation function\n"
    1698             :   "used internally by dirmngr.  This command is only useful for\n"
    1699             :   "debugging.  To get the actual certificate, this command immediately\n"
    1700             :   "inquires it using\n"
    1701             :   "\n"
    1702             :   "  INQUIRE TARGETCERT\n"
    1703             :   "\n"
    1704             :   "and the caller is expected to return the certificate for the\n"
    1705             :   "request as a binary blob.";
    1706             : static gpg_error_t
    1707           0 : cmd_validate (assuan_context_t ctx, char *line)
    1708             : {
    1709           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    1710             :   gpg_error_t err;
    1711           0 :   ksba_cert_t cert = NULL;
    1712           0 :   unsigned char *value = NULL;
    1713             :   size_t valuelen;
    1714             : 
    1715             :   (void)line;
    1716             : 
    1717           0 :   err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
    1718             :                        &value, &valuelen, MAX_CERT_LENGTH);
    1719           0 :   if (err)
    1720             :     {
    1721           0 :       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
    1722           0 :       goto leave;
    1723             :     }
    1724             : 
    1725           0 :   if (!valuelen) /* No data returned; return a comprehensible error. */
    1726           0 :     err = gpg_error (GPG_ERR_MISSING_CERT);
    1727             :   else
    1728             :     {
    1729           0 :       err = ksba_cert_new (&cert);
    1730           0 :       if (!err)
    1731           0 :         err = ksba_cert_init_from_mem (cert, value, valuelen);
    1732             :     }
    1733           0 :   xfree (value);
    1734           0 :   if(err)
    1735           0 :     goto leave;
    1736             : 
    1737             :   /* If we have this certificate already in our cache, use the cached
    1738             :      version for validation because this will take care of any cached
    1739             :      results. */
    1740             :   {
    1741             :     unsigned char fpr[20];
    1742             :     ksba_cert_t tmpcert;
    1743             : 
    1744           0 :     cert_compute_fpr (cert, fpr);
    1745           0 :     tmpcert = get_cert_byfpr (fpr);
    1746           0 :     if (tmpcert)
    1747             :       {
    1748           0 :         ksba_cert_release (cert);
    1749           0 :         cert = tmpcert;
    1750             :       }
    1751             :   }
    1752             : 
    1753           0 :   err = validate_cert_chain (ctrl, cert, NULL, VALIDATE_MODE_CERT, NULL);
    1754             : 
    1755             :  leave:
    1756           0 :   ksba_cert_release (cert);
    1757           0 :   return leave_cmd (ctx, err);
    1758             : }
    1759             : 
    1760             : 
    1761             : 
    1762             : /* Parse an keyserver URI and store it in a new uri item which is
    1763             :    returned at R_ITEM.  On error return an error code.  */
    1764             : static gpg_error_t
    1765           0 : make_keyserver_item (const char *uri, uri_item_t *r_item)
    1766             : {
    1767             :   gpg_error_t err;
    1768             :   uri_item_t item;
    1769             : 
    1770           0 :   *r_item = NULL;
    1771           0 :   item = xtrymalloc (sizeof *item + strlen (uri));
    1772           0 :   if (!item)
    1773           0 :     return gpg_error_from_syserror ();
    1774             : 
    1775           0 :   item->next = NULL;
    1776           0 :   item->parsed_uri = NULL;
    1777           0 :   strcpy (item->uri, uri);
    1778             : 
    1779             : #if USE_LDAP
    1780           0 :   if (ldap_uri_p (item->uri))
    1781           0 :     err = ldap_parse_uri (&item->parsed_uri, uri);
    1782             :   else
    1783             : #endif
    1784             :     {
    1785           0 :       err = http_parse_uri (&item->parsed_uri, uri, 1);
    1786             :     }
    1787             : 
    1788           0 :   if (err)
    1789           0 :     xfree (item);
    1790             :   else
    1791           0 :     *r_item = item;
    1792           0 :   return err;
    1793             : }
    1794             : 
    1795             : 
    1796             : /* If no keyserver is stored in CTRL but a global keyserver has been
    1797             :    set, put that global keyserver into CTRL.  We need use this
    1798             :    function to help migrate from the old gpg based keyserver
    1799             :    configuration to the new dirmngr based configuration.  */
    1800             : static gpg_error_t
    1801           0 : ensure_keyserver (ctrl_t ctrl)
    1802             : {
    1803             :   gpg_error_t err;
    1804             :   uri_item_t item;
    1805           0 :   uri_item_t onion_items = NULL;
    1806           0 :   uri_item_t plain_items = NULL;
    1807             :   uri_item_t ui;
    1808             :   strlist_t sl;
    1809             : 
    1810           0 :   if (ctrl->server_local->keyservers)
    1811           0 :     return 0; /* Already set for this session.  */
    1812           0 :   if (!opt.keyserver)
    1813           0 :     return 0; /* No global option set.  */
    1814             : 
    1815           0 :   for (sl = opt.keyserver; sl; sl = sl->next)
    1816             :     {
    1817           0 :       err = make_keyserver_item (sl->d, &item);
    1818           0 :       if (err)
    1819           0 :         goto leave;
    1820           0 :       if (item->parsed_uri->onion)
    1821             :         {
    1822           0 :           item->next = onion_items;
    1823           0 :           onion_items = item;
    1824             :         }
    1825             :       else
    1826             :         {
    1827           0 :           item->next = plain_items;
    1828           0 :           plain_items = item;
    1829             :         }
    1830             :     }
    1831             : 
    1832             :   /* Decide which to use.  Note that the sesssion has no keyservers
    1833             :      yet set. */
    1834           0 :   if (onion_items && !onion_items->next && plain_items && !plain_items->next)
    1835             :     {
    1836             :       /* If there is just one onion and one plain keyserver given, we take
    1837             :          only one depending on whether Tor is running or not.  */
    1838           0 :       if (is_tor_running (ctrl))
    1839             :         {
    1840           0 :           ctrl->server_local->keyservers = onion_items;
    1841           0 :           onion_items = NULL;
    1842             :         }
    1843             :       else
    1844             :         {
    1845           0 :           ctrl->server_local->keyservers = plain_items;
    1846           0 :           plain_items = NULL;
    1847             :         }
    1848             :     }
    1849           0 :   else if (!is_tor_running (ctrl))
    1850             :     {
    1851             :       /* Tor is not running.  It does not make sense to add Onion
    1852             :          addresses.  */
    1853           0 :       ctrl->server_local->keyservers = plain_items;
    1854           0 :       plain_items = NULL;
    1855             :     }
    1856             :   else
    1857             :     {
    1858             :       /* In all other cases add all keyservers.  */
    1859           0 :       ctrl->server_local->keyservers = onion_items;
    1860           0 :       onion_items = NULL;
    1861           0 :       for (ui = ctrl->server_local->keyservers; ui && ui->next; ui = ui->next)
    1862             :         ;
    1863           0 :       if (ui)
    1864           0 :         ui->next = plain_items;
    1865             :       else
    1866           0 :         ctrl->server_local->keyservers = plain_items;
    1867           0 :       plain_items = NULL;
    1868             :     }
    1869             : 
    1870             :  leave:
    1871           0 :   release_uri_item_list (onion_items);
    1872           0 :   release_uri_item_list (plain_items);
    1873             : 
    1874           0 :   return err;
    1875             : }
    1876             : 
    1877             : 
    1878             : static const char hlp_keyserver[] =
    1879             :   "KEYSERVER [<options>] [<uri>|<host>]\n"
    1880             :   "Options are:\n"
    1881             :   "  --help\n"
    1882             :   "  --clear      Remove all configured keyservers\n"
    1883             :   "  --resolve    Resolve HKP host names and rotate\n"
    1884             :   "  --hosttable  Print table of known hosts and pools\n"
    1885             :   "  --dead       Mark <host> as dead\n"
    1886             :   "  --alive      Mark <host> as alive\n"
    1887             :   "\n"
    1888             :   "If called without arguments list all configured keyserver URLs.\n"
    1889             :   "If called with an URI add this as keyserver.  Note that keyservers\n"
    1890             :   "are configured on a per-session base.  A default keyserver may already be\n"
    1891             :   "present, thus the \"--clear\" option must be used to get full control.\n"
    1892             :   "If \"--clear\" and an URI are used together the clear command is\n"
    1893             :   "obviously executed first.  A RESET command does not change the list\n"
    1894             :   "of configured keyservers.";
    1895             : static gpg_error_t
    1896           0 : cmd_keyserver (assuan_context_t ctx, char *line)
    1897             : {
    1898           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    1899           0 :   gpg_error_t err = 0;
    1900             :   int clear_flag, add_flag, help_flag, host_flag, resolve_flag;
    1901             :   int dead_flag, alive_flag;
    1902           0 :   uri_item_t item = NULL; /* gcc 4.4.5 is not able to detect that it
    1903             :                              is always initialized.  */
    1904             : 
    1905           0 :   clear_flag = has_option (line, "--clear");
    1906           0 :   help_flag = has_option (line, "--help");
    1907           0 :   resolve_flag = has_option (line, "--resolve");
    1908           0 :   host_flag = has_option (line, "--hosttable");
    1909           0 :   dead_flag = has_option (line, "--dead");
    1910           0 :   alive_flag = has_option (line, "--alive");
    1911           0 :   line = skip_options (line);
    1912           0 :   add_flag = !!*line;
    1913             : 
    1914           0 :   if (help_flag)
    1915             :     {
    1916           0 :       err = ks_action_help (ctrl, line);
    1917           0 :       goto leave;
    1918             :     }
    1919             : 
    1920           0 :   if (resolve_flag)
    1921             :     {
    1922           0 :       err = ensure_keyserver (ctrl);
    1923           0 :       if (!err)
    1924           0 :         err = ks_action_resolve (ctrl, ctrl->server_local->keyservers);
    1925           0 :       if (err)
    1926           0 :         goto leave;
    1927             :     }
    1928             : 
    1929           0 :   if (alive_flag && dead_flag)
    1930             :     {
    1931           0 :       err = set_error (GPG_ERR_ASS_PARAMETER, "no support for zombies");
    1932           0 :       goto leave;
    1933             :     }
    1934           0 :   if (dead_flag)
    1935             :     {
    1936           0 :       err = check_owner_permission (ctx, "no permission to use --dead");
    1937           0 :       if (err)
    1938           0 :         goto leave;
    1939             :     }
    1940           0 :   if (alive_flag || dead_flag)
    1941             :     {
    1942           0 :       if (!*line)
    1943             :         {
    1944           0 :           err = set_error (GPG_ERR_ASS_PARAMETER, "name of host missing");
    1945           0 :           goto leave;
    1946             :         }
    1947             : 
    1948           0 :       err = ks_hkp_mark_host (ctrl, line, alive_flag);
    1949           0 :       if (err)
    1950           0 :         goto leave;
    1951             :     }
    1952             : 
    1953           0 :   if (host_flag)
    1954             :     {
    1955           0 :       err = ks_hkp_print_hosttable (ctrl);
    1956           0 :       if (err)
    1957           0 :         goto leave;
    1958             :     }
    1959           0 :   if (resolve_flag || host_flag || alive_flag || dead_flag)
    1960             :     goto leave;
    1961             : 
    1962           0 :   if (add_flag)
    1963             :     {
    1964           0 :       err = make_keyserver_item (line, &item);
    1965           0 :       if (err)
    1966           0 :         goto leave;
    1967             :     }
    1968           0 :   if (clear_flag)
    1969           0 :     release_ctrl_keyservers (ctrl);
    1970           0 :   if (add_flag)
    1971             :     {
    1972           0 :       item->next = ctrl->server_local->keyservers;
    1973           0 :       ctrl->server_local->keyservers = item;
    1974             :     }
    1975             : 
    1976           0 :   if (!add_flag && !clear_flag && !help_flag)
    1977             :     {
    1978             :       /* List configured keyservers.  However, we first add a global
    1979             :          keyserver. */
    1980             :       uri_item_t u;
    1981             : 
    1982           0 :       err = ensure_keyserver (ctrl);
    1983           0 :       if (err)
    1984             :         {
    1985           0 :           assuan_set_error (ctx, err,
    1986             :                             "Bad keyserver configuration in dirmngr.conf");
    1987           0 :           goto leave;
    1988             :         }
    1989             : 
    1990           0 :       for (u=ctrl->server_local->keyservers; u; u = u->next)
    1991           0 :         dirmngr_status (ctrl, "KEYSERVER", u->uri, NULL);
    1992             :     }
    1993           0 :   err = 0;
    1994             : 
    1995             :  leave:
    1996           0 :   return leave_cmd (ctx, err);
    1997             : }
    1998             : 
    1999             : 
    2000             : 
    2001             : static const char hlp_ks_search[] =
    2002             :   "KS_SEARCH {<pattern>}\n"
    2003             :   "\n"
    2004             :   "Search the configured OpenPGP keyservers (see command KEYSERVER)\n"
    2005             :   "for keys matching PATTERN";
    2006             : static gpg_error_t
    2007           0 : cmd_ks_search (assuan_context_t ctx, char *line)
    2008             : {
    2009           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    2010             :   gpg_error_t err;
    2011             :   strlist_t list, sl;
    2012             :   char *p;
    2013             :   estream_t outfp;
    2014             : 
    2015             :   /* No options for now.  */
    2016           0 :   line = skip_options (line);
    2017             : 
    2018             :   /* Break the line down into an strlist.  Each pattern is
    2019             :      percent-plus escaped. */
    2020           0 :   list = NULL;
    2021           0 :   for (p=line; *p; line = p)
    2022             :     {
    2023           0 :       while (*p && *p != ' ')
    2024           0 :         p++;
    2025           0 :       if (*p)
    2026           0 :         *p++ = 0;
    2027           0 :       if (*line)
    2028             :         {
    2029           0 :           sl = xtrymalloc (sizeof *sl + strlen (line));
    2030           0 :           if (!sl)
    2031             :             {
    2032           0 :               err = gpg_error_from_syserror ();
    2033           0 :               goto leave;
    2034             :             }
    2035           0 :           sl->flags = 0;
    2036           0 :           strcpy_escaped_plus (sl->d, line);
    2037           0 :           sl->next = list;
    2038           0 :           list = sl;
    2039             :         }
    2040             :     }
    2041             : 
    2042           0 :   err = ensure_keyserver (ctrl);
    2043           0 :   if (err)
    2044           0 :     goto leave;
    2045             : 
    2046             :   /* Setup an output stream and perform the search.  */
    2047           0 :   outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
    2048           0 :   if (!outfp)
    2049           0 :     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
    2050             :   else
    2051             :     {
    2052           0 :       err = ks_action_search (ctrl, ctrl->server_local->keyservers,
    2053             :                               list, outfp);
    2054           0 :       es_fclose (outfp);
    2055             :     }
    2056             : 
    2057             :  leave:
    2058           0 :   free_strlist (list);
    2059           0 :   return leave_cmd (ctx, err);
    2060             : }
    2061             : 
    2062             : 
    2063             : 
    2064             : static const char hlp_ks_get[] =
    2065             :   "KS_GET {<pattern>}\n"
    2066             :   "\n"
    2067             :   "Get the keys matching PATTERN from the configured OpenPGP keyservers\n"
    2068             :   "(see command KEYSERVER).  Each pattern should be a keyid, a fingerprint,\n"
    2069             :   "or an exact name indicated by the '=' prefix.";
    2070             : static gpg_error_t
    2071           0 : cmd_ks_get (assuan_context_t ctx, char *line)
    2072             : {
    2073           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    2074             :   gpg_error_t err;
    2075             :   strlist_t list, sl;
    2076             :   char *p;
    2077             :   estream_t outfp;
    2078             : 
    2079             :   /* No options for now.  */
    2080           0 :   line = skip_options (line);
    2081             : 
    2082             :   /* Break the line into a strlist.  Each pattern is by
    2083             :      definition percent-plus escaped.  However we only support keyids
    2084             :      and fingerprints and thus the client has no need to apply the
    2085             :      escaping.  */
    2086           0 :   list = NULL;
    2087           0 :   for (p=line; *p; line = p)
    2088             :     {
    2089           0 :       while (*p && *p != ' ')
    2090           0 :         p++;
    2091           0 :       if (*p)
    2092           0 :         *p++ = 0;
    2093           0 :       if (*line)
    2094             :         {
    2095           0 :           sl = xtrymalloc (sizeof *sl + strlen (line));
    2096           0 :           if (!sl)
    2097             :             {
    2098           0 :               err = gpg_error_from_syserror ();
    2099           0 :               goto leave;
    2100             :             }
    2101           0 :           sl->flags = 0;
    2102           0 :           strcpy_escaped_plus (sl->d, line);
    2103           0 :           sl->next = list;
    2104           0 :           list = sl;
    2105             :         }
    2106             :     }
    2107             : 
    2108           0 :   err = ensure_keyserver (ctrl);
    2109           0 :   if (err)
    2110           0 :     goto leave;
    2111             : 
    2112             :   /* Setup an output stream and perform the get.  */
    2113           0 :   outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
    2114           0 :   if (!outfp)
    2115           0 :     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
    2116             :   else
    2117             :     {
    2118           0 :       ctrl->server_local->inhibit_data_logging = 1;
    2119           0 :       ctrl->server_local->inhibit_data_logging_now = 0;
    2120           0 :       ctrl->server_local->inhibit_data_logging_count = 0;
    2121           0 :       err = ks_action_get (ctrl, ctrl->server_local->keyservers, list, outfp);
    2122           0 :       es_fclose (outfp);
    2123           0 :       ctrl->server_local->inhibit_data_logging = 0;
    2124             :     }
    2125             : 
    2126             :  leave:
    2127           0 :   free_strlist (list);
    2128           0 :   return leave_cmd (ctx, err);
    2129             : }
    2130             : 
    2131             : 
    2132             : static const char hlp_ks_fetch[] =
    2133             :   "KS_FETCH <URL>\n"
    2134             :   "\n"
    2135             :   "Get the key(s) from URL.";
    2136             : static gpg_error_t
    2137           0 : cmd_ks_fetch (assuan_context_t ctx, char *line)
    2138             : {
    2139           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    2140             :   gpg_error_t err;
    2141             :   estream_t outfp;
    2142             : 
    2143             :   /* No options for now.  */
    2144           0 :   line = skip_options (line);
    2145             : 
    2146           0 :   err = ensure_keyserver (ctrl);  /* FIXME: Why do we needs this here?  */
    2147           0 :   if (err)
    2148           0 :     goto leave;
    2149             : 
    2150             :   /* Setup an output stream and perform the get.  */
    2151           0 :   outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
    2152           0 :   if (!outfp)
    2153           0 :     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
    2154             :   else
    2155             :     {
    2156           0 :       ctrl->server_local->inhibit_data_logging = 1;
    2157           0 :       ctrl->server_local->inhibit_data_logging_now = 0;
    2158           0 :       ctrl->server_local->inhibit_data_logging_count = 0;
    2159           0 :       err = ks_action_fetch (ctrl, line, outfp);
    2160           0 :       es_fclose (outfp);
    2161           0 :       ctrl->server_local->inhibit_data_logging = 0;
    2162             :     }
    2163             : 
    2164             :  leave:
    2165           0 :   return leave_cmd (ctx, err);
    2166             : }
    2167             : 
    2168             : 
    2169             : 
    2170             : static const char hlp_ks_put[] =
    2171             :   "KS_PUT\n"
    2172             :   "\n"
    2173             :   "Send a key to the configured OpenPGP keyservers.  The actual key material\n"
    2174             :   "is then requested by Dirmngr using\n"
    2175             :   "\n"
    2176             :   "  INQUIRE KEYBLOCK\n"
    2177             :   "\n"
    2178             :   "The client shall respond with a binary version of the keyblock (e.g.,\n"
    2179             :   "the output of `gpg --export KEYID').  For LDAP\n"
    2180             :   "keyservers Dirmngr may ask for meta information of the provided keyblock\n"
    2181             :   "using:\n"
    2182             :   "\n"
    2183             :   "  INQUIRE KEYBLOCK_INFO\n"
    2184             :   "\n"
    2185             :   "The client shall respond with a colon delimited info lines (the output\n"
    2186             :   "of 'for x in keys sigs; do gpg --list-$x --with-colons KEYID; done').\n";
    2187             : static gpg_error_t
    2188           0 : cmd_ks_put (assuan_context_t ctx, char *line)
    2189             : {
    2190           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    2191             :   gpg_error_t err;
    2192           0 :   unsigned char *value = NULL;
    2193             :   size_t valuelen;
    2194           0 :   unsigned char *info = NULL;
    2195             :   size_t infolen;
    2196             : 
    2197             :   /* No options for now.  */
    2198           0 :   line = skip_options (line);
    2199             : 
    2200           0 :   err = ensure_keyserver (ctrl);
    2201           0 :   if (err)
    2202           0 :     goto leave;
    2203             : 
    2204             :   /* Ask for the key material.  */
    2205           0 :   err = assuan_inquire (ctx, "KEYBLOCK",
    2206             :                         &value, &valuelen, MAX_KEYBLOCK_LENGTH);
    2207           0 :   if (err)
    2208             :     {
    2209           0 :       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
    2210           0 :       goto leave;
    2211             :     }
    2212             : 
    2213           0 :   if (!valuelen) /* No data returned; return a comprehensible error. */
    2214             :     {
    2215           0 :       err = gpg_error (GPG_ERR_MISSING_CERT);
    2216           0 :       goto leave;
    2217             :     }
    2218             : 
    2219             :   /* Ask for the key meta data. Not actually needed for HKP servers
    2220             :      but we do it anyway to test the client implementaion.  */
    2221           0 :   err = assuan_inquire (ctx, "KEYBLOCK_INFO",
    2222             :                         &info, &infolen, MAX_KEYBLOCK_LENGTH);
    2223           0 :   if (err)
    2224             :     {
    2225           0 :       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
    2226           0 :       goto leave;
    2227             :     }
    2228             : 
    2229             :   /* Send the key.  */
    2230           0 :   err = ks_action_put (ctrl, ctrl->server_local->keyservers,
    2231             :                        value, valuelen, info, infolen);
    2232             : 
    2233             :  leave:
    2234           0 :   xfree (info);
    2235           0 :   xfree (value);
    2236           0 :   return leave_cmd (ctx, err);
    2237             : }
    2238             : 
    2239             : 
    2240             : 
    2241             : 
    2242             : static const char hlp_getinfo[] =
    2243             :   "GETINFO <what>\n"
    2244             :   "\n"
    2245             :   "Multi purpose command to return certain information.  \n"
    2246             :   "Supported values of WHAT are:\n"
    2247             :   "\n"
    2248             :   "version     - Return the version of the program.\n"
    2249             :   "pid         - Return the process id of the server.\n"
    2250             :   "tor         - Return OK if running in Tor mode\n"
    2251             :   "dnsinfo     - Return info about the DNS resolver\n"
    2252             :   "socket_name - Return the name of the socket.\n";
    2253             : static gpg_error_t
    2254           0 : cmd_getinfo (assuan_context_t ctx, char *line)
    2255             : {
    2256           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    2257             :   gpg_error_t err;
    2258             : 
    2259           0 :   if (!strcmp (line, "version"))
    2260             :     {
    2261           0 :       const char *s = VERSION;
    2262           0 :       err = assuan_send_data (ctx, s, strlen (s));
    2263             :     }
    2264           0 :   else if (!strcmp (line, "pid"))
    2265             :     {
    2266             :       char numbuf[50];
    2267             : 
    2268           0 :       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
    2269           0 :       err = assuan_send_data (ctx, numbuf, strlen (numbuf));
    2270             :     }
    2271           0 :   else if (!strcmp (line, "socket_name"))
    2272             :     {
    2273           0 :       const char *s = dirmngr_socket_name ();
    2274           0 :       err = assuan_send_data (ctx, s, strlen (s));
    2275             :     }
    2276           0 :   else if (!strcmp (line, "tor"))
    2277             :     {
    2278           0 :       if (opt.use_tor)
    2279             :         {
    2280           0 :           if (!is_tor_running (ctrl))
    2281           0 :             err = assuan_write_status (ctx, "NO_TOR", "Tor not running");
    2282             :           else
    2283           0 :             err = 0;
    2284           0 :           if (!err)
    2285           0 :             assuan_set_okay_line (ctx, "- Tor mode is enabled");
    2286             :         }
    2287             :       else
    2288           0 :         err = set_error (GPG_ERR_FALSE, "Tor mode is NOT enabled");
    2289             :     }
    2290           0 :   else if (!strcmp (line, "dnsinfo"))
    2291             :     {
    2292             : #if USE_ADNS && HAVE_ADNS_IF_TORMODE
    2293             :       assuan_set_okay_line (ctx, "- ADNS with Tor support");
    2294             : #elif USE_ADNS
    2295             :       assuan_set_okay_line (ctx, "- ADNS w/o Tor support");
    2296             : #else
    2297           0 :       assuan_set_okay_line (ctx, "- System resolver w/o Tor support");
    2298             : #endif
    2299           0 :       err = 0;
    2300             :     }
    2301             :   else
    2302           0 :     err = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
    2303             : 
    2304           0 :   return leave_cmd (ctx, err);
    2305             : }
    2306             : 
    2307             : 
    2308             : 
    2309             : static const char hlp_killdirmngr[] =
    2310             :   "KILLDIRMNGR\n"
    2311             :   "\n"
    2312             :   "This command allows a user - given sufficient permissions -\n"
    2313             :   "to kill this dirmngr process.\n";
    2314             : static gpg_error_t
    2315           0 : cmd_killdirmngr (assuan_context_t ctx, char *line)
    2316             : {
    2317           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    2318             : 
    2319             :   (void)line;
    2320             : 
    2321           0 :   ctrl->server_local->stopme = 1;
    2322           0 :   assuan_set_flag (ctx, ASSUAN_FORCE_CLOSE, 1);
    2323           0 :   return gpg_error (GPG_ERR_EOF);
    2324             : }
    2325             : 
    2326             : 
    2327             : static const char hlp_reloaddirmngr[] =
    2328             :   "RELOADDIRMNGR\n"
    2329             :   "\n"
    2330             :   "This command is an alternative to SIGHUP\n"
    2331             :   "to reload the configuration.";
    2332             : static gpg_error_t
    2333           0 : cmd_reloaddirmngr (assuan_context_t ctx, char *line)
    2334             : {
    2335             :   (void)ctx;
    2336             :   (void)line;
    2337             : 
    2338           0 :   dirmngr_sighup_action ();
    2339           0 :   return 0;
    2340             : }
    2341             : 
    2342             : 
    2343             : 
    2344             : 
    2345             : /* Tell the assuan library about our commands. */
    2346             : static int
    2347           0 : register_commands (assuan_context_t ctx)
    2348             : {
    2349             :   static struct {
    2350             :     const char *name;
    2351             :     assuan_handler_t handler;
    2352             :     const char * const help;
    2353             :   } table[] = {
    2354             :     { "DNS_CERT",   cmd_dns_cert,   hlp_dns_cert },
    2355             :     { "WKD_GET",    cmd_wkd_get,    hlp_wkd_get },
    2356             :     { "LDAPSERVER", cmd_ldapserver, hlp_ldapserver },
    2357             :     { "ISVALID",    cmd_isvalid,    hlp_isvalid },
    2358             :     { "CHECKCRL",   cmd_checkcrl,   hlp_checkcrl },
    2359             :     { "CHECKOCSP",  cmd_checkocsp,  hlp_checkocsp },
    2360             :     { "LOOKUP",     cmd_lookup,     hlp_lookup },
    2361             :     { "LOADCRL",    cmd_loadcrl,    hlp_loadcrl },
    2362             :     { "LISTCRLS",   cmd_listcrls,   hlp_listcrls },
    2363             :     { "CACHECERT",  cmd_cachecert,  hlp_cachecert },
    2364             :     { "VALIDATE",   cmd_validate,   hlp_validate },
    2365             :     { "KEYSERVER",  cmd_keyserver,  hlp_keyserver },
    2366             :     { "KS_SEARCH",  cmd_ks_search,  hlp_ks_search },
    2367             :     { "KS_GET",     cmd_ks_get,     hlp_ks_get },
    2368             :     { "KS_FETCH",   cmd_ks_fetch,   hlp_ks_fetch },
    2369             :     { "KS_PUT",     cmd_ks_put,     hlp_ks_put },
    2370             :     { "GETINFO",    cmd_getinfo,    hlp_getinfo },
    2371             :     { "KILLDIRMNGR",cmd_killdirmngr,hlp_killdirmngr },
    2372             :     { "RELOADDIRMNGR",cmd_reloaddirmngr,hlp_reloaddirmngr },
    2373             :     { NULL, NULL }
    2374             :   };
    2375             :   int i, j, rc;
    2376             : 
    2377           0 :   for (i=j=0; table[i].name; i++)
    2378             :     {
    2379           0 :       rc = assuan_register_command (ctx, table[i].name, table[i].handler,
    2380             :                                     table[i].help);
    2381           0 :       if (rc)
    2382           0 :         return rc;
    2383             :     }
    2384           0 :   return 0;
    2385             : }
    2386             : 
    2387             : 
    2388             : /* Note that we do not reset the list of configured keyservers.  */
    2389             : static gpg_error_t
    2390           0 : reset_notify (assuan_context_t ctx, char *line)
    2391             : {
    2392           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    2393             :   (void)line;
    2394             : 
    2395             : #if USE_LDAP
    2396           0 :   ldapserver_list_free (ctrl->server_local->ldapservers);
    2397             : #endif /*USE_LDAP*/
    2398           0 :   ctrl->server_local->ldapservers = NULL;
    2399           0 :   return 0;
    2400             : }
    2401             : 
    2402             : 
    2403             : /* This function is called by our assuan log handler to test whether a
    2404             :  * log message shall really be printed.  The function must return
    2405             :  * false to inhibit the logging of MSG.  CAT gives the requested log
    2406             :  * category.  MSG might be NULL. */
    2407             : int
    2408           0 : dirmngr_assuan_log_monitor (assuan_context_t ctx, unsigned int cat,
    2409             :                             const char *msg)
    2410             : {
    2411           0 :   ctrl_t ctrl = assuan_get_pointer (ctx);
    2412             : 
    2413             :   (void)cat;
    2414             :   (void)msg;
    2415             : 
    2416           0 :   if (!ctrl || !ctrl->server_local)
    2417           0 :     return 1; /* Can't decide - allow logging.  */
    2418             : 
    2419           0 :   if (!ctrl->server_local->inhibit_data_logging)
    2420           0 :     return 1; /* Not requested - allow logging.  */
    2421             : 
    2422             :   /* Disallow logging if *_now is true.  */
    2423           0 :   return !ctrl->server_local->inhibit_data_logging_now;
    2424             : }
    2425             : 
    2426             : 
    2427             : /* Startup the server and run the main command loop.  With FD = -1,
    2428             :    use stdin/stdout. */
    2429             : void
    2430           0 : start_command_handler (assuan_fd_t fd)
    2431             : {
    2432             :   static const char hello[] = "Dirmngr " VERSION " at your service";
    2433             :   static char *hello_line;
    2434             :   int rc;
    2435             :   assuan_context_t ctx;
    2436             :   ctrl_t ctrl;
    2437             : 
    2438           0 :   ctrl = xtrycalloc (1, sizeof *ctrl);
    2439           0 :   if (ctrl)
    2440           0 :     ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
    2441           0 :   if (!ctrl || !ctrl->server_local)
    2442             :     {
    2443           0 :       log_error (_("can't allocate control structure: %s\n"),
    2444           0 :                  strerror (errno));
    2445           0 :       xfree (ctrl);
    2446           0 :       return;
    2447             :     }
    2448             : 
    2449           0 :   dirmngr_init_default_ctrl (ctrl);
    2450             : 
    2451           0 :   rc = assuan_new (&ctx);
    2452           0 :   if (rc)
    2453             :     {
    2454           0 :       log_error (_("failed to allocate assuan context: %s\n"),
    2455             :                  gpg_strerror (rc));
    2456           0 :       dirmngr_exit (2);
    2457             :     }
    2458             : 
    2459           0 :   if (fd == ASSUAN_INVALID_FD)
    2460             :     {
    2461             :       assuan_fd_t filedes[2];
    2462             : 
    2463           0 :       filedes[0] = assuan_fdopen (0);
    2464           0 :       filedes[1] = assuan_fdopen (1);
    2465           0 :       rc = assuan_init_pipe_server (ctx, filedes);
    2466             :     }
    2467             :   else
    2468             :     {
    2469           0 :       rc = assuan_init_socket_server (ctx, fd, ASSUAN_SOCKET_SERVER_ACCEPTED);
    2470             :     }
    2471             : 
    2472           0 :   if (rc)
    2473             :     {
    2474           0 :       assuan_release (ctx);
    2475           0 :       log_error (_("failed to initialize the server: %s\n"),
    2476             :                  gpg_strerror(rc));
    2477           0 :       dirmngr_exit (2);
    2478             :     }
    2479             : 
    2480           0 :   rc = register_commands (ctx);
    2481           0 :   if (rc)
    2482             :     {
    2483           0 :       log_error (_("failed to the register commands with Assuan: %s\n"),
    2484             :                  gpg_strerror(rc));
    2485           0 :       dirmngr_exit (2);
    2486             :     }
    2487             : 
    2488             : 
    2489           0 :   if (!hello_line)
    2490             :     {
    2491           0 :       hello_line = xtryasprintf
    2492             :         ("Home: %s\n"
    2493             :          "Config: %s\n"
    2494             :          "%s",
    2495             :          gnupg_homedir (),
    2496           0 :          opt.config_filename? opt.config_filename : "[none]",
    2497             :          hello);
    2498             :     }
    2499             : 
    2500           0 :   ctrl->server_local->assuan_ctx = ctx;
    2501           0 :   assuan_set_pointer (ctx, ctrl);
    2502             : 
    2503           0 :   assuan_set_hello_line (ctx, hello_line);
    2504           0 :   assuan_register_option_handler (ctx, option_handler);
    2505           0 :   assuan_register_reset_notify (ctx, reset_notify);
    2506             : 
    2507             :   for (;;)
    2508             :     {
    2509           0 :       rc = assuan_accept (ctx);
    2510           0 :       if (rc == -1)
    2511           0 :         break;
    2512           0 :       if (rc)
    2513             :         {
    2514           0 :           log_info (_("Assuan accept problem: %s\n"), gpg_strerror (rc));
    2515           0 :           break;
    2516             :         }
    2517             : 
    2518             : #ifndef HAVE_W32_SYSTEM
    2519           0 :       if (opt.verbose)
    2520             :         {
    2521             :           assuan_peercred_t peercred;
    2522             : 
    2523           0 :           if (!assuan_get_peercred (ctx, &peercred))
    2524           0 :             log_info ("connection from process %ld (%ld:%ld)\n",
    2525           0 :                       (long)peercred->pid, (long)peercred->uid,
    2526           0 :                       (long)peercred->gid);
    2527             :         }
    2528             : #endif
    2529             : 
    2530           0 :       rc = assuan_process (ctx);
    2531           0 :       if (rc)
    2532             :         {
    2533           0 :           log_info (_("Assuan processing failed: %s\n"), gpg_strerror (rc));
    2534           0 :           continue;
    2535             :         }
    2536           0 :     }
    2537             : 
    2538             : 
    2539             : #if USE_LDAP
    2540           0 :   ldap_wrapper_connection_cleanup (ctrl);
    2541             : 
    2542           0 :   ldapserver_list_free (ctrl->server_local->ldapservers);
    2543             : #endif /*USE_LDAP*/
    2544           0 :   ctrl->server_local->ldapservers = NULL;
    2545             : 
    2546           0 :   release_ctrl_keyservers (ctrl);
    2547             : 
    2548           0 :   ctrl->server_local->assuan_ctx = NULL;
    2549           0 :   assuan_release (ctx);
    2550             : 
    2551           0 :   if (ctrl->server_local->stopme)
    2552           0 :     dirmngr_exit (0);
    2553             : 
    2554           0 :   if (ctrl->refcount)
    2555           0 :     log_error ("oops: connection control structure still referenced (%d)\n",
    2556             :                ctrl->refcount);
    2557             :   else
    2558             :     {
    2559           0 :       release_ctrl_ocsp_certs (ctrl);
    2560           0 :       xfree (ctrl->server_local);
    2561           0 :       dirmngr_deinit_default_ctrl (ctrl);
    2562           0 :       xfree (ctrl);
    2563             :     }
    2564             : }
    2565             : 
    2566             : 
    2567             : /* Send a status line back to the client.  KEYWORD is the status
    2568             :    keyword, the optional string arguments are blank separated added to
    2569             :    the line, the last argument must be a NULL. */
    2570             : gpg_error_t
    2571           0 : dirmngr_status (ctrl_t ctrl, const char *keyword, ...)
    2572             : {
    2573           0 :   gpg_error_t err = 0;
    2574             :   va_list arg_ptr;
    2575             :   const char *text;
    2576             : 
    2577           0 :   va_start (arg_ptr, keyword);
    2578             : 
    2579           0 :   if (ctrl->server_local)
    2580             :     {
    2581           0 :       assuan_context_t ctx = ctrl->server_local->assuan_ctx;
    2582             :       char buf[950], *p;
    2583             :       size_t n;
    2584             : 
    2585           0 :       p = buf;
    2586           0 :       n = 0;
    2587           0 :       while ( (text = va_arg (arg_ptr, const char *)) )
    2588             :         {
    2589           0 :           if (n)
    2590             :             {
    2591           0 :               *p++ = ' ';
    2592           0 :               n++;
    2593             :             }
    2594           0 :           for ( ; *text && n < DIM (buf)-2; n++)
    2595           0 :             *p++ = *text++;
    2596             :         }
    2597           0 :       *p = 0;
    2598           0 :       err = assuan_write_status (ctx, keyword, buf);
    2599             :     }
    2600             : 
    2601           0 :   va_end (arg_ptr);
    2602           0 :   return err;
    2603             : }
    2604             : 
    2605             : 
    2606             : /* Print a help status line.  TEXTLEN gives the length of the text
    2607             :    from TEXT to be printed.  The function splits text at LFs.  */
    2608             : gpg_error_t
    2609           0 : dirmngr_status_help (ctrl_t ctrl, const char *text)
    2610             : {
    2611           0 :   gpg_error_t err = 0;
    2612             : 
    2613           0 :   if (ctrl->server_local)
    2614             :     {
    2615           0 :       assuan_context_t ctx = ctrl->server_local->assuan_ctx;
    2616             :       char buf[950], *p;
    2617             :       size_t n;
    2618             : 
    2619             :       do
    2620             :         {
    2621           0 :           p = buf;
    2622           0 :           n = 0;
    2623           0 :           for ( ; *text && *text != '\n' && n < DIM (buf)-2; n++)
    2624           0 :             *p++ = *text++;
    2625           0 :           if (*text == '\n')
    2626           0 :             text++;
    2627           0 :           *p = 0;
    2628           0 :           err = assuan_write_status (ctx, "#", buf);
    2629             :         }
    2630           0 :       while (!err && *text);
    2631             :     }
    2632             : 
    2633           0 :   return err;
    2634             : }
    2635             : 
    2636             : /* Send a tick progress indicator back.  Fixme: This is only done for
    2637             :    the currently active channel.  */
    2638             : gpg_error_t
    2639           0 : dirmngr_tick (ctrl_t ctrl)
    2640             : {
    2641             :   static time_t next_tick = 0;
    2642           0 :   gpg_error_t err = 0;
    2643           0 :   time_t now = time (NULL);
    2644             : 
    2645           0 :   if (!next_tick)
    2646             :     {
    2647           0 :       next_tick = now + 1;
    2648             :     }
    2649           0 :   else if ( now > next_tick )
    2650             :     {
    2651           0 :       if (ctrl)
    2652             :         {
    2653           0 :           err = dirmngr_status (ctrl, "PROGRESS", "tick", "? 0 0", NULL);
    2654           0 :           if (err)
    2655             :             {
    2656             :               /* Take this as in indication for a cancel request.  */
    2657           0 :               err = gpg_error (GPG_ERR_CANCELED);
    2658             :             }
    2659           0 :           now = time (NULL);
    2660             :         }
    2661             : 
    2662           0 :       next_tick = now + 1;
    2663             :     }
    2664           0 :   return err;
    2665             : }

Generated by: LCOV version 1.11