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