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