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