dirmngr: Allow sending much larger keyblocks.
[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 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-cert.h"
54 #include "mbox-util.h"
55
56 /* To avoid DoS attacks we limit the size of a certificate to
57    something reasonable.  The DoS was actually only an issue back when
58    Dirmngr was a system service and not a user service. */
59 #define MAX_CERT_LENGTH (16*1024)
60
61 /* The same goes for OpenPGP keyblocks, but here we need to allow for
62    much longer blocks; a 200k keyblock is not too unusual for keys
63    with a lot of signatures (e.g. 0x5b0358a2).  9C31503C6D866396 even
64    has 770 KiB as of 2015-08-23.  To avoid adding a runtime option we
65    now use 20MiB which should really be enough.  Well, a key with
66    several pictures could be larger (the parser as a 18MiB limit for
67    attribute packets) but it won't be nice to the keyservers to send
68    them such large blobs.  */
69 #define MAX_KEYBLOCK_LENGTH (20*1024*1024)
70
71
72 #define PARM_ERROR(t) assuan_set_error (ctx, \
73                                         gpg_error (GPG_ERR_ASS_PARAMETER), (t))
74 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
75
76
77
78 /* Control structure per connection. */
79 struct server_local_s
80 {
81   /* Data used to associate an Assuan context with local server data */
82   assuan_context_t assuan_ctx;
83
84   /* Per-session LDAP servers.  */
85   ldap_server_t ldapservers;
86
87   /* Per-session list of keyservers.  */
88   uri_item_t keyservers;
89
90   /* If this flag is set to true this dirmngr process will be
91      terminated after the end of this session.  */
92   int stopme;
93 };
94
95
96 /* Cookie definition for assuan data line output.  */
97 static ssize_t data_line_cookie_write (void *cookie,
98                                        const void *buffer, size_t size);
99 static int data_line_cookie_close (void *cookie);
100 static es_cookie_io_functions_t data_line_cookie_functions =
101   {
102     NULL,
103     data_line_cookie_write,
104     NULL,
105     data_line_cookie_close
106   };
107
108
109
110
111 \f
112 /* Accessor for the local ldapservers variable. */
113 ldap_server_t
114 get_ldapservers_from_ctrl (ctrl_t ctrl)
115 {
116   if (ctrl && ctrl->server_local)
117     return ctrl->server_local->ldapservers;
118   else
119     return NULL;
120 }
121
122
123 /* Release all configured keyserver info from CTRL.  */
124 void
125 release_ctrl_keyservers (ctrl_t ctrl)
126 {
127   if (! ctrl->server_local)
128     return;
129
130   while (ctrl->server_local->keyservers)
131     {
132       uri_item_t tmp = ctrl->server_local->keyservers->next;
133       http_release_parsed_uri (ctrl->server_local->keyservers->parsed_uri);
134       xfree (ctrl->server_local->keyservers);
135       ctrl->server_local->keyservers = tmp;
136     }
137 }
138
139
140
141 /* Helper to print a message while leaving a command.  */
142 static gpg_error_t
143 leave_cmd (assuan_context_t ctx, gpg_error_t err)
144 {
145   if (err)
146     {
147       const char *name = assuan_get_command_name (ctx);
148       if (!name)
149         name = "?";
150       if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
151         log_error ("command '%s' failed: %s\n", name,
152                    gpg_strerror (err));
153       else
154         log_error ("command '%s' failed: %s <%s>\n", name,
155                    gpg_strerror (err), gpg_strsource (err));
156     }
157   return err;
158 }
159
160
161 /* This is a wrapper around assuan_send_data which makes debugging the
162    output in verbose mode easier.  */
163 static gpg_error_t
164 data_line_write (assuan_context_t ctx, const void *buffer_arg, size_t size)
165 {
166   const char *buffer = buffer_arg;
167   gpg_error_t err;
168
169   if (opt.verbose && buffer && size)
170     {
171       /* Ease reading of output by sending a physical line at each LF.  */
172       const char *p;
173       size_t n, nbytes;
174
175       nbytes = size;
176       do
177         {
178           p = memchr (buffer, '\n', nbytes);
179           n = p ? (p - buffer) + 1 : nbytes;
180           err = assuan_send_data (ctx, buffer, n);
181           if (err)
182             {
183               gpg_err_set_errno (EIO);
184               return err;
185             }
186           buffer += n;
187           nbytes -= n;
188           if (nbytes && (err=assuan_send_data (ctx, NULL, 0))) /* Flush line. */
189             {
190               gpg_err_set_errno (EIO);
191               return err;
192             }
193         }
194       while (nbytes);
195     }
196   else
197     {
198       err = assuan_send_data (ctx, buffer, size);
199       if (err)
200         {
201           gpg_err_set_errno (EIO);  /* For use by data_line_cookie_write.  */
202           return err;
203         }
204     }
205
206   return 0;
207 }
208
209
210 /* A write handler used by es_fopencookie to write assuan data
211    lines.  */
212 static ssize_t
213 data_line_cookie_write (void *cookie, const void *buffer, size_t size)
214 {
215   assuan_context_t ctx = cookie;
216
217   if (data_line_write (ctx, buffer, size))
218     return -1;
219   return (ssize_t)size;
220 }
221
222
223 static int
224 data_line_cookie_close (void *cookie)
225 {
226   assuan_context_t ctx = cookie;
227
228   if (assuan_send_data (ctx, NULL, 0))
229     {
230       gpg_err_set_errno (EIO);
231       return -1;
232     }
233
234   return 0;
235 }
236
237
238 /* Copy the % and + escaped string S into the buffer D and replace the
239    escape sequences.  Note, that it is sufficient to allocate the
240    target string D as long as the source string S, i.e.: strlen(s)+1.
241    Note further that if S contains an escaped binary Nul the resulting
242    string D will contain the 0 as well as all other characters but it
243    will be impossible to know whether this is the original EOS or a
244    copied Nul. */
245 static void
246 strcpy_escaped_plus (char *d, const unsigned char *s)
247 {
248   while (*s)
249     {
250       if (*s == '%' && s[1] && s[2])
251         {
252           s++;
253           *d++ = xtoi_2 ( s);
254           s += 2;
255         }
256       else if (*s == '+')
257         *d++ = ' ', s++;
258       else
259         *d++ = *s++;
260     }
261   *d = 0;
262 }
263
264
265 /* Check whether the option NAME appears in LINE */
266 static int
267 has_option (const char *line, const char *name)
268 {
269   const char *s;
270   int n = strlen (name);
271
272   s = strstr (line, name);
273   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
274 }
275
276 /* Same as has_option but only considers options at the begin of the
277    line.  This is useful for commands which allow arbitrary strings on
278    the line.  */
279 static int
280 has_leading_option (const char *line, const char *name)
281 {
282   const char *s;
283   int n;
284
285   if (name[0] != '-' || name[1] != '-' || !name[2] || spacep (name+2))
286     return 0;
287   n = strlen (name);
288   while ( *line == '-' && line[1] == '-' )
289     {
290       s = line;
291       while (*line && !spacep (line))
292         line++;
293       if (n == (line - s) && !strncmp (s, name, n))
294         return 1;
295       while (spacep (line))
296         line++;
297     }
298   return 0;
299 }
300
301
302 /* Same as has_option but does only test for the name of the option
303    and ignores an argument, i.e. with NAME being "--hash" it would
304    return a pointer for "--hash" as well as for "--hash=foo".  If
305    thhere is no such option NULL is returned.  The pointer returned
306    points right behind the option name, this may be an equal sign, Nul
307    or a space.  */
308 /* static const char * */
309 /* has_option_name (const char *line, const char *name) */
310 /* { */
311 /*   const char *s; */
312 /*   int n = strlen (name); */
313
314 /*   s = strstr (line, name); */
315 /*   return (s && (s == line || spacep (s-1)) */
316 /*           && (!s[n] || spacep (s+n) || s[n] == '=')) ? (s+n) : NULL; */
317 /* } */
318
319
320 /* Skip over options.  It is assumed that leading spaces have been
321    removed (this is the case for lines passed to a handler from
322    assuan).  Blanks after the options are also removed. */
323 static char *
324 skip_options (char *line)
325 {
326   while ( *line == '-' && line[1] == '-' )
327     {
328       while (*line && !spacep (line))
329         line++;
330       while (spacep (line))
331         line++;
332     }
333   return line;
334 }
335
336
337 /* Return an error if the assuan context does not belong to the owner
338    of the process or to root.  On error FAILTEXT is set as Assuan
339    error string.  */
340 static gpg_error_t
341 check_owner_permission (assuan_context_t ctx, const char *failtext)
342 {
343 #ifdef HAVE_W32_SYSTEM
344   /* Under Windows the dirmngr is always run under the control of the
345      user.  */
346   (void)ctx;
347   (void)failtext;
348 #else
349   gpg_err_code_t ec;
350   assuan_peercred_t cred;
351
352   ec = gpg_err_code (assuan_get_peercred (ctx, &cred));
353   if (!ec && cred->uid && cred->uid != getuid ())
354     ec = GPG_ERR_EPERM;
355   if (ec)
356     return set_error (ec, failtext);
357 #endif
358   return 0;
359 }
360
361
362
363 /* Common code for get_cert_local and get_issuer_cert_local. */
364 static ksba_cert_t
365 do_get_cert_local (ctrl_t ctrl, const char *name, const char *command)
366 {
367   unsigned char *value;
368   size_t valuelen;
369   int rc;
370   char *buf;
371   ksba_cert_t cert;
372
373   if (name)
374     {
375       buf = xmalloc ( strlen (command) + 1 + strlen(name) + 1);
376       strcpy (stpcpy (stpcpy (buf, command), " "), name);
377     }
378   else
379     buf = xstrdup (command);
380
381   rc = assuan_inquire (ctrl->server_local->assuan_ctx, buf,
382                        &value, &valuelen, MAX_CERT_LENGTH);
383   xfree (buf);
384   if (rc)
385     {
386       log_error (_("assuan_inquire(%s) failed: %s\n"),
387                  command, gpg_strerror (rc));
388       return NULL;
389     }
390
391   if (!valuelen)
392     {
393       xfree (value);
394       return NULL;
395     }
396
397   rc = ksba_cert_new (&cert);
398   if (!rc)
399     {
400       rc = ksba_cert_init_from_mem (cert, value, valuelen);
401       if (rc)
402         {
403           ksba_cert_release (cert);
404           cert = NULL;
405         }
406     }
407   xfree (value);
408   return cert;
409 }
410
411
412
413 /* Ask back to return a certificate for name, given as a regular
414    gpgsm certificate indentificates (e.g. fingerprint or one of the
415    other methods).  Alternatively, NULL may be used for NAME to
416    return the current target certificate. Either return the certificate
417    in a KSBA object or NULL if it is not available.
418 */
419 ksba_cert_t
420 get_cert_local (ctrl_t ctrl, const char *name)
421 {
422   if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
423     {
424       if (opt.debug)
425         log_debug ("get_cert_local called w/o context\n");
426       return NULL;
427     }
428   return do_get_cert_local (ctrl, name, "SENDCERT");
429
430 }
431
432 /* Ask back to return the issuing certificate for name, given as a
433    regular gpgsm certificate indentificates (e.g. fingerprint or one
434    of the other methods).  Alternatively, NULL may be used for NAME to
435    return thecurrent target certificate. Either return the certificate
436    in a KSBA object or NULL if it is not available.
437
438 */
439 ksba_cert_t
440 get_issuing_cert_local (ctrl_t ctrl, const char *name)
441 {
442   if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
443     {
444       if (opt.debug)
445         log_debug ("get_issuing_cert_local called w/o context\n");
446       return NULL;
447     }
448   return do_get_cert_local (ctrl, name, "SENDISSUERCERT");
449 }
450
451 /* Ask back to return a certificate with subject NAME and a
452    subjectKeyIdentifier of KEYID. */
453 ksba_cert_t
454 get_cert_local_ski (ctrl_t ctrl, const char *name, ksba_sexp_t keyid)
455 {
456   unsigned char *value;
457   size_t valuelen;
458   int rc;
459   char *buf;
460   ksba_cert_t cert;
461   char *hexkeyid;
462
463   if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
464     {
465       if (opt.debug)
466         log_debug ("get_cert_local_ski called w/o context\n");
467       return NULL;
468     }
469   if (!name || !keyid)
470     {
471       log_debug ("get_cert_local_ski called with insufficient arguments\n");
472       return NULL;
473     }
474
475   hexkeyid = serial_hex (keyid);
476   if (!hexkeyid)
477     {
478       log_debug ("serial_hex() failed\n");
479       return NULL;
480     }
481
482   buf = xtrymalloc (15 + strlen (hexkeyid) + 2 + strlen(name) + 1);
483   if (!buf)
484     {
485
486       log_error ("can't allocate enough memory: %s\n", strerror (errno));
487       xfree (hexkeyid);
488       return NULL;
489     }
490   strcpy (stpcpy (stpcpy (stpcpy (buf, "SENDCERT_SKI "), hexkeyid)," /"),name);
491   xfree (hexkeyid);
492
493   rc = assuan_inquire (ctrl->server_local->assuan_ctx, buf,
494                        &value, &valuelen, MAX_CERT_LENGTH);
495   xfree (buf);
496   if (rc)
497     {
498       log_error (_("assuan_inquire(%s) failed: %s\n"), "SENDCERT_SKI",
499                  gpg_strerror (rc));
500       return NULL;
501     }
502
503   if (!valuelen)
504     {
505       xfree (value);
506       return NULL;
507     }
508
509   rc = ksba_cert_new (&cert);
510   if (!rc)
511     {
512       rc = ksba_cert_init_from_mem (cert, value, valuelen);
513       if (rc)
514         {
515           ksba_cert_release (cert);
516           cert = NULL;
517         }
518     }
519   xfree (value);
520   return cert;
521 }
522
523
524 /* Ask the client via an inquiry to check the istrusted status of the
525    certificate specified by the hexified fingerprint HEXFPR.  Returns
526    0 if the certificate is trusted by the client or an error code.  */
527 gpg_error_t
528 get_istrusted_from_client (ctrl_t ctrl, const char *hexfpr)
529 {
530   unsigned char *value;
531   size_t valuelen;
532   int rc;
533   char request[100];
534
535   if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx
536       || !hexfpr)
537     return gpg_error (GPG_ERR_INV_ARG);
538
539   snprintf (request, sizeof request, "ISTRUSTED %s", hexfpr);
540   rc = assuan_inquire (ctrl->server_local->assuan_ctx, request,
541                        &value, &valuelen, 100);
542   if (rc)
543     {
544       log_error (_("assuan_inquire(%s) failed: %s\n"),
545                  request, gpg_strerror (rc));
546       return rc;
547     }
548   /* The expected data is: "1" or "1 cruft" (not a C-string).  */
549   if (valuelen && *value == '1' && (valuelen == 1 || spacep (value+1)))
550     rc = 0;
551   else
552     rc = gpg_error (GPG_ERR_NOT_TRUSTED);
553   xfree (value);
554   return rc;
555 }
556
557
558
559
560 /* Ask the client to return the certificate associated with the
561    current command. This is sometimes needed because the client usually
562    sends us just the cert ID, assuming that the request can be
563    satisfied from the cache, where the cert ID is used as key. */
564 static int
565 inquire_cert_and_load_crl (assuan_context_t ctx)
566 {
567   ctrl_t ctrl = assuan_get_pointer (ctx);
568   gpg_error_t err;
569   unsigned char *value = NULL;
570   size_t valuelen;
571   ksba_cert_t cert = NULL;
572
573   err = assuan_inquire( ctx, "SENDCERT", &value, &valuelen, 0);
574   if (err)
575     return err;
576
577 /*   { */
578 /*     FILE *fp = fopen ("foo.der", "r"); */
579 /*     value = xmalloc (2000); */
580 /*     valuelen = fread (value, 1, 2000, fp); */
581 /*     fclose (fp); */
582 /*   } */
583
584   if (!valuelen) /* No data returned; return a comprehensible error. */
585     return gpg_error (GPG_ERR_MISSING_CERT);
586
587   err = ksba_cert_new (&cert);
588   if (err)
589     goto leave;
590   err = ksba_cert_init_from_mem (cert, value, valuelen);
591   if(err)
592     goto leave;
593   xfree (value); value = NULL;
594
595   err = crl_cache_reload_crl (ctrl, cert);
596
597  leave:
598   ksba_cert_release (cert);
599   xfree (value);
600   return err;
601 }
602
603
604 /* Handle OPTION commands. */
605 static gpg_error_t
606 option_handler (assuan_context_t ctx, const char *key, const char *value)
607 {
608   ctrl_t ctrl = assuan_get_pointer (ctx);
609   gpg_error_t err = 0;
610
611   if (!strcmp (key, "force-crl-refresh"))
612     {
613       int i = *value? atoi (value) : 0;
614       ctrl->force_crl_refresh = i;
615     }
616   else if (!strcmp (key, "audit-events"))
617     {
618       int i = *value? atoi (value) : 0;
619       ctrl->audit_events = i;
620     }
621   else if (!strcmp (key, "http-proxy"))
622     {
623       xfree (ctrl->http_proxy);
624       if (!*value || !strcmp (value, "none"))
625         ctrl->http_proxy = NULL;
626       else if (!(ctrl->http_proxy = xtrystrdup (value)))
627         err = gpg_error_from_syserror ();
628     }
629   else
630     err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
631
632   return err;
633 }
634
635
636 \f
637 static const char hlp_dns_cert[] =
638   "DNS_CERT <subtype> <name>\n"
639   "DNS_CERT --pka <user_id>\n"
640   "\n"
641   "Return the CERT record for <name>.  <subtype> is one of\n"
642   "  *     Return the first record of any supported subtype\n"
643   "  PGP   Return the first record of subtype PGP (3)\n"
644   "  IPGP  Return the first record of subtype IPGP (6)\n"
645   "If the content of a certifciate is available (PGP) it is returned\n"
646   "by data lines.  Fingerprints and URLs are returned via status lines.\n"
647   "In --pka mode the fingerprint and if available an URL is returned.";
648 static gpg_error_t
649 cmd_dns_cert (assuan_context_t ctx, char *line)
650 {
651   /* ctrl_t ctrl = assuan_get_pointer (ctx); */
652   gpg_error_t err = 0;
653   int pka_mode;
654   char *mbox = NULL;
655   char *namebuf = NULL;
656   char *encodedhash = NULL;
657   const char *name;
658   int certtype;
659   char *p;
660   void *key = NULL;
661   size_t keylen;
662   unsigned char *fpr = NULL;
663   size_t fprlen;
664   char *url = NULL;
665
666   pka_mode = has_option (line, "--pka");
667   line = skip_options (line);
668   if (pka_mode)
669     ; /* No need to parse here - we do this later.  */
670   else
671     {
672       p = strchr (line, ' ');
673       if (!p)
674         {
675           err = PARM_ERROR ("missing arguments");
676           goto leave;
677         }
678       *p++ = 0;
679       if (!strcmp (line, "*"))
680         certtype = DNS_CERTTYPE_ANY;
681       else if (!strcmp (line, "IPGP"))
682         certtype = DNS_CERTTYPE_IPGP;
683       else if (!strcmp (line, "PGP"))
684         certtype = DNS_CERTTYPE_PGP;
685       else
686         {
687           err = PARM_ERROR ("unknown subtype");
688           goto leave;
689         }
690       while (spacep (p))
691         p++;
692       line = p;
693       if (!*line)
694         {
695           err = PARM_ERROR ("name missing");
696           goto leave;
697         }
698     }
699
700   if (pka_mode)
701     {
702       char *domain;  /* Points to mbox.  */
703       char hashbuf[20];
704
705       mbox = mailbox_from_userid (line);
706       if (!mbox || !(domain = strchr (mbox, '@')))
707         {
708           err = set_error (GPG_ERR_INV_USER_ID, "no mailbox in user id");
709           goto leave;
710         }
711       *domain++ = 0;
712
713       gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf, mbox, strlen (mbox));
714       encodedhash = zb32_encode (hashbuf, 8*20);
715       if (!encodedhash)
716         {
717           err = gpg_error_from_syserror ();
718           goto leave;
719         }
720       namebuf = strconcat (encodedhash, "._pka.", domain, NULL);
721       if (!namebuf)
722         {
723           err = gpg_error_from_syserror ();
724           goto leave;
725         }
726       name = namebuf;
727       certtype = DNS_CERTTYPE_IPGP;
728     }
729   else
730     name = line;
731
732   err = get_dns_cert (name, certtype, &key, &keylen, &fpr, &fprlen, &url);
733   if (err)
734     goto leave;
735
736   if (key)
737     {
738       err = data_line_write (ctx, key, keylen);
739       if (err)
740         goto leave;
741     }
742
743   if (fpr)
744     {
745       char *tmpstr;
746
747       tmpstr = bin2hex (fpr, fprlen, NULL);
748       if (!tmpstr)
749         err = gpg_error_from_syserror ();
750       else
751         {
752           err = assuan_write_status (ctx, "FPR", tmpstr);
753           xfree (tmpstr);
754         }
755       if (err)
756         goto leave;
757     }
758
759   if (url)
760     {
761       err = assuan_write_status (ctx, "URL", url);
762       if (err)
763         goto leave;
764     }
765
766
767  leave:
768   xfree (key);
769   xfree (fpr);
770   xfree (url);
771   xfree (mbox);
772   xfree (namebuf);
773   xfree (encodedhash);
774   return leave_cmd (ctx, err);
775 }
776
777
778 \f
779 static const char hlp_ldapserver[] =
780   "LDAPSERVER <data>\n"
781   "\n"
782   "Add a new LDAP server to the list of configured LDAP servers.\n"
783   "DATA is in the same format as expected in the configure file.";
784 static gpg_error_t
785 cmd_ldapserver (assuan_context_t ctx, char *line)
786 {
787 #if USE_LDAP
788   ctrl_t ctrl = assuan_get_pointer (ctx);
789   ldap_server_t server;
790   ldap_server_t *last_next_p;
791
792   while (spacep (line))
793     line++;
794   if (*line == '\0')
795     return leave_cmd (ctx, PARM_ERROR (_("ldapserver missing")));
796
797   server = ldapserver_parse_one (line, "", 0);
798   if (! server)
799     return leave_cmd (ctx, gpg_error (GPG_ERR_INV_ARG));
800
801   last_next_p = &ctrl->server_local->ldapservers;
802   while (*last_next_p)
803     last_next_p = &(*last_next_p)->next;
804   *last_next_p = server;
805   return leave_cmd (ctx, 0);
806 #else
807   (void)line;
808   return leave_cmd (ctx, gpg_error (GPG_ERR_NOT_IMPLEMENTED));
809 #endif
810 }
811
812
813 static const char hlp_isvalid[] =
814   "ISVALID [--only-ocsp] [--force-default-responder]"
815   " <certificate_id>|<certificate_fpr>\n"
816   "\n"
817   "This command checks whether the certificate identified by the\n"
818   "certificate_id is valid.  This is done by consulting CRLs or\n"
819   "whatever has been configured.  Note, that the returned error codes\n"
820   "are from gpg-error.h.  The command may callback using the inquire\n"
821   "function.  See the manual for details.\n"
822   "\n"
823   "The CERTIFICATE_ID is a hex encoded string consisting of two parts,\n"
824   "delimited by a single dot.  The first part is the SHA-1 hash of the\n"
825   "issuer name and the second part the serial number.\n"
826   "\n"
827   "Alternatively the certificate's fingerprint may be given in which\n"
828   "case an OCSP request is done before consulting the CRL.\n"
829   "\n"
830   "If the option --only-ocsp is given, no fallback to a CRL check will\n"
831   "be used.\n"
832   "\n"
833   "If the option --force-default-responder is given, only the default\n"
834   "OCSP responder will be used and any other methods of obtaining an\n"
835   "OCSP responder URL won't be used.";
836 static gpg_error_t
837 cmd_isvalid (assuan_context_t ctx, char *line)
838 {
839   ctrl_t ctrl = assuan_get_pointer (ctx);
840   char *issuerhash, *serialno;
841   gpg_error_t err;
842   int did_inquire = 0;
843   int ocsp_mode = 0;
844   int only_ocsp;
845   int force_default_responder;
846
847   only_ocsp = has_option (line, "--only-ocsp");
848   force_default_responder = has_option (line, "--force-default-responder");
849   line = skip_options (line);
850
851   issuerhash = xstrdup (line); /* We need to work on a copy of the
852                                   line because that same Assuan
853                                   context may be used for an inquiry.
854                                   That is because Assuan reuses its
855                                   line buffer.
856                                    */
857
858   serialno = strchr (issuerhash, '.');
859   if (serialno)
860     *serialno++ = 0;
861   else
862     {
863       char *endp = strchr (issuerhash, ' ');
864       if (endp)
865         *endp = 0;
866       if (strlen (issuerhash) != 40)
867         {
868           xfree (issuerhash);
869           return leave_cmd (ctx, PARM_ERROR (_("serialno missing in cert ID")));
870         }
871       ocsp_mode = 1;
872     }
873
874
875  again:
876   if (ocsp_mode)
877     {
878       /* Note, that we ignore the given issuer hash and instead rely
879          on the current certificate semantics used with this
880          command. */
881       if (!opt.allow_ocsp)
882         err = gpg_error (GPG_ERR_NOT_SUPPORTED);
883       else
884         err = ocsp_isvalid (ctrl, NULL, NULL, force_default_responder);
885       /* Fixme: If we got no ocsp response and --only-ocsp is not used
886          we should fall back to CRL mode.  Thus we need to clear
887          OCSP_MODE, get the issuerhash and the serialno from the
888          current certificate and jump to again. */
889     }
890   else if (only_ocsp)
891     err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
892   else
893     {
894       switch (crl_cache_isvalid (ctrl,
895                                  issuerhash, serialno,
896                                  ctrl->force_crl_refresh))
897         {
898         case CRL_CACHE_VALID:
899           err = 0;
900           break;
901         case CRL_CACHE_INVALID:
902           err = gpg_error (GPG_ERR_CERT_REVOKED);
903           break;
904         case CRL_CACHE_DONTKNOW:
905           if (did_inquire)
906             err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
907           else if (!(err = inquire_cert_and_load_crl (ctx)))
908             {
909               did_inquire = 1;
910               goto again;
911             }
912           break;
913         case CRL_CACHE_CANTUSE:
914           err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
915           break;
916         default:
917           log_fatal ("crl_cache_isvalid returned invalid code\n");
918         }
919     }
920
921   xfree (issuerhash);
922   return leave_cmd (ctx, err);
923 }
924
925
926 /* If the line contains a SHA-1 fingerprint as the first argument,
927    return the FPR vuffer on success.  The function checks that the
928    fingerprint consists of valid characters and prints and error
929    message if it does not and returns NULL.  Fingerprints are
930    considered optional and thus no explicit error is returned. NULL is
931    also returned if there is no fingerprint at all available.
932    FPR must be a caller provided buffer of at least 20 bytes.
933
934    Note that colons within the fingerprint are allowed to separate 2
935    hex digits; this allows for easier cutting and pasting using the
936    usual fingerprint rendering.
937 */
938 static unsigned char *
939 get_fingerprint_from_line (const char *line, unsigned char *fpr)
940 {
941   const char *s;
942   int i;
943
944   for (s=line, i=0; *s && *s != ' '; s++ )
945     {
946       if ( hexdigitp (s) && hexdigitp (s+1) )
947         {
948           if ( i >= 20 )
949             return NULL;  /* Fingerprint too long.  */
950           fpr[i++] = xtoi_2 (s);
951           s++;
952         }
953       else if ( *s != ':' )
954         return NULL; /* Invalid.  */
955     }
956   if ( i != 20 )
957     return NULL; /* Fingerprint to short.  */
958   return fpr;
959 }
960
961
962
963 static const char hlp_checkcrl[] =
964   "CHECKCRL [<fingerprint>]\n"
965   "\n"
966   "Check whether the certificate with FINGERPRINT (SHA-1 hash of the\n"
967   "entire X.509 certificate blob) is valid or not by consulting the\n"
968   "CRL responsible for this certificate.  If the fingerprint has not\n"
969   "been given or the certificate is not known, the function \n"
970   "inquires the certificate using an\n"
971   "\n"
972   "  INQUIRE TARGETCERT\n"
973   "\n"
974   "and the caller is expected to return the certificate for the\n"
975   "request (which should match FINGERPRINT) as a binary blob.\n"
976   "Processing then takes place without further interaction; in\n"
977   "particular dirmngr tries to locate other required certificate by\n"
978   "its own mechanism which includes a local certificate store as well\n"
979   "as a list of trusted root certificates.\n"
980   "\n"
981   "The return value is the usual gpg-error code or 0 for ducesss;\n"
982   "i.e. the certificate validity has been confirmed by a valid CRL.";
983 static gpg_error_t
984 cmd_checkcrl (assuan_context_t ctx, char *line)
985 {
986   ctrl_t ctrl = assuan_get_pointer (ctx);
987   gpg_error_t err;
988   unsigned char fprbuffer[20], *fpr;
989   ksba_cert_t cert;
990
991   fpr = get_fingerprint_from_line (line, fprbuffer);
992   cert = fpr? get_cert_byfpr (fpr) : NULL;
993
994   if (!cert)
995     {
996       /* We do not have this certificate yet or the fingerprint has
997          not been given.  Inquire it from the client.  */
998       unsigned char *value = NULL;
999       size_t valuelen;
1000
1001       err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1002                            &value, &valuelen, MAX_CERT_LENGTH);
1003       if (err)
1004         {
1005           log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1006           goto leave;
1007         }
1008
1009       if (!valuelen) /* No data returned; return a comprehensible error. */
1010         err = gpg_error (GPG_ERR_MISSING_CERT);
1011       else
1012         {
1013           err = ksba_cert_new (&cert);
1014           if (!err)
1015             err = ksba_cert_init_from_mem (cert, value, valuelen);
1016         }
1017       xfree (value);
1018       if(err)
1019         goto leave;
1020     }
1021
1022   assert (cert);
1023
1024   err = crl_cache_cert_isvalid (ctrl, cert, ctrl->force_crl_refresh);
1025   if (gpg_err_code (err) == GPG_ERR_NO_CRL_KNOWN)
1026     {
1027       err = crl_cache_reload_crl (ctrl, cert);
1028       if (!err)
1029         err = crl_cache_cert_isvalid (ctrl, cert, 0);
1030     }
1031
1032  leave:
1033   ksba_cert_release (cert);
1034   return leave_cmd (ctx, err);
1035 }
1036
1037
1038 static const char hlp_checkocsp[] =
1039   "CHECKOCSP [--force-default-responder] [<fingerprint>]\n"
1040   "\n"
1041   "Check whether the certificate with FINGERPRINT (SHA-1 hash of the\n"
1042   "entire X.509 certificate blob) is valid or not by asking an OCSP\n"
1043   "responder responsible for this certificate.  The optional\n"
1044   "fingerprint may be used for a quick check in case an OCSP check has\n"
1045   "been done for this certificate recently (we always cache OCSP\n"
1046   "responses for a couple of minutes). If the fingerprint has not been\n"
1047   "given or there is no cached result, the function inquires the\n"
1048   "certificate using an\n"
1049   "\n"
1050   "   INQUIRE TARGETCERT\n"
1051   "\n"
1052   "and the caller is expected to return the certificate for the\n"
1053   "request (which should match FINGERPRINT) as a binary blob.\n"
1054   "Processing then takes place without further interaction; in\n"
1055   "particular dirmngr tries to locate other required certificates by\n"
1056   "its own mechanism which includes a local certificate store as well\n"
1057   "as a list of trusted root certifciates.\n"
1058   "\n"
1059   "If the option --force-default-responder is given, only the default\n"
1060   "OCSP responder will be used and any other methods of obtaining an\n"
1061   "OCSP responder URL won't be used.\n"
1062   "\n"
1063   "The return value is the usual gpg-error code or 0 for ducesss;\n"
1064   "i.e. the certificate validity has been confirmed by a valid CRL.";
1065 static gpg_error_t
1066 cmd_checkocsp (assuan_context_t ctx, char *line)
1067 {
1068   ctrl_t ctrl = assuan_get_pointer (ctx);
1069   gpg_error_t err;
1070   unsigned char fprbuffer[20], *fpr;
1071   ksba_cert_t cert;
1072   int force_default_responder;
1073
1074   force_default_responder = has_option (line, "--force-default-responder");
1075   line = skip_options (line);
1076
1077   fpr = get_fingerprint_from_line (line, fprbuffer);
1078   cert = fpr? get_cert_byfpr (fpr) : NULL;
1079
1080   if (!cert)
1081     {
1082       /* We do not have this certificate yet or the fingerprint has
1083          not been given.  Inquire it from the client.  */
1084       unsigned char *value = NULL;
1085       size_t valuelen;
1086
1087       err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1088                            &value, &valuelen, MAX_CERT_LENGTH);
1089       if (err)
1090         {
1091           log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1092           goto leave;
1093         }
1094
1095       if (!valuelen) /* No data returned; return a comprehensible error. */
1096         err = gpg_error (GPG_ERR_MISSING_CERT);
1097       else
1098         {
1099           err = ksba_cert_new (&cert);
1100           if (!err)
1101             err = ksba_cert_init_from_mem (cert, value, valuelen);
1102         }
1103       xfree (value);
1104       if(err)
1105         goto leave;
1106     }
1107
1108   assert (cert);
1109
1110   if (!opt.allow_ocsp)
1111     err = gpg_error (GPG_ERR_NOT_SUPPORTED);
1112   else
1113     err = ocsp_isvalid (ctrl, cert, NULL, force_default_responder);
1114
1115  leave:
1116   ksba_cert_release (cert);
1117   return leave_cmd (ctx, err);
1118 }
1119
1120
1121
1122 static int
1123 lookup_cert_by_url (assuan_context_t ctx, const char *url)
1124 {
1125   ctrl_t ctrl = assuan_get_pointer (ctx);
1126   gpg_error_t err = 0;
1127   unsigned char *value = NULL;
1128   size_t valuelen;
1129
1130   /* Fetch single certificate given it's URL.  */
1131   err = fetch_cert_by_url (ctrl, url, &value, &valuelen);
1132   if (err)
1133     {
1134       log_error (_("fetch_cert_by_url failed: %s\n"), gpg_strerror (err));
1135       goto leave;
1136     }
1137
1138   /* Send the data, flush the buffer and then send an END. */
1139   err = assuan_send_data (ctx, value, valuelen);
1140   if (!err)
1141     err = assuan_send_data (ctx, NULL, 0);
1142   if (!err)
1143     err = assuan_write_line (ctx, "END");
1144   if (err)
1145     {
1146       log_error (_("error sending data: %s\n"), gpg_strerror (err));
1147       goto leave;
1148     }
1149
1150  leave:
1151
1152   return err;
1153 }
1154
1155
1156 /* Send the certificate, flush the buffer and then send an END. */
1157 static gpg_error_t
1158 return_one_cert (void *opaque, ksba_cert_t cert)
1159 {
1160   assuan_context_t ctx = opaque;
1161   gpg_error_t err;
1162   const unsigned char *der;
1163   size_t derlen;
1164
1165   der = ksba_cert_get_image (cert, &derlen);
1166   if (!der)
1167     err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1168   else
1169     {
1170       err = assuan_send_data (ctx, der, derlen);
1171       if (!err)
1172         err = assuan_send_data (ctx, NULL, 0);
1173       if (!err)
1174         err = assuan_write_line (ctx, "END");
1175     }
1176   if (err)
1177     log_error (_("error sending data: %s\n"), gpg_strerror (err));
1178   return err;
1179 }
1180
1181
1182 /* Lookup certificates from the internal cache or using the ldap
1183    servers. */
1184 static int
1185 lookup_cert_by_pattern (assuan_context_t ctx, char *line,
1186                         int single, int cache_only)
1187 {
1188   gpg_error_t err = 0;
1189   char *p;
1190   strlist_t sl, list = NULL;
1191   int truncated = 0, truncation_forced = 0;
1192   int count = 0;
1193   int local_count = 0;
1194 #if USE_LDAP
1195   ctrl_t ctrl = assuan_get_pointer (ctx);
1196   unsigned char *value = NULL;
1197   size_t valuelen;
1198   struct ldapserver_iter ldapserver_iter;
1199   cert_fetch_context_t fetch_context;
1200 #endif /*USE_LDAP*/
1201   int any_no_data = 0;
1202
1203   /* Break the line down into an STRLIST */
1204   for (p=line; *p; line = p)
1205     {
1206       while (*p && *p != ' ')
1207         p++;
1208       if (*p)
1209         *p++ = 0;
1210
1211       if (*line)
1212         {
1213           sl = xtrymalloc (sizeof *sl + strlen (line));
1214           if (!sl)
1215             {
1216               err = gpg_error_from_errno (errno);
1217               goto leave;
1218             }
1219           memset (sl, 0, sizeof *sl);
1220           strcpy_escaped_plus (sl->d, line);
1221           sl->next = list;
1222           list = sl;
1223         }
1224     }
1225
1226   /* First look through the internal cache.  The certifcates retruned
1227      here are not counted towards the truncation limit.  */
1228   if (single && !cache_only)
1229     ; /* Do not read from the local cache in this case.  */
1230   else
1231     {
1232       for (sl=list; sl; sl = sl->next)
1233         {
1234           err = get_certs_bypattern (sl->d, return_one_cert, ctx);
1235           if (!err)
1236             local_count++;
1237           if (!err && single)
1238             goto ready;
1239
1240           if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1241             {
1242               err = 0;
1243               if (cache_only)
1244                 any_no_data = 1;
1245             }
1246           else if (gpg_err_code (err) == GPG_ERR_INV_NAME && !cache_only)
1247             {
1248               /* No real fault because the internal pattern lookup
1249                  can't yet cope with all types of pattern.  */
1250               err = 0;
1251             }
1252           if (err)
1253             goto ready;
1254         }
1255     }
1256
1257   /* Loop over all configured servers unless we want only the
1258      certificates from the cache.  */
1259 #if USE_LDAP
1260   for (ldapserver_iter_begin (&ldapserver_iter, ctrl);
1261        !cache_only && !ldapserver_iter_end_p (&ldapserver_iter)
1262          && ldapserver_iter.server->host && !truncation_forced;
1263        ldapserver_iter_next (&ldapserver_iter))
1264     {
1265       ldap_server_t ldapserver = ldapserver_iter.server;
1266
1267       if (DBG_LOOKUP)
1268         log_debug ("cmd_lookup: trying %s:%d base=%s\n",
1269                    ldapserver->host, ldapserver->port,
1270                    ldapserver->base?ldapserver->base : "[default]");
1271
1272       /* Fetch certificates matching pattern */
1273       err = start_cert_fetch (ctrl, &fetch_context, list, ldapserver);
1274       if ( gpg_err_code (err) == GPG_ERR_NO_DATA )
1275         {
1276           if (DBG_LOOKUP)
1277             log_debug ("cmd_lookup: no data\n");
1278           err = 0;
1279           any_no_data = 1;
1280           continue;
1281         }
1282       if (err)
1283         {
1284           log_error (_("start_cert_fetch failed: %s\n"), gpg_strerror (err));
1285           goto leave;
1286         }
1287
1288       /* Fetch the certificates for this query. */
1289       while (!truncation_forced)
1290         {
1291           xfree (value); value = NULL;
1292           err = fetch_next_cert (fetch_context, &value, &valuelen);
1293           if (gpg_err_code (err) == GPG_ERR_NO_DATA )
1294             {
1295               err = 0;
1296               any_no_data = 1;
1297               break; /* Ready. */
1298             }
1299           if (gpg_err_code (err) == GPG_ERR_TRUNCATED)
1300             {
1301               truncated = 1;
1302               err = 0;
1303               break;  /* Ready.  */
1304             }
1305           if (gpg_err_code (err) == GPG_ERR_EOF)
1306             {
1307               err = 0;
1308               break; /* Ready. */
1309             }
1310           if (!err && !value)
1311             {
1312               err = gpg_error (GPG_ERR_BUG);
1313               goto leave;
1314             }
1315           if (err)
1316             {
1317               log_error (_("fetch_next_cert failed: %s\n"),
1318                          gpg_strerror (err));
1319               end_cert_fetch (fetch_context);
1320               goto leave;
1321             }
1322
1323           if (DBG_LOOKUP)
1324             log_debug ("cmd_lookup: returning one cert%s\n",
1325                        truncated? " (truncated)":"");
1326
1327           /* Send the data, flush the buffer and then send an END line
1328              as a certificate delimiter. */
1329           err = assuan_send_data (ctx, value, valuelen);
1330           if (!err)
1331             err = assuan_send_data (ctx, NULL, 0);
1332           if (!err)
1333             err = assuan_write_line (ctx, "END");
1334           if (err)
1335             {
1336               log_error (_("error sending data: %s\n"), gpg_strerror (err));
1337               end_cert_fetch (fetch_context);
1338               goto leave;
1339             }
1340
1341           if (++count >= opt.max_replies )
1342             {
1343               truncation_forced = 1;
1344               log_info (_("max_replies %d exceeded\n"), opt.max_replies );
1345             }
1346           if (single)
1347             break;
1348         }
1349
1350       end_cert_fetch (fetch_context);
1351     }
1352 #endif /*USE_LDAP*/
1353
1354  ready:
1355   if (truncated || truncation_forced)
1356     {
1357       char str[50];
1358
1359       sprintf (str, "%d", count);
1360       assuan_write_status (ctx, "TRUNCATED", str);
1361     }
1362
1363   if (!err && !count && !local_count && any_no_data)
1364     err = gpg_error (GPG_ERR_NO_DATA);
1365
1366  leave:
1367   free_strlist (list);
1368   return err;
1369 }
1370
1371
1372 static const char hlp_lookup[] =
1373   "LOOKUP [--url] [--single] [--cache-only] <pattern>\n"
1374   "\n"
1375   "Lookup certificates matching PATTERN. With --url the pattern is\n"
1376   "expected to be one URL.\n"
1377   "\n"
1378   "If --url is not given:  To allow for multiple patterns (which are ORed)\n"
1379   "quoting is required: Spaces are translated to \"+\" or \"%20\";\n"
1380   "obviously this requires that the usual escape quoting rules are applied.\n"
1381   "\n"
1382   "If --url is given no special escaping is required because URLs are\n"
1383   "already escaped this way.\n"
1384   "\n"
1385   "If --single is given the first and only the first match will be\n"
1386   "returned.  If --cache-only is _not_ given, no local query will be\n"
1387   "done.\n"
1388   "\n"
1389   "If --cache-only is given no external lookup is done so that only\n"
1390   "certificates from the cache may get returned.";
1391 static gpg_error_t
1392 cmd_lookup (assuan_context_t ctx, char *line)
1393 {
1394   gpg_error_t err;
1395   int lookup_url, single, cache_only;
1396
1397   lookup_url = has_leading_option (line, "--url");
1398   single = has_leading_option (line, "--single");
1399   cache_only = has_leading_option (line, "--cache-only");
1400   line = skip_options (line);
1401
1402   if (lookup_url && cache_only)
1403     err = gpg_error (GPG_ERR_NOT_FOUND);
1404   else if (lookup_url && single)
1405     err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1406   else if (lookup_url)
1407     err = lookup_cert_by_url (ctx, line);
1408   else
1409     err = lookup_cert_by_pattern (ctx, line, single, cache_only);
1410
1411   return leave_cmd (ctx, err);
1412 }
1413
1414
1415 static const char hlp_loadcrl[] =
1416   "LOADCRL [--url] <filename|url>\n"
1417   "\n"
1418   "Load the CRL in the file with name FILENAME into our cache.  Note\n"
1419   "that FILENAME should be given with an absolute path because\n"
1420   "Dirmngrs cwd is not known.  With --url the CRL is directly loaded\n"
1421   "from the given URL.\n"
1422   "\n"
1423   "This command is usually used by gpgsm using the invocation \"gpgsm\n"
1424   "--call-dirmngr loadcrl <filename>\".  A direct invocation of Dirmngr\n"
1425   "is not useful because gpgsm might need to callback gpgsm to ask for\n"
1426   "the CA's certificate.";
1427 static gpg_error_t
1428 cmd_loadcrl (assuan_context_t ctx, char *line)
1429 {
1430   ctrl_t ctrl = assuan_get_pointer (ctx);
1431   gpg_error_t err = 0;
1432   int use_url = has_leading_option (line, "--url");
1433
1434   line = skip_options (line);
1435
1436   if (use_url)
1437     {
1438       ksba_reader_t reader;
1439
1440       err = crl_fetch (ctrl, line, &reader);
1441       if (err)
1442         log_error (_("fetching CRL from '%s' failed: %s\n"),
1443                    line, gpg_strerror (err));
1444       else
1445         {
1446           err = crl_cache_insert (ctrl, line, reader);
1447           if (err)
1448             log_error (_("processing CRL from '%s' failed: %s\n"),
1449                        line, gpg_strerror (err));
1450           crl_close_reader (reader);
1451         }
1452     }
1453   else
1454     {
1455       char *buf;
1456
1457       buf = xtrymalloc (strlen (line)+1);
1458       if (!buf)
1459         err = gpg_error_from_syserror ();
1460       else
1461         {
1462           strcpy_escaped_plus (buf, line);
1463           err = crl_cache_load (ctrl, buf);
1464           xfree (buf);
1465         }
1466     }
1467
1468   return leave_cmd (ctx, err);
1469 }
1470
1471
1472 static const char hlp_listcrls[] =
1473   "LISTCRLS\n"
1474   "\n"
1475   "List the content of all CRLs in a readable format.  This command is\n"
1476   "usually used by gpgsm using the invocation \"gpgsm --call-dirmngr\n"
1477   "listcrls\".  It may also be used directly using \"dirmngr\n"
1478   "--list-crls\".";
1479 static gpg_error_t
1480 cmd_listcrls (assuan_context_t ctx, char *line)
1481 {
1482   gpg_error_t err;
1483   estream_t fp;
1484
1485   (void)line;
1486
1487   fp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1488   if (!fp)
1489     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1490   else
1491     {
1492       err = crl_cache_list (fp);
1493       es_fclose (fp);
1494     }
1495   return leave_cmd (ctx, err);
1496 }
1497
1498
1499 static const char hlp_cachecert[] =
1500   "CACHECERT\n"
1501   "\n"
1502   "Put a certificate into the internal cache.  This command might be\n"
1503   "useful if a client knows in advance certificates required for a\n"
1504   "test and wants to make sure they get added to the internal cache.\n"
1505   "It is also helpful for debugging.  To get the actual certificate,\n"
1506   "this command immediately inquires it using\n"
1507   "\n"
1508   "  INQUIRE TARGETCERT\n"
1509   "\n"
1510   "and the caller is expected to return the certificate for the\n"
1511   "request as a binary blob.";
1512 static gpg_error_t
1513 cmd_cachecert (assuan_context_t ctx, char *line)
1514 {
1515   ctrl_t ctrl = assuan_get_pointer (ctx);
1516   gpg_error_t err;
1517   ksba_cert_t cert = NULL;
1518   unsigned char *value = NULL;
1519   size_t valuelen;
1520
1521   (void)line;
1522
1523   err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1524                        &value, &valuelen, MAX_CERT_LENGTH);
1525   if (err)
1526     {
1527       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1528       goto leave;
1529     }
1530
1531   if (!valuelen) /* No data returned; return a comprehensible error. */
1532     err = gpg_error (GPG_ERR_MISSING_CERT);
1533   else
1534     {
1535       err = ksba_cert_new (&cert);
1536       if (!err)
1537         err = ksba_cert_init_from_mem (cert, value, valuelen);
1538     }
1539   xfree (value);
1540   if(err)
1541     goto leave;
1542
1543   err = cache_cert (cert);
1544
1545  leave:
1546   ksba_cert_release (cert);
1547   return leave_cmd (ctx, err);
1548 }
1549
1550
1551 static const char hlp_validate[] =
1552   "VALIDATE\n"
1553   "\n"
1554   "Validate a certificate using the certificate validation function\n"
1555   "used internally by dirmngr.  This command is only useful for\n"
1556   "debugging.  To get the actual certificate, this command immediately\n"
1557   "inquires it using\n"
1558   "\n"
1559   "  INQUIRE TARGETCERT\n"
1560   "\n"
1561   "and the caller is expected to return the certificate for the\n"
1562   "request as a binary blob.";
1563 static gpg_error_t
1564 cmd_validate (assuan_context_t ctx, char *line)
1565 {
1566   ctrl_t ctrl = assuan_get_pointer (ctx);
1567   gpg_error_t err;
1568   ksba_cert_t cert = NULL;
1569   unsigned char *value = NULL;
1570   size_t valuelen;
1571
1572   (void)line;
1573
1574   err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1575                        &value, &valuelen, MAX_CERT_LENGTH);
1576   if (err)
1577     {
1578       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1579       goto leave;
1580     }
1581
1582   if (!valuelen) /* No data returned; return a comprehensible error. */
1583     err = gpg_error (GPG_ERR_MISSING_CERT);
1584   else
1585     {
1586       err = ksba_cert_new (&cert);
1587       if (!err)
1588         err = ksba_cert_init_from_mem (cert, value, valuelen);
1589     }
1590   xfree (value);
1591   if(err)
1592     goto leave;
1593
1594   /* If we have this certificate already in our cache, use the cached
1595      version for validation because this will take care of any cached
1596      results. */
1597   {
1598     unsigned char fpr[20];
1599     ksba_cert_t tmpcert;
1600
1601     cert_compute_fpr (cert, fpr);
1602     tmpcert = get_cert_byfpr (fpr);
1603     if (tmpcert)
1604       {
1605         ksba_cert_release (cert);
1606         cert = tmpcert;
1607       }
1608   }
1609
1610   err = validate_cert_chain (ctrl, cert, NULL, VALIDATE_MODE_CERT, NULL);
1611
1612  leave:
1613   ksba_cert_release (cert);
1614   return leave_cmd (ctx, err);
1615 }
1616
1617 \f
1618 static const char hlp_keyserver[] =
1619   "KEYSERVER [<options>] [<uri>|<host>]\n"
1620   "Options are:\n"
1621   "  --help\n"
1622   "  --clear      Remove all configured keyservers\n"
1623   "  --resolve    Resolve HKP host names and rotate\n"
1624   "  --hosttable  Print table of known hosts and pools\n"
1625   "  --dead       Mark <host> as dead\n"
1626   "  --alive      Mark <host> as alive\n"
1627   "\n"
1628   "If called without arguments list all configured keyserver URLs.\n"
1629   "If called with an URI add this as keyserver.  Note that keyservers\n"
1630   "are configured on a per-session base.  A default keyserver may already be\n"
1631   "present, thus the \"--clear\" option must be used to get full control.\n"
1632   "If \"--clear\" and an URI are used together the clear command is\n"
1633   "obviously executed first.  A RESET command does not change the list\n"
1634   "of configured keyservers.";
1635 static gpg_error_t
1636 cmd_keyserver (assuan_context_t ctx, char *line)
1637 {
1638   ctrl_t ctrl = assuan_get_pointer (ctx);
1639   gpg_error_t err = 0;
1640   int clear_flag, add_flag, help_flag, host_flag, resolve_flag;
1641   int dead_flag, alive_flag;
1642   uri_item_t item = NULL; /* gcc 4.4.5 is not able to detect that it
1643                              is always initialized.  */
1644
1645   clear_flag = has_option (line, "--clear");
1646   help_flag = has_option (line, "--help");
1647   resolve_flag = has_option (line, "--resolve");
1648   host_flag = has_option (line, "--hosttable");
1649   dead_flag = has_option (line, "--dead");
1650   alive_flag = has_option (line, "--alive");
1651   line = skip_options (line);
1652   add_flag = !!*line;
1653
1654   if (help_flag)
1655     {
1656       err = ks_action_help (ctrl, line);
1657       goto leave;
1658     }
1659
1660   if (resolve_flag)
1661     {
1662       err = ks_action_resolve (ctrl, ctrl->server_local->keyservers);
1663       if (err)
1664         goto leave;
1665     }
1666
1667   if (alive_flag && dead_flag)
1668     {
1669       err = set_error (GPG_ERR_ASS_PARAMETER, "no support for zombies");
1670       goto leave;
1671     }
1672   if (dead_flag)
1673     {
1674       err = check_owner_permission (ctx, "no permission to use --dead");
1675       if (err)
1676         goto leave;
1677     }
1678   if (alive_flag || dead_flag)
1679     {
1680       if (!*line)
1681         {
1682           err = set_error (GPG_ERR_ASS_PARAMETER, "name of host missing");
1683           goto leave;
1684         }
1685
1686       err = ks_hkp_mark_host (ctrl, line, alive_flag);
1687       if (err)
1688         goto leave;
1689     }
1690
1691   if (host_flag)
1692     {
1693       err = ks_hkp_print_hosttable (ctrl);
1694       if (err)
1695         goto leave;
1696     }
1697   if (resolve_flag || host_flag || alive_flag || dead_flag)
1698     goto leave;
1699
1700   if (add_flag)
1701     {
1702       item = xtrymalloc (sizeof *item + strlen (line));
1703       if (!item)
1704         {
1705           err = gpg_error_from_syserror ();
1706           goto leave;
1707         }
1708       item->next = NULL;
1709       item->parsed_uri = NULL;
1710       strcpy (item->uri, line);
1711
1712 #if USE_LDAP
1713       if (ldap_uri_p (item->uri))
1714         err = ldap_parse_uri (&item->parsed_uri, line);
1715       else
1716 #endif
1717         {
1718           err = http_parse_uri (&item->parsed_uri, line, 1);
1719         }
1720       if (err)
1721         {
1722           xfree (item);
1723           goto leave;
1724         }
1725     }
1726   if (clear_flag)
1727     release_ctrl_keyservers (ctrl);
1728   if (add_flag)
1729     {
1730       item->next = ctrl->server_local->keyservers;
1731       ctrl->server_local->keyservers = item;
1732     }
1733
1734   if (!add_flag && !clear_flag && !help_flag) /* List configured keyservers.  */
1735     {
1736       uri_item_t u;
1737
1738       for (u=ctrl->server_local->keyservers; u; u = u->next)
1739         dirmngr_status (ctrl, "KEYSERVER", u->uri, NULL);
1740     }
1741   err = 0;
1742
1743  leave:
1744   return leave_cmd (ctx, err);
1745 }
1746
1747
1748 \f
1749 static const char hlp_ks_search[] =
1750   "KS_SEARCH {<pattern>}\n"
1751   "\n"
1752   "Search the configured OpenPGP keyservers (see command KEYSERVER)\n"
1753   "for keys matching PATTERN";
1754 static gpg_error_t
1755 cmd_ks_search (assuan_context_t ctx, char *line)
1756 {
1757   ctrl_t ctrl = assuan_get_pointer (ctx);
1758   gpg_error_t err;
1759   strlist_t list, sl;
1760   char *p;
1761   estream_t outfp;
1762
1763   /* No options for now.  */
1764   line = skip_options (line);
1765
1766   /* Break the line down into an strlist.  Each pattern is
1767      percent-plus escaped. */
1768   list = NULL;
1769   for (p=line; *p; line = p)
1770     {
1771       while (*p && *p != ' ')
1772         p++;
1773       if (*p)
1774         *p++ = 0;
1775       if (*line)
1776         {
1777           sl = xtrymalloc (sizeof *sl + strlen (line));
1778           if (!sl)
1779             {
1780               err = gpg_error_from_syserror ();
1781               goto leave;
1782             }
1783           sl->flags = 0;
1784           strcpy_escaped_plus (sl->d, line);
1785           sl->next = list;
1786           list = sl;
1787         }
1788     }
1789
1790   /* Setup an output stream and perform the search.  */
1791   outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1792   if (!outfp)
1793     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1794   else
1795     {
1796       err = ks_action_search (ctrl, ctrl->server_local->keyservers,
1797                               list, outfp);
1798       es_fclose (outfp);
1799     }
1800
1801  leave:
1802   free_strlist (list);
1803   return leave_cmd (ctx, err);
1804 }
1805
1806
1807 \f
1808 static const char hlp_ks_get[] =
1809   "KS_GET {<pattern>}\n"
1810   "\n"
1811   "Get the keys matching PATTERN from the configured OpenPGP keyservers\n"
1812   "(see command KEYSERVER).  Each pattern should be a keyid, a fingerprint,\n"
1813   "or an exact name indicated by the '=' prefix.";
1814 static gpg_error_t
1815 cmd_ks_get (assuan_context_t ctx, char *line)
1816 {
1817   ctrl_t ctrl = assuan_get_pointer (ctx);
1818   gpg_error_t err;
1819   strlist_t list, sl;
1820   char *p;
1821   estream_t outfp;
1822
1823   /* No options for now.  */
1824   line = skip_options (line);
1825
1826   /* Break the line into a strlist.  Each pattern is by
1827      definition percent-plus escaped.  However we only support keyids
1828      and fingerprints and thus the client has no need to apply the
1829      escaping.  */
1830   list = NULL;
1831   for (p=line; *p; line = p)
1832     {
1833       while (*p && *p != ' ')
1834         p++;
1835       if (*p)
1836         *p++ = 0;
1837       if (*line)
1838         {
1839           sl = xtrymalloc (sizeof *sl + strlen (line));
1840           if (!sl)
1841             {
1842               err = gpg_error_from_syserror ();
1843               goto leave;
1844             }
1845           sl->flags = 0;
1846           strcpy_escaped_plus (sl->d, line);
1847           sl->next = list;
1848           list = sl;
1849         }
1850     }
1851
1852   /* Setup an output stream and perform the get.  */
1853   outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1854   if (!outfp)
1855     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1856   else
1857     {
1858       err = ks_action_get (ctrl, ctrl->server_local->keyservers, list, outfp);
1859       es_fclose (outfp);
1860     }
1861
1862  leave:
1863   free_strlist (list);
1864   return leave_cmd (ctx, err);
1865 }
1866
1867
1868 static const char hlp_ks_fetch[] =
1869   "KS_FETCH <URL>\n"
1870   "\n"
1871   "Get the key(s) from URL.";
1872 static gpg_error_t
1873 cmd_ks_fetch (assuan_context_t ctx, char *line)
1874 {
1875   ctrl_t ctrl = assuan_get_pointer (ctx);
1876   gpg_error_t err;
1877   estream_t outfp;
1878
1879   /* No options for now.  */
1880   line = skip_options (line);
1881
1882   /* Setup an output stream and perform the get.  */
1883   outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1884   if (!outfp)
1885     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1886   else
1887     {
1888       err = ks_action_fetch (ctrl, line, outfp);
1889       es_fclose (outfp);
1890     }
1891
1892   return leave_cmd (ctx, err);
1893 }
1894
1895
1896 \f
1897 static const char hlp_ks_put[] =
1898   "KS_PUT\n"
1899   "\n"
1900   "Send a key to the configured OpenPGP keyservers.  The actual key material\n"
1901   "is then requested by Dirmngr using\n"
1902   "\n"
1903   "  INQUIRE KEYBLOCK\n"
1904   "\n"
1905   "The client shall respond with a binary version of the keyblock (e.g.,\n"
1906   "the output of `gpg --export KEYID').  For LDAP\n"
1907   "keyservers Dirmngr may ask for meta information of the provided keyblock\n"
1908   "using:\n"
1909   "\n"
1910   "  INQUIRE KEYBLOCK_INFO\n"
1911   "\n"
1912   "The client shall respond with a colon delimited info lines (the output\n"
1913   "of 'for x in keys sigs; do gpg --list-$x --with-colons KEYID; done').\n";
1914 static gpg_error_t
1915 cmd_ks_put (assuan_context_t ctx, char *line)
1916 {
1917   ctrl_t ctrl = assuan_get_pointer (ctx);
1918   gpg_error_t err;
1919   unsigned char *value = NULL;
1920   size_t valuelen;
1921   unsigned char *info = NULL;
1922   size_t infolen;
1923
1924   /* No options for now.  */
1925   line = skip_options (line);
1926
1927   /* Ask for the key material.  */
1928   err = assuan_inquire (ctx, "KEYBLOCK",
1929                         &value, &valuelen, MAX_KEYBLOCK_LENGTH);
1930   if (err)
1931     {
1932       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1933       goto leave;
1934     }
1935
1936   if (!valuelen) /* No data returned; return a comprehensible error. */
1937     {
1938       err = gpg_error (GPG_ERR_MISSING_CERT);
1939       goto leave;
1940     }
1941
1942   /* Ask for the key meta data. Not actually needed for HKP servers
1943      but we do it anyway to test the client implementaion.  */
1944   err = assuan_inquire (ctx, "KEYBLOCK_INFO",
1945                         &info, &infolen, MAX_KEYBLOCK_LENGTH);
1946   if (err)
1947     {
1948       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1949       goto leave;
1950     }
1951
1952   /* Send the key.  */
1953   err = ks_action_put (ctrl, ctrl->server_local->keyservers,
1954                        value, valuelen, info, infolen);
1955
1956  leave:
1957   xfree (info);
1958   xfree (value);
1959   return leave_cmd (ctx, err);
1960 }
1961
1962
1963
1964 \f
1965 static const char hlp_getinfo[] =
1966   "GETINFO <what>\n"
1967   "\n"
1968   "Multi purpose command to return certain information.  \n"
1969   "Supported values of WHAT are:\n"
1970   "\n"
1971   "version     - Return the version of the program.\n"
1972   "pid         - Return the process id of the server.\n"
1973   "\n"
1974   "socket_name - Return the name of the socket.\n";
1975 static gpg_error_t
1976 cmd_getinfo (assuan_context_t ctx, char *line)
1977 {
1978   gpg_error_t err;
1979
1980   if (!strcmp (line, "version"))
1981     {
1982       const char *s = VERSION;
1983       err = assuan_send_data (ctx, s, strlen (s));
1984     }
1985   else if (!strcmp (line, "pid"))
1986     {
1987       char numbuf[50];
1988
1989       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1990       err = assuan_send_data (ctx, numbuf, strlen (numbuf));
1991     }
1992   else if (!strcmp (line, "socket_name"))
1993     {
1994       const char *s = dirmngr_user_socket_name ();
1995
1996       if (!s)
1997         s = dirmngr_sys_socket_name ();
1998
1999       if (s)
2000         err = assuan_send_data (ctx, s, strlen (s));
2001       else
2002         err = gpg_error (GPG_ERR_NO_DATA);
2003     }
2004   else
2005     err = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
2006
2007   return leave_cmd (ctx, err);
2008 }
2009
2010
2011 \f
2012 static const char hlp_killdirmngr[] =
2013   "KILLDIRMNGR\n"
2014   "\n"
2015   "This command allows a user - given sufficient permissions -\n"
2016   "to kill this dirmngr process.\n";
2017 static gpg_error_t
2018 cmd_killdirmngr (assuan_context_t ctx, char *line)
2019 {
2020   ctrl_t ctrl = assuan_get_pointer (ctx);
2021   gpg_error_t err;
2022
2023   (void)line;
2024
2025   if (opt.system_daemon)
2026     {
2027       if (opt.system_service)
2028         err = set_error (GPG_ERR_NOT_SUPPORTED,
2029                          "can't do that whilst running as system service");
2030       else
2031         err = check_owner_permission (ctx,
2032                                       "no permission to kill this process");
2033     }
2034   else
2035     err = 0;
2036
2037   if (!err)
2038     {
2039       ctrl->server_local->stopme = 1;
2040       err = gpg_error (GPG_ERR_EOF);
2041     }
2042   return err;
2043 }
2044
2045
2046 static const char hlp_reloaddirmngr[] =
2047   "RELOADDIRMNGR\n"
2048   "\n"
2049   "This command is an alternative to SIGHUP\n"
2050   "to reload the configuration.";
2051 static gpg_error_t
2052 cmd_reloaddirmngr (assuan_context_t ctx, char *line)
2053 {
2054   (void)ctx;
2055   (void)line;
2056
2057  if (opt.system_daemon)
2058     {
2059 #ifndef HAVE_W32_SYSTEM
2060       {
2061         gpg_err_code_t ec;
2062         assuan_peercred_t cred;
2063
2064         ec = gpg_err_code (assuan_get_peercred (ctx, &cred));
2065         if (!ec && cred->uid)
2066           ec = GPG_ERR_EPERM; /* Only root may terminate.  */
2067         if (ec)
2068           return set_error (ec, "no permission to reload this process");
2069       }
2070 #endif
2071     }
2072
2073   dirmngr_sighup_action ();
2074   return 0;
2075 }
2076
2077
2078
2079 \f
2080 /* Tell the assuan library about our commands. */
2081 static int
2082 register_commands (assuan_context_t ctx)
2083 {
2084   static struct {
2085     const char *name;
2086     assuan_handler_t handler;
2087     const char * const help;
2088   } table[] = {
2089     { "DNS_CERT",   cmd_dns_cert,   hlp_dns_cert },
2090     { "LDAPSERVER", cmd_ldapserver, hlp_ldapserver },
2091     { "ISVALID",    cmd_isvalid,    hlp_isvalid },
2092     { "CHECKCRL",   cmd_checkcrl,   hlp_checkcrl },
2093     { "CHECKOCSP",  cmd_checkocsp,  hlp_checkocsp },
2094     { "LOOKUP",     cmd_lookup,     hlp_lookup },
2095     { "LOADCRL",    cmd_loadcrl,    hlp_loadcrl },
2096     { "LISTCRLS",   cmd_listcrls,   hlp_listcrls },
2097     { "CACHECERT",  cmd_cachecert,  hlp_cachecert },
2098     { "VALIDATE",   cmd_validate,   hlp_validate },
2099     { "KEYSERVER",  cmd_keyserver,  hlp_keyserver },
2100     { "KS_SEARCH",  cmd_ks_search,  hlp_ks_search },
2101     { "KS_GET",     cmd_ks_get,     hlp_ks_get },
2102     { "KS_FETCH",   cmd_ks_fetch,   hlp_ks_fetch },
2103     { "KS_PUT",     cmd_ks_put,     hlp_ks_put },
2104     { "GETINFO",    cmd_getinfo,    hlp_getinfo },
2105     { "KILLDIRMNGR",cmd_killdirmngr,hlp_killdirmngr },
2106     { "RELOADDIRMNGR",cmd_reloaddirmngr,hlp_reloaddirmngr },
2107     { NULL, NULL }
2108   };
2109   int i, j, rc;
2110
2111   for (i=j=0; table[i].name; i++)
2112     {
2113       rc = assuan_register_command (ctx, table[i].name, table[i].handler,
2114                                     table[i].help);
2115       if (rc)
2116         return rc;
2117     }
2118   return 0;
2119 }
2120
2121
2122 /* Note that we do not reset the list of configured keyservers.  */
2123 static gpg_error_t
2124 reset_notify (assuan_context_t ctx, char *line)
2125 {
2126   ctrl_t ctrl = assuan_get_pointer (ctx);
2127   (void)line;
2128
2129 #if USE_LDAP
2130   ldapserver_list_free (ctrl->server_local->ldapservers);
2131 #endif /*USE_LDAP*/
2132   ctrl->server_local->ldapservers = NULL;
2133   return 0;
2134 }
2135
2136
2137 /* Startup the server and run the main command loop.  With FD = -1,
2138    use stdin/stdout. */
2139 void
2140 start_command_handler (assuan_fd_t fd)
2141 {
2142   static const char hello[] = "Dirmngr " VERSION " at your service";
2143   static char *hello_line;
2144   int rc;
2145   assuan_context_t ctx;
2146   ctrl_t ctrl;
2147
2148   ctrl = xtrycalloc (1, sizeof *ctrl);
2149   if (ctrl)
2150     ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
2151   if (!ctrl || !ctrl->server_local)
2152     {
2153       log_error (_("can't allocate control structure: %s\n"),
2154                  strerror (errno));
2155       xfree (ctrl);
2156       return;
2157     }
2158
2159   dirmngr_init_default_ctrl (ctrl);
2160
2161   rc = assuan_new (&ctx);
2162   if (rc)
2163     {
2164       log_error (_("failed to allocate assuan context: %s\n"),
2165                  gpg_strerror (rc));
2166       dirmngr_exit (2);
2167     }
2168
2169   if (fd == ASSUAN_INVALID_FD)
2170     {
2171       assuan_fd_t filedes[2];
2172
2173       filedes[0] = assuan_fdopen (0);
2174       filedes[1] = assuan_fdopen (1);
2175       rc = assuan_init_pipe_server (ctx, filedes);
2176     }
2177   else
2178     {
2179       rc = assuan_init_socket_server (ctx, fd, ASSUAN_SOCKET_SERVER_ACCEPTED);
2180     }
2181
2182   if (rc)
2183     {
2184       assuan_release (ctx);
2185       log_error (_("failed to initialize the server: %s\n"),
2186                  gpg_strerror(rc));
2187       dirmngr_exit (2);
2188     }
2189
2190   rc = register_commands (ctx);
2191   if (rc)
2192     {
2193       log_error (_("failed to the register commands with Assuan: %s\n"),
2194                  gpg_strerror(rc));
2195       dirmngr_exit (2);
2196     }
2197
2198
2199   if (!hello_line)
2200     {
2201       size_t n;
2202       const char *cfgname;
2203
2204       cfgname = opt.config_filename? opt.config_filename : "[none]";
2205
2206       n = (30 + strlen (opt.homedir) + strlen (cfgname)
2207            + strlen (hello) + 1);
2208       hello_line = xmalloc (n+1);
2209       snprintf (hello_line, n,
2210                 "Home: %s\n"
2211                 "Config: %s\n"
2212                 "%s",
2213                 opt.homedir,
2214                 cfgname,
2215                 hello);
2216       hello_line[n] = 0;
2217     }
2218
2219   ctrl->server_local->assuan_ctx = ctx;
2220   assuan_set_pointer (ctx, ctrl);
2221
2222   assuan_set_hello_line (ctx, hello_line);
2223   assuan_register_option_handler (ctx, option_handler);
2224   assuan_register_reset_notify (ctx, reset_notify);
2225
2226   for (;;)
2227     {
2228       rc = assuan_accept (ctx);
2229       if (rc == -1)
2230         break;
2231       if (rc)
2232         {
2233           log_info (_("Assuan accept problem: %s\n"), gpg_strerror (rc));
2234           break;
2235         }
2236
2237 #ifndef HAVE_W32_SYSTEM
2238       if (opt.verbose)
2239         {
2240           assuan_peercred_t peercred;
2241
2242           if (!assuan_get_peercred (ctx, &peercred))
2243             log_info ("connection from process %ld (%ld:%ld)\n",
2244                       (long)peercred->pid, (long)peercred->uid,
2245                       (long)peercred->gid);
2246         }
2247 #endif
2248
2249       rc = assuan_process (ctx);
2250       if (rc)
2251         {
2252           log_info (_("Assuan processing failed: %s\n"), gpg_strerror (rc));
2253           continue;
2254         }
2255     }
2256
2257 #if USE_LDAP
2258   ldap_wrapper_connection_cleanup (ctrl);
2259
2260   ldapserver_list_free (ctrl->server_local->ldapservers);
2261 #endif /*USE_LDAP*/
2262   ctrl->server_local->ldapservers = NULL;
2263
2264   ctrl->server_local->assuan_ctx = NULL;
2265   assuan_release (ctx);
2266
2267   if (ctrl->server_local->stopme)
2268     dirmngr_exit (0);
2269
2270   if (ctrl->refcount)
2271     log_error ("oops: connection control structure still referenced (%d)\n",
2272                ctrl->refcount);
2273   else
2274     {
2275       release_ctrl_ocsp_certs (ctrl);
2276       xfree (ctrl->server_local);
2277       dirmngr_deinit_default_ctrl (ctrl);
2278       xfree (ctrl);
2279     }
2280 }
2281
2282
2283 /* Send a status line back to the client.  KEYWORD is the status
2284    keyword, the optional string arguments are blank separated added to
2285    the line, the last argument must be a NULL. */
2286 gpg_error_t
2287 dirmngr_status (ctrl_t ctrl, const char *keyword, ...)
2288 {
2289   gpg_error_t err = 0;
2290   va_list arg_ptr;
2291   const char *text;
2292
2293   va_start (arg_ptr, keyword);
2294
2295   if (ctrl->server_local)
2296     {
2297       assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2298       char buf[950], *p;
2299       size_t n;
2300
2301       p = buf;
2302       n = 0;
2303       while ( (text = va_arg (arg_ptr, const char *)) )
2304         {
2305           if (n)
2306             {
2307               *p++ = ' ';
2308               n++;
2309             }
2310           for ( ; *text && n < DIM (buf)-2; n++)
2311             *p++ = *text++;
2312         }
2313       *p = 0;
2314       err = assuan_write_status (ctx, keyword, buf);
2315     }
2316
2317   va_end (arg_ptr);
2318   return err;
2319 }
2320
2321
2322 /* Print a help status line.  TEXTLEN gives the length of the text
2323    from TEXT to be printed.  The function splits text at LFs.  */
2324 gpg_error_t
2325 dirmngr_status_help (ctrl_t ctrl, const char *text)
2326 {
2327   gpg_error_t err = 0;
2328
2329   if (ctrl->server_local)
2330     {
2331       assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2332       char buf[950], *p;
2333       size_t n;
2334
2335       do
2336         {
2337           p = buf;
2338           n = 0;
2339           for ( ; *text && *text != '\n' && n < DIM (buf)-2; n++)
2340             *p++ = *text++;
2341           if (*text == '\n')
2342             text++;
2343           *p = 0;
2344           err = assuan_write_status (ctx, "#", buf);
2345         }
2346       while (!err && *text);
2347     }
2348
2349   return err;
2350 }
2351
2352 /* Send a tick progress indicator back.  Fixme: This is only done for
2353    the currently active channel.  */
2354 gpg_error_t
2355 dirmngr_tick (ctrl_t ctrl)
2356 {
2357   static time_t next_tick = 0;
2358   gpg_error_t err = 0;
2359   time_t now = time (NULL);
2360
2361   if (!next_tick)
2362     {
2363       next_tick = now + 1;
2364     }
2365   else if ( now > next_tick )
2366     {
2367       if (ctrl)
2368         {
2369           err = dirmngr_status (ctrl, "PROGRESS", "tick", "? 0 0", NULL);
2370           if (err)
2371             {
2372               /* Take this as in indication for a cancel request.  */
2373               err = gpg_error (GPG_ERR_CANCELED);
2374             }
2375           now = time (NULL);
2376         }
2377
2378       next_tick = now + 1;
2379     }
2380   return err;
2381 }