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

Generated by: LCOV version 1.11