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