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