dirmngr: Prepare for updated WKD specs with ?l= param
[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       /* Check for rogue DNS names.  */
891       for (i = 0; i < srvscount; i++)
892         {
893           if (!is_valid_domain_name (srvs[i].target))
894             {
895               err = gpg_error (GPG_ERR_DNS_ADDRESS);
896               log_error ("rogue openpgpkey SRV record for '%s'\n", domain);
897               xfree (srvs);
898               goto leave;
899             }
900         }
901
902       /* Find the first target which also ends in DOMAIN or is equal
903        * to DOMAIN.  */
904       domainlen = strlen (domain);
905       for (i = 0; i < srvscount; i++)
906         {
907           if (DBG_DNS)
908             log_debug ("srv: trying '%s:%hu'\n", srvs[i].target, srvs[i].port);
909           targetlen = strlen (srvs[i].target);
910           if ((targetlen > domainlen + 1
911                && srvs[i].target[targetlen - domainlen - 1] == '.'
912                && !ascii_strcasecmp (srvs[i].target + targetlen - domainlen,
913                                      domain))
914               || (targetlen == domainlen
915                   && !ascii_strcasecmp (srvs[i].target, domain)))
916             {
917               /* found.  */
918               domainbuf = xtrystrdup (srvs[i].target);
919               if (!domainbuf)
920                 {
921                   err = gpg_error_from_syserror ();
922                   xfree (srvs);
923                   goto leave;
924                 }
925               domain = domainbuf;
926               if (srvs[i].port)
927                 snprintf (portstr, sizeof portstr, ":%hu", srvs[i].port);
928               break;
929             }
930         }
931       xfree (srvs);
932     }
933
934   gcry_md_hash_buffer (GCRY_MD_SHA1, sha1buf, mbox, strlen (mbox));
935   encodedhash = zb32_encode (sha1buf, 8*20);
936   if (!encodedhash)
937     {
938       err = gpg_error_from_syserror ();
939       goto leave;
940     }
941
942   if (opt_submission_addr)
943     {
944       uri = strconcat ("https://",
945                        domain,
946                        portstr,
947                        "/.well-known/openpgpkey/submission-address",
948                        NULL);
949     }
950   else if (opt_policy_flags)
951     {
952       uri = strconcat ("https://",
953                        domain,
954                        portstr,
955                        "/.well-known/openpgpkey/policy",
956                        NULL);
957     }
958   else
959     {
960       char *escapedmbox;
961
962       escapedmbox = http_escape_string (mbox, "%;?&=");
963       if (escapedmbox)
964         {
965           uri = strconcat ("https://",
966                            domain,
967                            portstr,
968                            "/.well-known/openpgpkey/hu/",
969                            encodedhash,
970                            "?l=",
971                            escapedmbox,
972                            NULL);
973           xfree (escapedmbox);
974           no_log = 1;
975           if (uri)
976             {
977               err = dirmngr_status_printf (ctrl, "SOURCE", "https://%s%s",
978                                            domain, portstr);
979               if (err)
980                 goto leave;
981             }
982         }
983     }
984   if (!uri)
985     {
986       err = gpg_error_from_syserror ();
987       goto leave;
988     }
989
990   /* Setup an output stream and perform the get.  */
991   {
992     estream_t outfp;
993
994     outfp = ctx? es_fopencookie (ctx, "w", data_line_cookie_functions) : NULL;
995     if (!outfp && ctx)
996       err = set_error (GPG_ERR_ASS_GENERAL,
997                        "error setting up a data stream");
998     else
999       {
1000         if (ctrl->server_local)
1001           {
1002             if (no_log)
1003               ctrl->server_local->inhibit_data_logging = 1;
1004             ctrl->server_local->inhibit_data_logging_now = 0;
1005             ctrl->server_local->inhibit_data_logging_count = 0;
1006           }
1007         err = ks_action_fetch (ctrl, uri, outfp);
1008         es_fclose (outfp);
1009         if (ctrl->server_local)
1010           ctrl->server_local->inhibit_data_logging = 0;
1011
1012         /* Register the result under the domain name of MBOX. */
1013         switch (gpg_err_code (err))
1014           {
1015           case 0:
1016             domaininfo_set_wkd_supported (domain_orig);
1017             break;
1018
1019           case GPG_ERR_NO_NAME:
1020             /* There is no such domain.  */
1021             domaininfo_set_no_name (domain_orig);
1022             break;
1023
1024           case GPG_ERR_NO_DATA:
1025             if (is_wkd_query && ctrl->server_local)
1026               {
1027                 /* Mark that and schedule a check.  */
1028                 domaininfo_set_wkd_not_found (domain_orig);
1029                 workqueue_add_task (task_check_wkd_support, domain_orig,
1030                                     ctrl->server_local->session_id, 1);
1031               }
1032             else if (opt_policy_flags) /* No policy file - no support.  */
1033               domaininfo_set_wkd_not_supported (domain_orig);
1034             break;
1035
1036           default:
1037             /* Don't register other errors.  */
1038             break;
1039           }
1040       }
1041   }
1042
1043  leave:
1044   xfree (uri);
1045   xfree (encodedhash);
1046   xfree (mbox);
1047   xfree (domainbuf);
1048   return err;
1049 }
1050
1051
1052 static const char hlp_wkd_get[] =
1053   "WKD_GET [--submission-address|--policy-flags] <user_id>\n"
1054   "\n"
1055   "Return the key or other info for <user_id>\n"
1056   "from the Web Key Directory.";
1057 static gpg_error_t
1058 cmd_wkd_get (assuan_context_t ctx, char *line)
1059 {
1060   ctrl_t ctrl = assuan_get_pointer (ctx);
1061   gpg_error_t err;
1062
1063   err = proc_wkd_get (ctrl, ctx, line);
1064
1065   return leave_cmd (ctx, err);
1066 }
1067
1068
1069 /* A task to check whether DOMAIN supports WKD.  This is done by
1070  * checking whether the policy flags file can be read.  */
1071 static const char *
1072 task_check_wkd_support (ctrl_t ctrl, const char *domain)
1073 {
1074   char *string;
1075
1076   if (!ctrl || !domain)
1077     return "check_wkd_support";
1078
1079   string = strconcat ("--policy-flags foo@", domain, NULL);
1080   if (!string)
1081     log_error ("%s: %s\n", __func__, gpg_strerror (gpg_error_from_syserror ()));
1082   else
1083     {
1084       proc_wkd_get (ctrl, NULL, string);
1085       xfree (string);
1086     }
1087
1088   return NULL;
1089 }
1090
1091
1092 \f
1093 static const char hlp_ldapserver[] =
1094   "LDAPSERVER <data>\n"
1095   "\n"
1096   "Add a new LDAP server to the list of configured LDAP servers.\n"
1097   "DATA is in the same format as expected in the configure file.";
1098 static gpg_error_t
1099 cmd_ldapserver (assuan_context_t ctx, char *line)
1100 {
1101 #if USE_LDAP
1102   ctrl_t ctrl = assuan_get_pointer (ctx);
1103   ldap_server_t server;
1104   ldap_server_t *last_next_p;
1105
1106   while (spacep (line))
1107     line++;
1108   if (*line == '\0')
1109     return leave_cmd (ctx, PARM_ERROR (_("ldapserver missing")));
1110
1111   server = ldapserver_parse_one (line, "", 0);
1112   if (! server)
1113     return leave_cmd (ctx, gpg_error (GPG_ERR_INV_ARG));
1114
1115   last_next_p = &ctrl->server_local->ldapservers;
1116   while (*last_next_p)
1117     last_next_p = &(*last_next_p)->next;
1118   *last_next_p = server;
1119   return leave_cmd (ctx, 0);
1120 #else
1121   (void)line;
1122   return leave_cmd (ctx, gpg_error (GPG_ERR_NOT_IMPLEMENTED));
1123 #endif
1124 }
1125
1126
1127 static const char hlp_isvalid[] =
1128   "ISVALID [--only-ocsp] [--force-default-responder]"
1129   " <certificate_id> [<certificate_fpr>]\n"
1130   "\n"
1131   "This command checks whether the certificate identified by the\n"
1132   "certificate_id is valid.  This is done by consulting CRLs or\n"
1133   "whatever has been configured.  Note, that the returned error codes\n"
1134   "are from gpg-error.h.  The command may callback using the inquire\n"
1135   "function.  See the manual for details.\n"
1136   "\n"
1137   "The CERTIFICATE_ID is a hex encoded string consisting of two parts,\n"
1138   "delimited by a single dot.  The first part is the SHA-1 hash of the\n"
1139   "issuer name and the second part the serial number.\n"
1140   "\n"
1141   "If an OCSP check is desired CERTIFICATE_FPR with the hex encoded\n"
1142   "fingerprint of the certificate is required.  In this case an OCSP\n"
1143   "request is done before consulting the CRL.\n"
1144   "\n"
1145   "If the option --only-ocsp is given, no fallback to a CRL check will\n"
1146   "be used.\n"
1147   "\n"
1148   "If the option --force-default-responder is given, only the default\n"
1149   "OCSP responder will be used and any other methods of obtaining an\n"
1150   "OCSP responder URL won't be used.";
1151 static gpg_error_t
1152 cmd_isvalid (assuan_context_t ctx, char *line)
1153 {
1154   ctrl_t ctrl = assuan_get_pointer (ctx);
1155   char *issuerhash, *serialno, *fpr;
1156   gpg_error_t err;
1157   int did_inquire = 0;
1158   int ocsp_mode = 0;
1159   int only_ocsp;
1160   int force_default_responder;
1161
1162   only_ocsp = has_option (line, "--only-ocsp");
1163   force_default_responder = has_option (line, "--force-default-responder");
1164   line = skip_options (line);
1165
1166   /* We need to work on a copy of the line because that same Assuan
1167    * context may be used for an inquiry.  That is because Assuan
1168    * reuses its line buffer.  */
1169   issuerhash = xstrdup (line);
1170
1171   serialno = strchr (issuerhash, '.');
1172   if (!serialno)
1173     {
1174       xfree (issuerhash);
1175       return leave_cmd (ctx, PARM_ERROR (_("serialno missing in cert ID")));
1176     }
1177   *serialno++ = 0;
1178   if (strlen (issuerhash) != 40)
1179     {
1180       xfree (issuerhash);
1181       return leave_cmd (ctx, PARM_ERROR ("cert ID is too short"));
1182     }
1183
1184   fpr = strchr (serialno, ' ');
1185   while (fpr && spacep (fpr))
1186     fpr++;
1187   if (fpr && *fpr)
1188     {
1189       char *endp = strchr (fpr, ' ');
1190       if (endp)
1191         *endp = 0;
1192       if (strlen (fpr) != 40)
1193         {
1194           xfree (issuerhash);
1195           return leave_cmd (ctx, PARM_ERROR ("fingerprint too short"));
1196         }
1197       ocsp_mode = 1;
1198     }
1199
1200
1201  again:
1202   if (ocsp_mode)
1203     {
1204       /* Note, that we currently ignore the supplied fingerprint FPR;
1205        * instead ocsp_isvalid does an inquire to ask for the cert.
1206        * The fingerprint may eventually be used to lookup the
1207        * certificate in a local cache.  */
1208       if (!opt.allow_ocsp)
1209         err = gpg_error (GPG_ERR_NOT_SUPPORTED);
1210       else
1211         err = ocsp_isvalid (ctrl, NULL, NULL, force_default_responder);
1212
1213       if (gpg_err_code (err) == GPG_ERR_CONFIGURATION
1214           && gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR)
1215         {
1216           /* No default responder configured - fallback to CRL.  */
1217           if (!only_ocsp)
1218             log_info ("falling back to CRL check\n");
1219           ocsp_mode = 0;
1220           goto again;
1221         }
1222     }
1223   else if (only_ocsp)
1224     err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
1225   else
1226     {
1227       switch (crl_cache_isvalid (ctrl,
1228                                  issuerhash, serialno,
1229                                  ctrl->force_crl_refresh))
1230         {
1231         case CRL_CACHE_VALID:
1232           err = 0;
1233           break;
1234         case CRL_CACHE_INVALID:
1235           err = gpg_error (GPG_ERR_CERT_REVOKED);
1236           break;
1237         case CRL_CACHE_DONTKNOW:
1238           if (did_inquire)
1239             err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
1240           else if (!(err = inquire_cert_and_load_crl (ctx)))
1241             {
1242               did_inquire = 1;
1243               goto again;
1244             }
1245           break;
1246         case CRL_CACHE_CANTUSE:
1247           err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
1248           break;
1249         default:
1250           log_fatal ("crl_cache_isvalid returned invalid code\n");
1251         }
1252     }
1253
1254   xfree (issuerhash);
1255   return leave_cmd (ctx, err);
1256 }
1257
1258
1259 /* If the line contains a SHA-1 fingerprint as the first argument,
1260    return the FPR vuffer on success.  The function checks that the
1261    fingerprint consists of valid characters and prints and error
1262    message if it does not and returns NULL.  Fingerprints are
1263    considered optional and thus no explicit error is returned. NULL is
1264    also returned if there is no fingerprint at all available.
1265    FPR must be a caller provided buffer of at least 20 bytes.
1266
1267    Note that colons within the fingerprint are allowed to separate 2
1268    hex digits; this allows for easier cutting and pasting using the
1269    usual fingerprint rendering.
1270 */
1271 static unsigned char *
1272 get_fingerprint_from_line (const char *line, unsigned char *fpr)
1273 {
1274   const char *s;
1275   int i;
1276
1277   for (s=line, i=0; *s && *s != ' '; s++ )
1278     {
1279       if ( hexdigitp (s) && hexdigitp (s+1) )
1280         {
1281           if ( i >= 20 )
1282             return NULL;  /* Fingerprint too long.  */
1283           fpr[i++] = xtoi_2 (s);
1284           s++;
1285         }
1286       else if ( *s != ':' )
1287         return NULL; /* Invalid.  */
1288     }
1289   if ( i != 20 )
1290     return NULL; /* Fingerprint to short.  */
1291   return fpr;
1292 }
1293
1294
1295
1296 static const char hlp_checkcrl[] =
1297   "CHECKCRL [<fingerprint>]\n"
1298   "\n"
1299   "Check whether the certificate with FINGERPRINT (SHA-1 hash of the\n"
1300   "entire X.509 certificate blob) is valid or not by consulting the\n"
1301   "CRL responsible for this certificate.  If the fingerprint has not\n"
1302   "been given or the certificate is not known, the function \n"
1303   "inquires the certificate using an\n"
1304   "\n"
1305   "  INQUIRE TARGETCERT\n"
1306   "\n"
1307   "and the caller is expected to return the certificate for the\n"
1308   "request (which should match FINGERPRINT) as a binary blob.\n"
1309   "Processing then takes place without further interaction; in\n"
1310   "particular dirmngr tries to locate other required certificate by\n"
1311   "its own mechanism which includes a local certificate store as well\n"
1312   "as a list of trusted root certificates.\n"
1313   "\n"
1314   "The return value is the usual gpg-error code or 0 for ducesss;\n"
1315   "i.e. the certificate validity has been confirmed by a valid CRL.";
1316 static gpg_error_t
1317 cmd_checkcrl (assuan_context_t ctx, char *line)
1318 {
1319   ctrl_t ctrl = assuan_get_pointer (ctx);
1320   gpg_error_t err;
1321   unsigned char fprbuffer[20], *fpr;
1322   ksba_cert_t cert;
1323
1324   fpr = get_fingerprint_from_line (line, fprbuffer);
1325   cert = fpr? get_cert_byfpr (fpr) : NULL;
1326
1327   if (!cert)
1328     {
1329       /* We do not have this certificate yet or the fingerprint has
1330          not been given.  Inquire it from the client.  */
1331       unsigned char *value = NULL;
1332       size_t valuelen;
1333
1334       err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1335                            &value, &valuelen, MAX_CERT_LENGTH);
1336       if (err)
1337         {
1338           log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1339           goto leave;
1340         }
1341
1342       if (!valuelen) /* No data returned; return a comprehensible error. */
1343         err = gpg_error (GPG_ERR_MISSING_CERT);
1344       else
1345         {
1346           err = ksba_cert_new (&cert);
1347           if (!err)
1348             err = ksba_cert_init_from_mem (cert, value, valuelen);
1349         }
1350       xfree (value);
1351       if(err)
1352         goto leave;
1353     }
1354
1355   assert (cert);
1356
1357   err = crl_cache_cert_isvalid (ctrl, cert, ctrl->force_crl_refresh);
1358   if (gpg_err_code (err) == GPG_ERR_NO_CRL_KNOWN)
1359     {
1360       err = crl_cache_reload_crl (ctrl, cert);
1361       if (!err)
1362         err = crl_cache_cert_isvalid (ctrl, cert, 0);
1363     }
1364
1365  leave:
1366   ksba_cert_release (cert);
1367   return leave_cmd (ctx, err);
1368 }
1369
1370
1371 static const char hlp_checkocsp[] =
1372   "CHECKOCSP [--force-default-responder] [<fingerprint>]\n"
1373   "\n"
1374   "Check whether the certificate with FINGERPRINT (SHA-1 hash of the\n"
1375   "entire X.509 certificate blob) is valid or not by asking an OCSP\n"
1376   "responder responsible for this certificate.  The optional\n"
1377   "fingerprint may be used for a quick check in case an OCSP check has\n"
1378   "been done for this certificate recently (we always cache OCSP\n"
1379   "responses for a couple of minutes). If the fingerprint has not been\n"
1380   "given or there is no cached result, the function inquires the\n"
1381   "certificate using an\n"
1382   "\n"
1383   "   INQUIRE TARGETCERT\n"
1384   "\n"
1385   "and the caller is expected to return the certificate for the\n"
1386   "request (which should match FINGERPRINT) as a binary blob.\n"
1387   "Processing then takes place without further interaction; in\n"
1388   "particular dirmngr tries to locate other required certificates by\n"
1389   "its own mechanism which includes a local certificate store as well\n"
1390   "as a list of trusted root certificates.\n"
1391   "\n"
1392   "If the option --force-default-responder is given, only the default\n"
1393   "OCSP responder will be used and any other methods of obtaining an\n"
1394   "OCSP responder URL won't be used.\n"
1395   "\n"
1396   "The return value is the usual gpg-error code or 0 for ducesss;\n"
1397   "i.e. the certificate validity has been confirmed by a valid CRL.";
1398 static gpg_error_t
1399 cmd_checkocsp (assuan_context_t ctx, char *line)
1400 {
1401   ctrl_t ctrl = assuan_get_pointer (ctx);
1402   gpg_error_t err;
1403   unsigned char fprbuffer[20], *fpr;
1404   ksba_cert_t cert;
1405   int force_default_responder;
1406
1407   force_default_responder = has_option (line, "--force-default-responder");
1408   line = skip_options (line);
1409
1410   fpr = get_fingerprint_from_line (line, fprbuffer);
1411   cert = fpr? get_cert_byfpr (fpr) : NULL;
1412
1413   if (!cert)
1414     {
1415       /* We do not have this certificate yet or the fingerprint has
1416          not been given.  Inquire it from the client.  */
1417       unsigned char *value = NULL;
1418       size_t valuelen;
1419
1420       err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1421                            &value, &valuelen, MAX_CERT_LENGTH);
1422       if (err)
1423         {
1424           log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1425           goto leave;
1426         }
1427
1428       if (!valuelen) /* No data returned; return a comprehensible error. */
1429         err = gpg_error (GPG_ERR_MISSING_CERT);
1430       else
1431         {
1432           err = ksba_cert_new (&cert);
1433           if (!err)
1434             err = ksba_cert_init_from_mem (cert, value, valuelen);
1435         }
1436       xfree (value);
1437       if(err)
1438         goto leave;
1439     }
1440
1441   assert (cert);
1442
1443   if (!opt.allow_ocsp)
1444     err = gpg_error (GPG_ERR_NOT_SUPPORTED);
1445   else
1446     err = ocsp_isvalid (ctrl, cert, NULL, force_default_responder);
1447
1448  leave:
1449   ksba_cert_release (cert);
1450   return leave_cmd (ctx, err);
1451 }
1452
1453
1454
1455 static int
1456 lookup_cert_by_url (assuan_context_t ctx, const char *url)
1457 {
1458   ctrl_t ctrl = assuan_get_pointer (ctx);
1459   gpg_error_t err = 0;
1460   unsigned char *value = NULL;
1461   size_t valuelen;
1462
1463   /* Fetch single certificate given it's URL.  */
1464   err = fetch_cert_by_url (ctrl, url, &value, &valuelen);
1465   if (err)
1466     {
1467       log_error (_("fetch_cert_by_url failed: %s\n"), gpg_strerror (err));
1468       goto leave;
1469     }
1470
1471   /* Send the data, flush the buffer and then send an END. */
1472   err = assuan_send_data (ctx, value, valuelen);
1473   if (!err)
1474     err = assuan_send_data (ctx, NULL, 0);
1475   if (!err)
1476     err = assuan_write_line (ctx, "END");
1477   if (err)
1478     {
1479       log_error (_("error sending data: %s\n"), gpg_strerror (err));
1480       goto leave;
1481     }
1482
1483  leave:
1484
1485   return err;
1486 }
1487
1488
1489 /* Send the certificate, flush the buffer and then send an END. */
1490 static gpg_error_t
1491 return_one_cert (void *opaque, ksba_cert_t cert)
1492 {
1493   assuan_context_t ctx = opaque;
1494   gpg_error_t err;
1495   const unsigned char *der;
1496   size_t derlen;
1497
1498   der = ksba_cert_get_image (cert, &derlen);
1499   if (!der)
1500     err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1501   else
1502     {
1503       err = assuan_send_data (ctx, der, derlen);
1504       if (!err)
1505         err = assuan_send_data (ctx, NULL, 0);
1506       if (!err)
1507         err = assuan_write_line (ctx, "END");
1508     }
1509   if (err)
1510     log_error (_("error sending data: %s\n"), gpg_strerror (err));
1511   return err;
1512 }
1513
1514
1515 /* Lookup certificates from the internal cache or using the ldap
1516    servers. */
1517 static int
1518 lookup_cert_by_pattern (assuan_context_t ctx, char *line,
1519                         int single, int cache_only)
1520 {
1521   gpg_error_t err = 0;
1522   char *p;
1523   strlist_t sl, list = NULL;
1524   int truncated = 0, truncation_forced = 0;
1525   int count = 0;
1526   int local_count = 0;
1527 #if USE_LDAP
1528   ctrl_t ctrl = assuan_get_pointer (ctx);
1529   unsigned char *value = NULL;
1530   size_t valuelen;
1531   struct ldapserver_iter ldapserver_iter;
1532   cert_fetch_context_t fetch_context;
1533 #endif /*USE_LDAP*/
1534   int any_no_data = 0;
1535
1536   /* Break the line down into an STRLIST */
1537   for (p=line; *p; line = p)
1538     {
1539       while (*p && *p != ' ')
1540         p++;
1541       if (*p)
1542         *p++ = 0;
1543
1544       if (*line)
1545         {
1546           sl = xtrymalloc (sizeof *sl + strlen (line));
1547           if (!sl)
1548             {
1549               err = gpg_error_from_errno (errno);
1550               goto leave;
1551             }
1552           memset (sl, 0, sizeof *sl);
1553           strcpy_escaped_plus (sl->d, line);
1554           sl->next = list;
1555           list = sl;
1556         }
1557     }
1558
1559   /* First look through the internal cache.  The certificates returned
1560      here are not counted towards the truncation limit.  */
1561   if (single && !cache_only)
1562     ; /* Do not read from the local cache in this case.  */
1563   else
1564     {
1565       for (sl=list; sl; sl = sl->next)
1566         {
1567           err = get_certs_bypattern (sl->d, return_one_cert, ctx);
1568           if (!err)
1569             local_count++;
1570           if (!err && single)
1571             goto ready;
1572
1573           if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1574             {
1575               err = 0;
1576               if (cache_only)
1577                 any_no_data = 1;
1578             }
1579           else if (gpg_err_code (err) == GPG_ERR_INV_NAME && !cache_only)
1580             {
1581               /* No real fault because the internal pattern lookup
1582                  can't yet cope with all types of pattern.  */
1583               err = 0;
1584             }
1585           if (err)
1586             goto ready;
1587         }
1588     }
1589
1590   /* Loop over all configured servers unless we want only the
1591      certificates from the cache.  */
1592 #if USE_LDAP
1593   for (ldapserver_iter_begin (&ldapserver_iter, ctrl);
1594        !cache_only && !ldapserver_iter_end_p (&ldapserver_iter)
1595          && ldapserver_iter.server->host && !truncation_forced;
1596        ldapserver_iter_next (&ldapserver_iter))
1597     {
1598       ldap_server_t ldapserver = ldapserver_iter.server;
1599
1600       if (DBG_LOOKUP)
1601         log_debug ("cmd_lookup: trying %s:%d base=%s\n",
1602                    ldapserver->host, ldapserver->port,
1603                    ldapserver->base?ldapserver->base : "[default]");
1604
1605       /* Fetch certificates matching pattern */
1606       err = start_cert_fetch (ctrl, &fetch_context, list, ldapserver);
1607       if ( gpg_err_code (err) == GPG_ERR_NO_DATA )
1608         {
1609           if (DBG_LOOKUP)
1610             log_debug ("cmd_lookup: no data\n");
1611           err = 0;
1612           any_no_data = 1;
1613           continue;
1614         }
1615       if (err)
1616         {
1617           log_error (_("start_cert_fetch failed: %s\n"), gpg_strerror (err));
1618           goto leave;
1619         }
1620
1621       /* Fetch the certificates for this query. */
1622       while (!truncation_forced)
1623         {
1624           xfree (value); value = NULL;
1625           err = fetch_next_cert (fetch_context, &value, &valuelen);
1626           if (gpg_err_code (err) == GPG_ERR_NO_DATA )
1627             {
1628               err = 0;
1629               any_no_data = 1;
1630               break; /* Ready. */
1631             }
1632           if (gpg_err_code (err) == GPG_ERR_TRUNCATED)
1633             {
1634               truncated = 1;
1635               err = 0;
1636               break;  /* Ready.  */
1637             }
1638           if (gpg_err_code (err) == GPG_ERR_EOF)
1639             {
1640               err = 0;
1641               break; /* Ready. */
1642             }
1643           if (!err && !value)
1644             {
1645               err = gpg_error (GPG_ERR_BUG);
1646               goto leave;
1647             }
1648           if (err)
1649             {
1650               log_error (_("fetch_next_cert failed: %s\n"),
1651                          gpg_strerror (err));
1652               end_cert_fetch (fetch_context);
1653               goto leave;
1654             }
1655
1656           if (DBG_LOOKUP)
1657             log_debug ("cmd_lookup: returning one cert%s\n",
1658                        truncated? " (truncated)":"");
1659
1660           /* Send the data, flush the buffer and then send an END line
1661              as a certificate delimiter. */
1662           err = assuan_send_data (ctx, value, valuelen);
1663           if (!err)
1664             err = assuan_send_data (ctx, NULL, 0);
1665           if (!err)
1666             err = assuan_write_line (ctx, "END");
1667           if (err)
1668             {
1669               log_error (_("error sending data: %s\n"), gpg_strerror (err));
1670               end_cert_fetch (fetch_context);
1671               goto leave;
1672             }
1673
1674           if (++count >= opt.max_replies )
1675             {
1676               truncation_forced = 1;
1677               log_info (_("max_replies %d exceeded\n"), opt.max_replies );
1678             }
1679           if (single)
1680             break;
1681         }
1682
1683       end_cert_fetch (fetch_context);
1684     }
1685 #endif /*USE_LDAP*/
1686
1687  ready:
1688   if (truncated || truncation_forced)
1689     {
1690       char str[50];
1691
1692       sprintf (str, "%d", count);
1693       assuan_write_status (ctx, "TRUNCATED", str);
1694     }
1695
1696   if (!err && !count && !local_count && any_no_data)
1697     err = gpg_error (GPG_ERR_NO_DATA);
1698
1699  leave:
1700   free_strlist (list);
1701   return err;
1702 }
1703
1704
1705 static const char hlp_lookup[] =
1706   "LOOKUP [--url] [--single] [--cache-only] <pattern>\n"
1707   "\n"
1708   "Lookup certificates matching PATTERN. With --url the pattern is\n"
1709   "expected to be one URL.\n"
1710   "\n"
1711   "If --url is not given:  To allow for multiple patterns (which are ORed)\n"
1712   "quoting is required: Spaces are translated to \"+\" or \"%20\";\n"
1713   "obviously this requires that the usual escape quoting rules are applied.\n"
1714   "\n"
1715   "If --url is given no special escaping is required because URLs are\n"
1716   "already escaped this way.\n"
1717   "\n"
1718   "If --single is given the first and only the first match will be\n"
1719   "returned.  If --cache-only is _not_ given, no local query will be\n"
1720   "done.\n"
1721   "\n"
1722   "If --cache-only is given no external lookup is done so that only\n"
1723   "certificates from the cache may get returned.";
1724 static gpg_error_t
1725 cmd_lookup (assuan_context_t ctx, char *line)
1726 {
1727   gpg_error_t err;
1728   int lookup_url, single, cache_only;
1729
1730   lookup_url = has_leading_option (line, "--url");
1731   single = has_leading_option (line, "--single");
1732   cache_only = has_leading_option (line, "--cache-only");
1733   line = skip_options (line);
1734
1735   if (lookup_url && cache_only)
1736     err = gpg_error (GPG_ERR_NOT_FOUND);
1737   else if (lookup_url && single)
1738     err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1739   else if (lookup_url)
1740     err = lookup_cert_by_url (ctx, line);
1741   else
1742     err = lookup_cert_by_pattern (ctx, line, single, cache_only);
1743
1744   return leave_cmd (ctx, err);
1745 }
1746
1747
1748 static const char hlp_loadcrl[] =
1749   "LOADCRL [--url] <filename|url>\n"
1750   "\n"
1751   "Load the CRL in the file with name FILENAME into our cache.  Note\n"
1752   "that FILENAME should be given with an absolute path because\n"
1753   "Dirmngrs cwd is not known.  With --url the CRL is directly loaded\n"
1754   "from the given URL.\n"
1755   "\n"
1756   "This command is usually used by gpgsm using the invocation \"gpgsm\n"
1757   "--call-dirmngr loadcrl <filename>\".  A direct invocation of Dirmngr\n"
1758   "is not useful because gpgsm might need to callback gpgsm to ask for\n"
1759   "the CA's certificate.";
1760 static gpg_error_t
1761 cmd_loadcrl (assuan_context_t ctx, char *line)
1762 {
1763   ctrl_t ctrl = assuan_get_pointer (ctx);
1764   gpg_error_t err = 0;
1765   int use_url = has_leading_option (line, "--url");
1766
1767   line = skip_options (line);
1768
1769   if (use_url)
1770     {
1771       ksba_reader_t reader;
1772
1773       err = crl_fetch (ctrl, line, &reader);
1774       if (err)
1775         log_error (_("fetching CRL from '%s' failed: %s\n"),
1776                    line, gpg_strerror (err));
1777       else
1778         {
1779           err = crl_cache_insert (ctrl, line, reader);
1780           if (err)
1781             log_error (_("processing CRL from '%s' failed: %s\n"),
1782                        line, gpg_strerror (err));
1783           crl_close_reader (reader);
1784         }
1785     }
1786   else
1787     {
1788       char *buf;
1789
1790       buf = xtrymalloc (strlen (line)+1);
1791       if (!buf)
1792         err = gpg_error_from_syserror ();
1793       else
1794         {
1795           strcpy_escaped_plus (buf, line);
1796           err = crl_cache_load (ctrl, buf);
1797           xfree (buf);
1798         }
1799     }
1800
1801   return leave_cmd (ctx, err);
1802 }
1803
1804
1805 static const char hlp_listcrls[] =
1806   "LISTCRLS\n"
1807   "\n"
1808   "List the content of all CRLs in a readable format.  This command is\n"
1809   "usually used by gpgsm using the invocation \"gpgsm --call-dirmngr\n"
1810   "listcrls\".  It may also be used directly using \"dirmngr\n"
1811   "--list-crls\".";
1812 static gpg_error_t
1813 cmd_listcrls (assuan_context_t ctx, char *line)
1814 {
1815   gpg_error_t err;
1816   estream_t fp;
1817
1818   (void)line;
1819
1820   fp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1821   if (!fp)
1822     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1823   else
1824     {
1825       err = crl_cache_list (fp);
1826       es_fclose (fp);
1827     }
1828   return leave_cmd (ctx, err);
1829 }
1830
1831
1832 static const char hlp_cachecert[] =
1833   "CACHECERT\n"
1834   "\n"
1835   "Put a certificate into the internal cache.  This command might be\n"
1836   "useful if a client knows in advance certificates required for a\n"
1837   "test and wants to make sure they get added to the internal cache.\n"
1838   "It is also helpful for debugging.  To get the actual certificate,\n"
1839   "this command immediately inquires it using\n"
1840   "\n"
1841   "  INQUIRE TARGETCERT\n"
1842   "\n"
1843   "and the caller is expected to return the certificate for the\n"
1844   "request as a binary blob.";
1845 static gpg_error_t
1846 cmd_cachecert (assuan_context_t ctx, char *line)
1847 {
1848   ctrl_t ctrl = assuan_get_pointer (ctx);
1849   gpg_error_t err;
1850   ksba_cert_t cert = NULL;
1851   unsigned char *value = NULL;
1852   size_t valuelen;
1853
1854   (void)line;
1855
1856   err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1857                        &value, &valuelen, MAX_CERT_LENGTH);
1858   if (err)
1859     {
1860       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1861       goto leave;
1862     }
1863
1864   if (!valuelen) /* No data returned; return a comprehensible error. */
1865     err = gpg_error (GPG_ERR_MISSING_CERT);
1866   else
1867     {
1868       err = ksba_cert_new (&cert);
1869       if (!err)
1870         err = ksba_cert_init_from_mem (cert, value, valuelen);
1871     }
1872   xfree (value);
1873   if(err)
1874     goto leave;
1875
1876   err = cache_cert (cert);
1877
1878  leave:
1879   ksba_cert_release (cert);
1880   return leave_cmd (ctx, err);
1881 }
1882
1883
1884 static const char hlp_validate[] =
1885   "VALIDATE [--systrust] [--tls] [--no-crl]\n"
1886   "\n"
1887   "Validate a certificate using the certificate validation function\n"
1888   "used internally by dirmngr.  This command is only useful for\n"
1889   "debugging.  To get the actual certificate, this command immediately\n"
1890   "inquires it using\n"
1891   "\n"
1892   "  INQUIRE TARGETCERT\n"
1893   "\n"
1894   "and the caller is expected to return the certificate for the\n"
1895   "request as a binary blob.  The option --tls modifies this by asking\n"
1896   "for list of certificates with\n"
1897   "\n"
1898   "  INQUIRE CERTLIST\n"
1899   "\n"
1900   "Here the first certificate is the target certificate, the remaining\n"
1901   "certificates are suggested intermediary certificates.  All certificates\n"
1902   "need to be PEM encoded.\n"
1903   "\n"
1904   "The option --systrust changes the behaviour to include the system\n"
1905   "provided root certificates as trust anchors.  The option --no-crl\n"
1906   "skips CRL checks";
1907 static gpg_error_t
1908 cmd_validate (assuan_context_t ctx, char *line)
1909 {
1910   ctrl_t ctrl = assuan_get_pointer (ctx);
1911   gpg_error_t err;
1912   ksba_cert_t cert = NULL;
1913   certlist_t certlist = NULL;
1914   unsigned char *value = NULL;
1915   size_t valuelen;
1916   int systrust_mode, tls_mode, no_crl;
1917
1918   systrust_mode = has_option (line, "--systrust");
1919   tls_mode = has_option (line, "--tls");
1920   no_crl = has_option (line, "--no-crl");
1921   line = skip_options (line);
1922
1923   if (tls_mode)
1924     err = assuan_inquire (ctrl->server_local->assuan_ctx, "CERTLIST",
1925                           &value, &valuelen, MAX_CERTLIST_LENGTH);
1926   else
1927     err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1928                           &value, &valuelen, MAX_CERT_LENGTH);
1929   if (err)
1930     {
1931       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1932       goto leave;
1933     }
1934
1935   if (!valuelen) /* No data returned; return a comprehensible error. */
1936     err = gpg_error (GPG_ERR_MISSING_CERT);
1937   else if (tls_mode)
1938     {
1939       estream_t fp;
1940
1941       fp = es_fopenmem_init (0, "rb", value, valuelen);
1942       if (!fp)
1943         err = gpg_error_from_syserror ();
1944       else
1945         {
1946           err = read_certlist_from_stream (&certlist, fp);
1947           es_fclose (fp);
1948           if (!err && !certlist)
1949             err = gpg_error (GPG_ERR_MISSING_CERT);
1950           if (!err)
1951             {
1952               /* Extract the first certificate from the list.  */
1953               cert = certlist->cert;
1954               ksba_cert_ref (cert);
1955             }
1956         }
1957     }
1958   else
1959     {
1960       err = ksba_cert_new (&cert);
1961       if (!err)
1962         err = ksba_cert_init_from_mem (cert, value, valuelen);
1963     }
1964   xfree (value);
1965   if(err)
1966     goto leave;
1967
1968   if (!tls_mode)
1969     {
1970       /* If we have this certificate already in our cache, use the
1971        * cached version for validation because this will take care of
1972        * any cached results.  We don't need to do this in tls mode
1973        * because this has already been done for certificate in a
1974        * certlist_t. */
1975       unsigned char fpr[20];
1976       ksba_cert_t tmpcert;
1977
1978       cert_compute_fpr (cert, fpr);
1979       tmpcert = get_cert_byfpr (fpr);
1980       if (tmpcert)
1981         {
1982           ksba_cert_release (cert);
1983           cert = tmpcert;
1984         }
1985     }
1986
1987   /* Quick hack to make verification work by inserting the supplied
1988    * certs into the cache.  */
1989   if (tls_mode && certlist)
1990     {
1991       certlist_t cl;
1992
1993       for (cl = certlist->next; cl; cl = cl->next)
1994         cache_cert (cl->cert);
1995     }
1996
1997   err = validate_cert_chain (ctrl, cert, NULL,
1998                              (VALIDATE_FLAG_TRUST_CONFIG
1999                               | (tls_mode ? VALIDATE_FLAG_TLS : 0)
2000                               | (systrust_mode ? VALIDATE_FLAG_TRUST_SYSTEM : 0)
2001                               | (no_crl ? VALIDATE_FLAG_NOCRLCHECK : 0)),
2002                              NULL);
2003
2004  leave:
2005   ksba_cert_release (cert);
2006   release_certlist (certlist);
2007   return leave_cmd (ctx, err);
2008 }
2009
2010
2011 \f
2012 /* Parse an keyserver URI and store it in a new uri item which is
2013    returned at R_ITEM.  On error return an error code.  */
2014 static gpg_error_t
2015 make_keyserver_item (const char *uri, uri_item_t *r_item)
2016 {
2017   gpg_error_t err;
2018   uri_item_t item;
2019
2020   *r_item = NULL;
2021
2022   /* We used to have DNS CNAME redirection from the URLs below to
2023    * sks-keyserver. pools.  The idea was to allow for a quick way to
2024    * switch to a different set of pools.  The problem with that
2025    * approach is that TLS needs to verify the hostname and - because
2026    * DNS is not secured - it can only check the user supplied hostname
2027    * and not a hostname from a CNAME RR.  Thus the final server all
2028    * need to have certificates with the actual pool name as well as
2029    * for keys.gnupg.net - that would render the advantage of
2030    * keys.gnupg.net useless and so we better give up on this.  Because
2031    * the keys.gnupg.net URL are still in widespread use we do a static
2032    * mapping here.
2033    */
2034   if (!strcmp (uri, "hkps://keys.gnupg.net")
2035       || !strcmp (uri, "keys.gnupg.net"))
2036     uri = "hkps://hkps.pool.sks-keyservers.net";
2037   else if (!strcmp (uri, "https://keys.gnupg.net"))
2038     uri = "https://hkps.pool.sks-keyservers.net";
2039   else if (!strcmp (uri, "hkp://keys.gnupg.net"))
2040     uri = "hkp://hkps.pool.sks-keyservers.net";
2041   else if (!strcmp (uri, "http://keys.gnupg.net"))
2042     uri = "http://hkps.pool.sks-keyservers.net";
2043   else if (!strcmp (uri, "hkps://http-keys.gnupg.net")
2044            || !strcmp (uri, "http-keys.gnupg.net"))
2045     uri = "hkps://ha.pool.sks-keyservers.net";
2046   else if (!strcmp (uri, "https://http-keys.gnupg.net"))
2047     uri = "https://ha.pool.sks-keyservers.net";
2048   else if (!strcmp (uri, "hkp://http-keys.gnupg.net"))
2049     uri = "hkp://ha.pool.sks-keyservers.net";
2050   else if (!strcmp (uri, "http://http-keys.gnupg.net"))
2051     uri = "http://ha.pool.sks-keyservers.net";
2052
2053   item = xtrymalloc (sizeof *item + strlen (uri));
2054   if (!item)
2055     return gpg_error_from_syserror ();
2056
2057   item->next = NULL;
2058   item->parsed_uri = NULL;
2059   strcpy (item->uri, uri);
2060
2061 #if USE_LDAP
2062   if (ldap_uri_p (item->uri))
2063     err = ldap_parse_uri (&item->parsed_uri, uri);
2064   else
2065 #endif
2066     {
2067       err = http_parse_uri (&item->parsed_uri, uri, 1);
2068     }
2069
2070   if (err)
2071     xfree (item);
2072   else
2073     *r_item = item;
2074   return err;
2075 }
2076
2077
2078 /* If no keyserver is stored in CTRL but a global keyserver has been
2079    set, put that global keyserver into CTRL.  We need use this
2080    function to help migrate from the old gpg based keyserver
2081    configuration to the new dirmngr based configuration.  */
2082 static gpg_error_t
2083 ensure_keyserver (ctrl_t ctrl)
2084 {
2085   gpg_error_t err;
2086   uri_item_t item;
2087   uri_item_t onion_items = NULL;
2088   uri_item_t plain_items = NULL;
2089   uri_item_t ui;
2090   strlist_t sl;
2091
2092   if (ctrl->server_local->keyservers)
2093     return 0; /* Already set for this session.  */
2094   if (!opt.keyserver)
2095     {
2096       /* No global option set.  Fall back to default:  */
2097       return make_keyserver_item (DIRMNGR_DEFAULT_KEYSERVER,
2098                                   &ctrl->server_local->keyservers);
2099     }
2100
2101   for (sl = opt.keyserver; sl; sl = sl->next)
2102     {
2103       err = make_keyserver_item (sl->d, &item);
2104       if (err)
2105         goto leave;
2106       if (item->parsed_uri->onion)
2107         {
2108           item->next = onion_items;
2109           onion_items = item;
2110         }
2111       else
2112         {
2113           item->next = plain_items;
2114           plain_items = item;
2115         }
2116     }
2117
2118   /* Decide which to use.  Note that the session has no keyservers
2119      yet set. */
2120   if (onion_items && !onion_items->next && plain_items && !plain_items->next)
2121     {
2122       /* If there is just one onion and one plain keyserver given, we take
2123          only one depending on whether Tor is running or not.  */
2124       if (is_tor_running (ctrl))
2125         {
2126           ctrl->server_local->keyservers = onion_items;
2127           onion_items = NULL;
2128         }
2129       else
2130         {
2131           ctrl->server_local->keyservers = plain_items;
2132           plain_items = NULL;
2133         }
2134     }
2135   else if (!is_tor_running (ctrl))
2136     {
2137       /* Tor is not running.  It does not make sense to add Onion
2138          addresses.  */
2139       ctrl->server_local->keyservers = plain_items;
2140       plain_items = NULL;
2141     }
2142   else
2143     {
2144       /* In all other cases add all keyservers.  */
2145       ctrl->server_local->keyservers = onion_items;
2146       onion_items = NULL;
2147       for (ui = ctrl->server_local->keyservers; ui && ui->next; ui = ui->next)
2148         ;
2149       if (ui)
2150         ui->next = plain_items;
2151       else
2152         ctrl->server_local->keyservers = plain_items;
2153       plain_items = NULL;
2154     }
2155
2156  leave:
2157   release_uri_item_list (onion_items);
2158   release_uri_item_list (plain_items);
2159
2160   return err;
2161 }
2162
2163
2164 static const char hlp_keyserver[] =
2165   "KEYSERVER [<options>] [<uri>|<host>]\n"
2166   "Options are:\n"
2167   "  --help\n"
2168   "  --clear      Remove all configured keyservers\n"
2169   "  --resolve    Resolve HKP host names and rotate\n"
2170   "  --hosttable  Print table of known hosts and pools\n"
2171   "  --dead       Mark <host> as dead\n"
2172   "  --alive      Mark <host> as alive\n"
2173   "\n"
2174   "If called without arguments list all configured keyserver URLs.\n"
2175   "If called with an URI add this as keyserver.  Note that keyservers\n"
2176   "are configured on a per-session base.  A default keyserver may already be\n"
2177   "present, thus the \"--clear\" option must be used to get full control.\n"
2178   "If \"--clear\" and an URI are used together the clear command is\n"
2179   "obviously executed first.  A RESET command does not change the list\n"
2180   "of configured keyservers.";
2181 static gpg_error_t
2182 cmd_keyserver (assuan_context_t ctx, char *line)
2183 {
2184   ctrl_t ctrl = assuan_get_pointer (ctx);
2185   gpg_error_t err = 0;
2186   int clear_flag, add_flag, help_flag, host_flag, resolve_flag;
2187   int dead_flag, alive_flag;
2188   uri_item_t item = NULL; /* gcc 4.4.5 is not able to detect that it
2189                              is always initialized.  */
2190
2191   clear_flag = has_option (line, "--clear");
2192   help_flag = has_option (line, "--help");
2193   resolve_flag = has_option (line, "--resolve");
2194   host_flag = has_option (line, "--hosttable");
2195   dead_flag = has_option (line, "--dead");
2196   alive_flag = has_option (line, "--alive");
2197   line = skip_options (line);
2198   add_flag = !!*line;
2199
2200   if (help_flag)
2201     {
2202       err = ks_action_help (ctrl, line);
2203       goto leave;
2204     }
2205
2206   if (resolve_flag)
2207     {
2208       err = ensure_keyserver (ctrl);
2209       if (err)
2210         {
2211           assuan_set_error (ctx, err,
2212                             "Bad keyserver configuration in dirmngr.conf");
2213           goto leave;
2214         }
2215       err = ks_action_resolve (ctrl, ctrl->server_local->keyservers);
2216       if (err)
2217         goto leave;
2218     }
2219
2220   if (alive_flag && dead_flag)
2221     {
2222       err = set_error (GPG_ERR_ASS_PARAMETER, "no support for zombies");
2223       goto leave;
2224     }
2225   if (dead_flag)
2226     {
2227       err = check_owner_permission (ctx, "no permission to use --dead");
2228       if (err)
2229         goto leave;
2230     }
2231   if (alive_flag || dead_flag)
2232     {
2233       if (!*line)
2234         {
2235           err = set_error (GPG_ERR_ASS_PARAMETER, "name of host missing");
2236           goto leave;
2237         }
2238
2239       err = ks_hkp_mark_host (ctrl, line, alive_flag);
2240       if (err)
2241         goto leave;
2242     }
2243
2244   if (host_flag)
2245     {
2246       err = ks_hkp_print_hosttable (ctrl);
2247       if (err)
2248         goto leave;
2249     }
2250   if (resolve_flag || host_flag || alive_flag || dead_flag)
2251     goto leave;
2252
2253   if (add_flag)
2254     {
2255       err = make_keyserver_item (line, &item);
2256       if (err)
2257         goto leave;
2258     }
2259   if (clear_flag)
2260     release_ctrl_keyservers (ctrl);
2261   if (add_flag)
2262     {
2263       item->next = ctrl->server_local->keyservers;
2264       ctrl->server_local->keyservers = item;
2265     }
2266
2267   if (!add_flag && !clear_flag && !help_flag)
2268     {
2269       /* List configured keyservers.  However, we first add a global
2270          keyserver. */
2271       uri_item_t u;
2272
2273       err = ensure_keyserver (ctrl);
2274       if (err)
2275         {
2276           assuan_set_error (ctx, err,
2277                             "Bad keyserver configuration in dirmngr.conf");
2278           goto leave;
2279         }
2280
2281       for (u=ctrl->server_local->keyservers; u; u = u->next)
2282         dirmngr_status (ctrl, "KEYSERVER", u->uri, NULL);
2283     }
2284   err = 0;
2285
2286  leave:
2287   return leave_cmd (ctx, err);
2288 }
2289
2290
2291 \f
2292 static const char hlp_ks_search[] =
2293   "KS_SEARCH {<pattern>}\n"
2294   "\n"
2295   "Search the configured OpenPGP keyservers (see command KEYSERVER)\n"
2296   "for keys matching PATTERN";
2297 static gpg_error_t
2298 cmd_ks_search (assuan_context_t ctx, char *line)
2299 {
2300   ctrl_t ctrl = assuan_get_pointer (ctx);
2301   gpg_error_t err;
2302   strlist_t list, sl;
2303   char *p;
2304   estream_t outfp;
2305
2306   if (has_option (line, "--quick"))
2307     ctrl->timeout = opt.connect_quick_timeout;
2308   line = skip_options (line);
2309
2310   /* Break the line down into an strlist.  Each pattern is
2311      percent-plus escaped. */
2312   list = NULL;
2313   for (p=line; *p; line = p)
2314     {
2315       while (*p && *p != ' ')
2316         p++;
2317       if (*p)
2318         *p++ = 0;
2319       if (*line)
2320         {
2321           sl = xtrymalloc (sizeof *sl + strlen (line));
2322           if (!sl)
2323             {
2324               err = gpg_error_from_syserror ();
2325               goto leave;
2326             }
2327           sl->flags = 0;
2328           strcpy_escaped_plus (sl->d, line);
2329           sl->next = list;
2330           list = sl;
2331         }
2332     }
2333
2334   err = ensure_keyserver (ctrl);
2335   if (err)
2336     goto leave;
2337
2338   /* Setup an output stream and perform the search.  */
2339   outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
2340   if (!outfp)
2341     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
2342   else
2343     {
2344       err = ks_action_search (ctrl, ctrl->server_local->keyservers,
2345                               list, outfp);
2346       es_fclose (outfp);
2347     }
2348
2349  leave:
2350   free_strlist (list);
2351   return leave_cmd (ctx, err);
2352 }
2353
2354
2355 \f
2356 static const char hlp_ks_get[] =
2357   "KS_GET {<pattern>}\n"
2358   "\n"
2359   "Get the keys matching PATTERN from the configured OpenPGP keyservers\n"
2360   "(see command KEYSERVER).  Each pattern should be a keyid, a fingerprint,\n"
2361   "or an exact name indicated by the '=' prefix.";
2362 static gpg_error_t
2363 cmd_ks_get (assuan_context_t ctx, char *line)
2364 {
2365   ctrl_t ctrl = assuan_get_pointer (ctx);
2366   gpg_error_t err;
2367   strlist_t list, sl;
2368   char *p;
2369   estream_t outfp;
2370
2371   if (has_option (line, "--quick"))
2372     ctrl->timeout = opt.connect_quick_timeout;
2373   line = skip_options (line);
2374
2375   /* Break the line into a strlist.  Each pattern is by
2376      definition percent-plus escaped.  However we only support keyids
2377      and fingerprints and thus the client has no need to apply the
2378      escaping.  */
2379   list = NULL;
2380   for (p=line; *p; line = p)
2381     {
2382       while (*p && *p != ' ')
2383         p++;
2384       if (*p)
2385         *p++ = 0;
2386       if (*line)
2387         {
2388           sl = xtrymalloc (sizeof *sl + strlen (line));
2389           if (!sl)
2390             {
2391               err = gpg_error_from_syserror ();
2392               goto leave;
2393             }
2394           sl->flags = 0;
2395           strcpy_escaped_plus (sl->d, line);
2396           sl->next = list;
2397           list = sl;
2398         }
2399     }
2400
2401   err = ensure_keyserver (ctrl);
2402   if (err)
2403     goto leave;
2404
2405   /* Setup an output stream and perform the get.  */
2406   outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
2407   if (!outfp)
2408     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
2409   else
2410     {
2411       ctrl->server_local->inhibit_data_logging = 1;
2412       ctrl->server_local->inhibit_data_logging_now = 0;
2413       ctrl->server_local->inhibit_data_logging_count = 0;
2414       err = ks_action_get (ctrl, ctrl->server_local->keyservers, list, outfp);
2415       es_fclose (outfp);
2416       ctrl->server_local->inhibit_data_logging = 0;
2417     }
2418
2419  leave:
2420   free_strlist (list);
2421   return leave_cmd (ctx, err);
2422 }
2423
2424
2425 static const char hlp_ks_fetch[] =
2426   "KS_FETCH <URL>\n"
2427   "\n"
2428   "Get the key(s) from URL.";
2429 static gpg_error_t
2430 cmd_ks_fetch (assuan_context_t ctx, char *line)
2431 {
2432   ctrl_t ctrl = assuan_get_pointer (ctx);
2433   gpg_error_t err;
2434   estream_t outfp;
2435
2436   if (has_option (line, "--quick"))
2437     ctrl->timeout = opt.connect_quick_timeout;
2438   line = skip_options (line);
2439
2440   err = ensure_keyserver (ctrl);  /* FIXME: Why do we needs this here?  */
2441   if (err)
2442     goto leave;
2443
2444   /* Setup an output stream and perform the get.  */
2445   outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
2446   if (!outfp)
2447     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
2448   else
2449     {
2450       ctrl->server_local->inhibit_data_logging = 1;
2451       ctrl->server_local->inhibit_data_logging_now = 0;
2452       ctrl->server_local->inhibit_data_logging_count = 0;
2453       err = ks_action_fetch (ctrl, line, outfp);
2454       es_fclose (outfp);
2455       ctrl->server_local->inhibit_data_logging = 0;
2456     }
2457
2458  leave:
2459   return leave_cmd (ctx, err);
2460 }
2461
2462
2463 \f
2464 static const char hlp_ks_put[] =
2465   "KS_PUT\n"
2466   "\n"
2467   "Send a key to the configured OpenPGP keyservers.  The actual key material\n"
2468   "is then requested by Dirmngr using\n"
2469   "\n"
2470   "  INQUIRE KEYBLOCK\n"
2471   "\n"
2472   "The client shall respond with a binary version of the keyblock (e.g.,\n"
2473   "the output of `gpg --export KEYID').  For LDAP\n"
2474   "keyservers Dirmngr may ask for meta information of the provided keyblock\n"
2475   "using:\n"
2476   "\n"
2477   "  INQUIRE KEYBLOCK_INFO\n"
2478   "\n"
2479   "The client shall respond with a colon delimited info lines (the output\n"
2480   "of 'for x in keys sigs; do gpg --list-$x --with-colons KEYID; done').\n";
2481 static gpg_error_t
2482 cmd_ks_put (assuan_context_t ctx, char *line)
2483 {
2484   ctrl_t ctrl = assuan_get_pointer (ctx);
2485   gpg_error_t err;
2486   unsigned char *value = NULL;
2487   size_t valuelen;
2488   unsigned char *info = NULL;
2489   size_t infolen;
2490
2491   /* No options for now.  */
2492   line = skip_options (line);
2493
2494   err = ensure_keyserver (ctrl);
2495   if (err)
2496     goto leave;
2497
2498   /* Ask for the key material.  */
2499   err = assuan_inquire (ctx, "KEYBLOCK",
2500                         &value, &valuelen, MAX_KEYBLOCK_LENGTH);
2501   if (err)
2502     {
2503       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
2504       goto leave;
2505     }
2506
2507   if (!valuelen) /* No data returned; return a comprehensible error. */
2508     {
2509       err = gpg_error (GPG_ERR_MISSING_CERT);
2510       goto leave;
2511     }
2512
2513   /* Ask for the key meta data. Not actually needed for HKP servers
2514      but we do it anyway to test the client implementation.  */
2515   err = assuan_inquire (ctx, "KEYBLOCK_INFO",
2516                         &info, &infolen, MAX_KEYBLOCK_LENGTH);
2517   if (err)
2518     {
2519       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
2520       goto leave;
2521     }
2522
2523   /* Send the key.  */
2524   err = ks_action_put (ctrl, ctrl->server_local->keyservers,
2525                        value, valuelen, info, infolen);
2526
2527  leave:
2528   xfree (info);
2529   xfree (value);
2530   return leave_cmd (ctx, err);
2531 }
2532
2533
2534 \f
2535 static const char hlp_loadswdb[] =
2536   "LOADSWDB [--force]\n"
2537   "\n"
2538   "Load and verify the swdb.lst from the Net.";
2539 static gpg_error_t
2540 cmd_loadswdb (assuan_context_t ctx, char *line)
2541 {
2542   ctrl_t ctrl = assuan_get_pointer (ctx);
2543   gpg_error_t err;
2544
2545   err = dirmngr_load_swdb (ctrl, has_option (line, "--force"));
2546
2547   return leave_cmd (ctx, err);
2548 }
2549
2550
2551 \f
2552 static const char hlp_getinfo[] =
2553   "GETINFO <what>\n"
2554   "\n"
2555   "Multi purpose command to return certain information.  \n"
2556   "Supported values of WHAT are:\n"
2557   "\n"
2558   "version     - Return the version of the program.\n"
2559   "pid         - Return the process id of the server.\n"
2560   "tor         - Return OK if running in Tor mode\n"
2561   "dnsinfo     - Return info about the DNS resolver\n"
2562   "socket_name - Return the name of the socket.\n"
2563   "session_id  - Return the current session_id.\n"
2564   "workqueue   - Inspect the work queue\n"
2565   "getenv NAME - Return value of envvar NAME\n";
2566 static gpg_error_t
2567 cmd_getinfo (assuan_context_t ctx, char *line)
2568 {
2569   ctrl_t ctrl = assuan_get_pointer (ctx);
2570   gpg_error_t err;
2571   char numbuf[50];
2572
2573   if (!strcmp (line, "version"))
2574     {
2575       const char *s = VERSION;
2576       err = assuan_send_data (ctx, s, strlen (s));
2577     }
2578   else if (!strcmp (line, "pid"))
2579     {
2580       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
2581       err = assuan_send_data (ctx, numbuf, strlen (numbuf));
2582     }
2583   else if (!strcmp (line, "socket_name"))
2584     {
2585       const char *s = dirmngr_get_current_socket_name ();
2586       err = assuan_send_data (ctx, s, strlen (s));
2587     }
2588   else if (!strcmp (line, "session_id"))
2589     {
2590       snprintf (numbuf, sizeof numbuf, "%u", ctrl->server_local->session_id);
2591       err = assuan_send_data (ctx, numbuf, strlen (numbuf));
2592     }
2593   else if (!strcmp (line, "tor"))
2594     {
2595       int use_tor;
2596
2597       use_tor = dirmngr_use_tor ();
2598       if (use_tor)
2599         {
2600           if (!is_tor_running (ctrl))
2601             err = assuan_write_status (ctx, "NO_TOR", "Tor not running");
2602           else
2603             err = 0;
2604           if (!err)
2605             assuan_set_okay_line (ctx, use_tor == 1 ? "- Tor mode is enabled"
2606                                   /**/              : "- Tor mode is enforced");
2607         }
2608       else
2609         err = set_error (GPG_ERR_FALSE, "Tor mode is NOT enabled");
2610     }
2611   else if (!strcmp (line, "dnsinfo"))
2612     {
2613       if (standard_resolver_p ())
2614         assuan_set_okay_line
2615           (ctx, "- Forced use of System resolver (w/o Tor support)");
2616       else
2617         {
2618 #ifdef USE_LIBDNS
2619           assuan_set_okay_line (ctx, (recursive_resolver_p ()
2620                                       ? "- Libdns recursive resolver"
2621                                       : "- Libdns stub resolver"));
2622 #else
2623           assuan_set_okay_line (ctx, "- System resolver (w/o Tor support)");
2624 #endif
2625         }
2626       err = 0;
2627     }
2628   else if (!strcmp (line, "workqueue"))
2629     {
2630       workqueue_dump_queue (ctrl);
2631       err = 0;
2632     }
2633   else if (!strncmp (line, "getenv", 6)
2634            && (line[6] == ' ' || line[6] == '\t' || !line[6]))
2635     {
2636       line += 6;
2637       while (*line == ' ' || *line == '\t')
2638         line++;
2639       if (!*line)
2640         err = gpg_error (GPG_ERR_MISSING_VALUE);
2641       else
2642         {
2643           const char *s = getenv (line);
2644           if (!s)
2645             err = set_error (GPG_ERR_NOT_FOUND, "No such envvar");
2646           else
2647             err = assuan_send_data (ctx, s, strlen (s));
2648         }
2649     }
2650   else
2651     err = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
2652
2653   return leave_cmd (ctx, err);
2654 }
2655
2656
2657 \f
2658 static const char hlp_killdirmngr[] =
2659   "KILLDIRMNGR\n"
2660   "\n"
2661   "This command allows a user - given sufficient permissions -\n"
2662   "to kill this dirmngr process.\n";
2663 static gpg_error_t
2664 cmd_killdirmngr (assuan_context_t ctx, char *line)
2665 {
2666   ctrl_t ctrl = assuan_get_pointer (ctx);
2667
2668   (void)line;
2669
2670   ctrl->server_local->stopme = 1;
2671   assuan_set_flag (ctx, ASSUAN_FORCE_CLOSE, 1);
2672   return gpg_error (GPG_ERR_EOF);
2673 }
2674
2675
2676 static const char hlp_reloaddirmngr[] =
2677   "RELOADDIRMNGR\n"
2678   "\n"
2679   "This command is an alternative to SIGHUP\n"
2680   "to reload the configuration.";
2681 static gpg_error_t
2682 cmd_reloaddirmngr (assuan_context_t ctx, char *line)
2683 {
2684   (void)ctx;
2685   (void)line;
2686
2687   dirmngr_sighup_action ();
2688   return 0;
2689 }
2690
2691
2692 \f
2693 /* Tell the assuan library about our commands. */
2694 static int
2695 register_commands (assuan_context_t ctx)
2696 {
2697   static struct {
2698     const char *name;
2699     assuan_handler_t handler;
2700     const char * const help;
2701   } table[] = {
2702     { "DNS_CERT",   cmd_dns_cert,   hlp_dns_cert },
2703     { "WKD_GET",    cmd_wkd_get,    hlp_wkd_get },
2704     { "LDAPSERVER", cmd_ldapserver, hlp_ldapserver },
2705     { "ISVALID",    cmd_isvalid,    hlp_isvalid },
2706     { "CHECKCRL",   cmd_checkcrl,   hlp_checkcrl },
2707     { "CHECKOCSP",  cmd_checkocsp,  hlp_checkocsp },
2708     { "LOOKUP",     cmd_lookup,     hlp_lookup },
2709     { "LOADCRL",    cmd_loadcrl,    hlp_loadcrl },
2710     { "LISTCRLS",   cmd_listcrls,   hlp_listcrls },
2711     { "CACHECERT",  cmd_cachecert,  hlp_cachecert },
2712     { "VALIDATE",   cmd_validate,   hlp_validate },
2713     { "KEYSERVER",  cmd_keyserver,  hlp_keyserver },
2714     { "KS_SEARCH",  cmd_ks_search,  hlp_ks_search },
2715     { "KS_GET",     cmd_ks_get,     hlp_ks_get },
2716     { "KS_FETCH",   cmd_ks_fetch,   hlp_ks_fetch },
2717     { "KS_PUT",     cmd_ks_put,     hlp_ks_put },
2718     { "GETINFO",    cmd_getinfo,    hlp_getinfo },
2719     { "LOADSWDB",   cmd_loadswdb,   hlp_loadswdb },
2720     { "KILLDIRMNGR",cmd_killdirmngr,hlp_killdirmngr },
2721     { "RELOADDIRMNGR",cmd_reloaddirmngr,hlp_reloaddirmngr },
2722     { NULL, NULL }
2723   };
2724   int i, j, rc;
2725
2726   for (i=j=0; table[i].name; i++)
2727     {
2728       rc = assuan_register_command (ctx, table[i].name, table[i].handler,
2729                                     table[i].help);
2730       if (rc)
2731         return rc;
2732     }
2733   return 0;
2734 }
2735
2736
2737 /* Note that we do not reset the list of configured keyservers.  */
2738 static gpg_error_t
2739 reset_notify (assuan_context_t ctx, char *line)
2740 {
2741   ctrl_t ctrl = assuan_get_pointer (ctx);
2742   (void)line;
2743
2744 #if USE_LDAP
2745   ldapserver_list_free (ctrl->server_local->ldapservers);
2746 #endif /*USE_LDAP*/
2747   ctrl->server_local->ldapservers = NULL;
2748   return 0;
2749 }
2750
2751
2752 /* This function is called by our assuan log handler to test whether a
2753  * log message shall really be printed.  The function must return
2754  * false to inhibit the logging of MSG.  CAT gives the requested log
2755  * category.  MSG might be NULL. */
2756 int
2757 dirmngr_assuan_log_monitor (assuan_context_t ctx, unsigned int cat,
2758                             const char *msg)
2759 {
2760   ctrl_t ctrl = assuan_get_pointer (ctx);
2761
2762   (void)cat;
2763   (void)msg;
2764
2765   if (!ctrl || !ctrl->server_local)
2766     return 1; /* Can't decide - allow logging.  */
2767
2768   if (!ctrl->server_local->inhibit_data_logging)
2769     return 1; /* Not requested - allow logging.  */
2770
2771   /* Disallow logging if *_now is true.  */
2772   return !ctrl->server_local->inhibit_data_logging_now;
2773 }
2774
2775
2776 /* Startup the server and run the main command loop.  With FD = -1,
2777  * use stdin/stdout.  SESSION_ID is either 0 or a unique number
2778  * identifying a session.  */
2779 void
2780 start_command_handler (assuan_fd_t fd, unsigned int session_id)
2781 {
2782   static const char hello[] = "Dirmngr " VERSION " at your service";
2783   static char *hello_line;
2784   int rc;
2785   assuan_context_t ctx;
2786   ctrl_t ctrl;
2787
2788   ctrl = xtrycalloc (1, sizeof *ctrl);
2789   if (ctrl)
2790     ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
2791   if (!ctrl || !ctrl->server_local)
2792     {
2793       log_error (_("can't allocate control structure: %s\n"),
2794                  strerror (errno));
2795       xfree (ctrl);
2796       return;
2797     }
2798
2799   dirmngr_init_default_ctrl (ctrl);
2800
2801   rc = assuan_new (&ctx);
2802   if (rc)
2803     {
2804       log_error (_("failed to allocate assuan context: %s\n"),
2805                  gpg_strerror (rc));
2806       dirmngr_exit (2);
2807     }
2808
2809   if (fd == ASSUAN_INVALID_FD)
2810     {
2811       assuan_fd_t filedes[2];
2812
2813       filedes[0] = assuan_fdopen (0);
2814       filedes[1] = assuan_fdopen (1);
2815       rc = assuan_init_pipe_server (ctx, filedes);
2816     }
2817   else
2818     {
2819       rc = assuan_init_socket_server (ctx, fd, ASSUAN_SOCKET_SERVER_ACCEPTED);
2820     }
2821
2822   if (rc)
2823     {
2824       assuan_release (ctx);
2825       log_error (_("failed to initialize the server: %s\n"),
2826                  gpg_strerror(rc));
2827       dirmngr_exit (2);
2828     }
2829
2830   rc = register_commands (ctx);
2831   if (rc)
2832     {
2833       log_error (_("failed to the register commands with Assuan: %s\n"),
2834                  gpg_strerror(rc));
2835       dirmngr_exit (2);
2836     }
2837
2838
2839   if (!hello_line)
2840     {
2841       hello_line = xtryasprintf
2842         ("Home: %s\n"
2843          "Config: %s\n"
2844          "%s",
2845          gnupg_homedir (),
2846          opt.config_filename? opt.config_filename : "[none]",
2847          hello);
2848     }
2849
2850   ctrl->server_local->assuan_ctx = ctx;
2851   assuan_set_pointer (ctx, ctrl);
2852
2853   assuan_set_hello_line (ctx, hello_line);
2854   assuan_register_option_handler (ctx, option_handler);
2855   assuan_register_reset_notify (ctx, reset_notify);
2856
2857   ctrl->server_local->session_id = session_id;
2858
2859   for (;;)
2860     {
2861       rc = assuan_accept (ctx);
2862       if (rc == -1)
2863         break;
2864       if (rc)
2865         {
2866           log_info (_("Assuan accept problem: %s\n"), gpg_strerror (rc));
2867           break;
2868         }
2869
2870 #ifndef HAVE_W32_SYSTEM
2871       if (opt.verbose)
2872         {
2873           assuan_peercred_t peercred;
2874
2875           if (!assuan_get_peercred (ctx, &peercred))
2876             log_info ("connection from process %ld (%ld:%ld)\n",
2877                       (long)peercred->pid, (long)peercred->uid,
2878                       (long)peercred->gid);
2879         }
2880 #endif
2881
2882       rc = assuan_process (ctx);
2883       if (rc)
2884         {
2885           log_info (_("Assuan processing failed: %s\n"), gpg_strerror (rc));
2886           continue;
2887         }
2888     }
2889
2890
2891 #if USE_LDAP
2892   ldap_wrapper_connection_cleanup (ctrl);
2893
2894   ldapserver_list_free (ctrl->server_local->ldapservers);
2895 #endif /*USE_LDAP*/
2896   ctrl->server_local->ldapservers = NULL;
2897
2898   release_ctrl_keyservers (ctrl);
2899
2900   ctrl->server_local->assuan_ctx = NULL;
2901   assuan_release (ctx);
2902
2903   if (ctrl->server_local->stopme)
2904     dirmngr_exit (0);
2905
2906   if (ctrl->refcount)
2907     log_error ("oops: connection control structure still referenced (%d)\n",
2908                ctrl->refcount);
2909   else
2910     {
2911       release_ctrl_ocsp_certs (ctrl);
2912       xfree (ctrl->server_local);
2913       dirmngr_deinit_default_ctrl (ctrl);
2914       xfree (ctrl);
2915     }
2916 }
2917
2918
2919 /* Send a status line back to the client.  KEYWORD is the status
2920    keyword, the optional string arguments are blank separated added to
2921    the line, the last argument must be a NULL. */
2922 gpg_error_t
2923 dirmngr_status (ctrl_t ctrl, const char *keyword, ...)
2924 {
2925   gpg_error_t err = 0;
2926   va_list arg_ptr;
2927   assuan_context_t ctx;
2928
2929   va_start (arg_ptr, keyword);
2930
2931   if (ctrl->server_local && (ctx = ctrl->server_local->assuan_ctx))
2932     {
2933       err = vprint_assuan_status_strings (ctx, keyword, arg_ptr);
2934     }
2935
2936   va_end (arg_ptr);
2937   return err;
2938 }
2939
2940
2941 /* Print a help status line.  The function splits text at LFs.  */
2942 gpg_error_t
2943 dirmngr_status_help (ctrl_t ctrl, const char *text)
2944 {
2945   gpg_error_t err = 0;
2946   assuan_context_t ctx;
2947
2948   if (ctrl->server_local && (ctx = ctrl->server_local->assuan_ctx))
2949     {
2950       char buf[950], *p;
2951       size_t n;
2952
2953       do
2954         {
2955           p = buf;
2956           n = 0;
2957           for ( ; *text && *text != '\n' && n < DIM (buf)-2; n++)
2958             *p++ = *text++;
2959           if (*text == '\n')
2960             text++;
2961           *p = 0;
2962           err = assuan_write_status (ctx, "#", buf);
2963         }
2964       while (!err && *text);
2965     }
2966
2967   return err;
2968 }
2969
2970
2971 /* Print a help status line using a printf like format.  The function
2972  * splits text at LFs.  */
2973 gpg_error_t
2974 dirmngr_status_helpf (ctrl_t ctrl, const char *format, ...)
2975 {
2976   va_list arg_ptr;
2977   gpg_error_t err;
2978   char *buf;
2979
2980   va_start (arg_ptr, format);
2981   buf = es_vbsprintf (format, arg_ptr);
2982   err = buf? 0 : gpg_error_from_syserror ();
2983   va_end (arg_ptr);
2984   if (!err)
2985     err = dirmngr_status_help (ctrl, buf);
2986   es_free (buf);
2987   return err;
2988 }
2989
2990
2991 /* This function is similar to print_assuan_status but takes a CTRL
2992  * arg instead of an assuan context as first argument.  */
2993 gpg_error_t
2994 dirmngr_status_printf (ctrl_t ctrl, const char *keyword,
2995                        const char *format, ...)
2996 {
2997   gpg_error_t err;
2998   va_list arg_ptr;
2999   assuan_context_t ctx;
3000
3001   if (!ctrl || !ctrl->server_local || !(ctx = ctrl->server_local->assuan_ctx))
3002     return 0;
3003
3004   va_start (arg_ptr, format);
3005   err = vprint_assuan_status (ctx, keyword, format, arg_ptr);
3006   va_end (arg_ptr);
3007   return err;
3008 }
3009
3010
3011 /* Send a tick progress indicator back.  Fixme: This is only done for
3012    the currently active channel.  */
3013 gpg_error_t
3014 dirmngr_tick (ctrl_t ctrl)
3015 {
3016   static time_t next_tick = 0;
3017   gpg_error_t err = 0;
3018   time_t now = time (NULL);
3019
3020   if (!next_tick)
3021     {
3022       next_tick = now + 1;
3023     }
3024   else if ( now > next_tick )
3025     {
3026       if (ctrl)
3027         {
3028           err = dirmngr_status (ctrl, "PROGRESS", "tick", "? 0 0", NULL);
3029           if (err)
3030             {
3031               /* Take this as in indication for a cancel request.  */
3032               err = gpg_error (GPG_ERR_CANCELED);
3033             }
3034           now = time (NULL);
3035         }
3036
3037       next_tick = now + 1;
3038     }
3039   return err;
3040 }