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