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