dirmngr: Add option --keyserver.
[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 if (!strcmp (key, "honor-keyserver-url-used"))
630     {
631       /* Return an error if we are running in TOR mode.  */
632       if (opt.use_tor)
633         err = gpg_error (GPG_ERR_FORBIDDEN);
634     }
635   else
636     err = gpg_error (GPG_ERR_UNKNOWN_OPTION);
637
638   return err;
639 }
640
641
642 \f
643 static const char hlp_dns_cert[] =
644   "DNS_CERT <subtype> <name>\n"
645   "DNS_CERT --pka <user_id>\n"
646   "\n"
647   "Return the CERT record for <name>.  <subtype> is one of\n"
648   "  *     Return the first record of any supported subtype\n"
649   "  PGP   Return the first record of subtype PGP (3)\n"
650   "  IPGP  Return the first record of subtype IPGP (6)\n"
651   "If the content of a certifciate is available (PGP) it is returned\n"
652   "by data lines.  Fingerprints and URLs are returned via status lines.\n"
653   "In --pka mode the fingerprint and if available an URL is returned.";
654 static gpg_error_t
655 cmd_dns_cert (assuan_context_t ctx, char *line)
656 {
657   /* ctrl_t ctrl = assuan_get_pointer (ctx); */
658   gpg_error_t err = 0;
659   int pka_mode;
660   char *mbox = NULL;
661   char *namebuf = NULL;
662   char *encodedhash = NULL;
663   const char *name;
664   int certtype;
665   char *p;
666   void *key = NULL;
667   size_t keylen;
668   unsigned char *fpr = NULL;
669   size_t fprlen;
670   char *url = NULL;
671
672   pka_mode = has_option (line, "--pka");
673   line = skip_options (line);
674   if (pka_mode)
675     ; /* No need to parse here - we do this later.  */
676   else
677     {
678       p = strchr (line, ' ');
679       if (!p)
680         {
681           err = PARM_ERROR ("missing arguments");
682           goto leave;
683         }
684       *p++ = 0;
685       if (!strcmp (line, "*"))
686         certtype = DNS_CERTTYPE_ANY;
687       else if (!strcmp (line, "IPGP"))
688         certtype = DNS_CERTTYPE_IPGP;
689       else if (!strcmp (line, "PGP"))
690         certtype = DNS_CERTTYPE_PGP;
691       else
692         {
693           err = PARM_ERROR ("unknown subtype");
694           goto leave;
695         }
696       while (spacep (p))
697         p++;
698       line = p;
699       if (!*line)
700         {
701           err = PARM_ERROR ("name missing");
702           goto leave;
703         }
704     }
705
706   if (opt.use_tor)
707     {
708       err = gpg_error (GPG_ERR_FORBIDDEN);
709       goto leave;
710     }
711
712   if (pka_mode)
713     {
714       char *domain;  /* Points to mbox.  */
715       char hashbuf[20];
716
717       mbox = mailbox_from_userid (line);
718       if (!mbox || !(domain = strchr (mbox, '@')))
719         {
720           err = set_error (GPG_ERR_INV_USER_ID, "no mailbox in user id");
721           goto leave;
722         }
723       *domain++ = 0;
724
725       gcry_md_hash_buffer (GCRY_MD_SHA1, hashbuf, mbox, strlen (mbox));
726       encodedhash = zb32_encode (hashbuf, 8*20);
727       if (!encodedhash)
728         {
729           err = gpg_error_from_syserror ();
730           goto leave;
731         }
732       namebuf = strconcat (encodedhash, "._pka.", domain, NULL);
733       if (!namebuf)
734         {
735           err = gpg_error_from_syserror ();
736           goto leave;
737         }
738       name = namebuf;
739       certtype = DNS_CERTTYPE_IPGP;
740     }
741   else
742     name = line;
743
744   err = get_dns_cert (name, certtype, &key, &keylen, &fpr, &fprlen, &url);
745   if (err)
746     goto leave;
747
748   if (key)
749     {
750       err = data_line_write (ctx, key, keylen);
751       if (err)
752         goto leave;
753     }
754
755   if (fpr)
756     {
757       char *tmpstr;
758
759       tmpstr = bin2hex (fpr, fprlen, NULL);
760       if (!tmpstr)
761         err = gpg_error_from_syserror ();
762       else
763         {
764           err = assuan_write_status (ctx, "FPR", tmpstr);
765           xfree (tmpstr);
766         }
767       if (err)
768         goto leave;
769     }
770
771   if (url)
772     {
773       err = assuan_write_status (ctx, "URL", url);
774       if (err)
775         goto leave;
776     }
777
778
779  leave:
780   xfree (key);
781   xfree (fpr);
782   xfree (url);
783   xfree (mbox);
784   xfree (namebuf);
785   xfree (encodedhash);
786   return leave_cmd (ctx, err);
787 }
788
789
790 \f
791 static const char hlp_ldapserver[] =
792   "LDAPSERVER <data>\n"
793   "\n"
794   "Add a new LDAP server to the list of configured LDAP servers.\n"
795   "DATA is in the same format as expected in the configure file.";
796 static gpg_error_t
797 cmd_ldapserver (assuan_context_t ctx, char *line)
798 {
799 #if USE_LDAP
800   ctrl_t ctrl = assuan_get_pointer (ctx);
801   ldap_server_t server;
802   ldap_server_t *last_next_p;
803
804   while (spacep (line))
805     line++;
806   if (*line == '\0')
807     return leave_cmd (ctx, PARM_ERROR (_("ldapserver missing")));
808
809   server = ldapserver_parse_one (line, "", 0);
810   if (! server)
811     return leave_cmd (ctx, gpg_error (GPG_ERR_INV_ARG));
812
813   last_next_p = &ctrl->server_local->ldapservers;
814   while (*last_next_p)
815     last_next_p = &(*last_next_p)->next;
816   *last_next_p = server;
817   return leave_cmd (ctx, 0);
818 #else
819   (void)line;
820   return leave_cmd (ctx, gpg_error (GPG_ERR_NOT_IMPLEMENTED));
821 #endif
822 }
823
824
825 static const char hlp_isvalid[] =
826   "ISVALID [--only-ocsp] [--force-default-responder]"
827   " <certificate_id>|<certificate_fpr>\n"
828   "\n"
829   "This command checks whether the certificate identified by the\n"
830   "certificate_id is valid.  This is done by consulting CRLs or\n"
831   "whatever has been configured.  Note, that the returned error codes\n"
832   "are from gpg-error.h.  The command may callback using the inquire\n"
833   "function.  See the manual for details.\n"
834   "\n"
835   "The CERTIFICATE_ID is a hex encoded string consisting of two parts,\n"
836   "delimited by a single dot.  The first part is the SHA-1 hash of the\n"
837   "issuer name and the second part the serial number.\n"
838   "\n"
839   "Alternatively the certificate's fingerprint may be given in which\n"
840   "case an OCSP request is done before consulting the CRL.\n"
841   "\n"
842   "If the option --only-ocsp is given, no fallback to a CRL check will\n"
843   "be used.\n"
844   "\n"
845   "If the option --force-default-responder is given, only the default\n"
846   "OCSP responder will be used and any other methods of obtaining an\n"
847   "OCSP responder URL won't be used.";
848 static gpg_error_t
849 cmd_isvalid (assuan_context_t ctx, char *line)
850 {
851   ctrl_t ctrl = assuan_get_pointer (ctx);
852   char *issuerhash, *serialno;
853   gpg_error_t err;
854   int did_inquire = 0;
855   int ocsp_mode = 0;
856   int only_ocsp;
857   int force_default_responder;
858
859   only_ocsp = has_option (line, "--only-ocsp");
860   force_default_responder = has_option (line, "--force-default-responder");
861   line = skip_options (line);
862
863   issuerhash = xstrdup (line); /* We need to work on a copy of the
864                                   line because that same Assuan
865                                   context may be used for an inquiry.
866                                   That is because Assuan reuses its
867                                   line buffer.
868                                    */
869
870   serialno = strchr (issuerhash, '.');
871   if (serialno)
872     *serialno++ = 0;
873   else
874     {
875       char *endp = strchr (issuerhash, ' ');
876       if (endp)
877         *endp = 0;
878       if (strlen (issuerhash) != 40)
879         {
880           xfree (issuerhash);
881           return leave_cmd (ctx, PARM_ERROR (_("serialno missing in cert ID")));
882         }
883       ocsp_mode = 1;
884     }
885
886
887  again:
888   if (ocsp_mode)
889     {
890       /* Note, that we ignore the given issuer hash and instead rely
891          on the current certificate semantics used with this
892          command. */
893       if (!opt.allow_ocsp)
894         err = gpg_error (GPG_ERR_NOT_SUPPORTED);
895       else
896         err = ocsp_isvalid (ctrl, NULL, NULL, force_default_responder);
897       /* Fixme: If we got no ocsp response and --only-ocsp is not used
898          we should fall back to CRL mode.  Thus we need to clear
899          OCSP_MODE, get the issuerhash and the serialno from the
900          current certificate and jump to again. */
901     }
902   else if (only_ocsp)
903     err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
904   else
905     {
906       switch (crl_cache_isvalid (ctrl,
907                                  issuerhash, serialno,
908                                  ctrl->force_crl_refresh))
909         {
910         case CRL_CACHE_VALID:
911           err = 0;
912           break;
913         case CRL_CACHE_INVALID:
914           err = gpg_error (GPG_ERR_CERT_REVOKED);
915           break;
916         case CRL_CACHE_DONTKNOW:
917           if (did_inquire)
918             err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
919           else if (!(err = inquire_cert_and_load_crl (ctx)))
920             {
921               did_inquire = 1;
922               goto again;
923             }
924           break;
925         case CRL_CACHE_CANTUSE:
926           err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
927           break;
928         default:
929           log_fatal ("crl_cache_isvalid returned invalid code\n");
930         }
931     }
932
933   xfree (issuerhash);
934   return leave_cmd (ctx, err);
935 }
936
937
938 /* If the line contains a SHA-1 fingerprint as the first argument,
939    return the FPR vuffer on success.  The function checks that the
940    fingerprint consists of valid characters and prints and error
941    message if it does not and returns NULL.  Fingerprints are
942    considered optional and thus no explicit error is returned. NULL is
943    also returned if there is no fingerprint at all available.
944    FPR must be a caller provided buffer of at least 20 bytes.
945
946    Note that colons within the fingerprint are allowed to separate 2
947    hex digits; this allows for easier cutting and pasting using the
948    usual fingerprint rendering.
949 */
950 static unsigned char *
951 get_fingerprint_from_line (const char *line, unsigned char *fpr)
952 {
953   const char *s;
954   int i;
955
956   for (s=line, i=0; *s && *s != ' '; s++ )
957     {
958       if ( hexdigitp (s) && hexdigitp (s+1) )
959         {
960           if ( i >= 20 )
961             return NULL;  /* Fingerprint too long.  */
962           fpr[i++] = xtoi_2 (s);
963           s++;
964         }
965       else if ( *s != ':' )
966         return NULL; /* Invalid.  */
967     }
968   if ( i != 20 )
969     return NULL; /* Fingerprint to short.  */
970   return fpr;
971 }
972
973
974
975 static const char hlp_checkcrl[] =
976   "CHECKCRL [<fingerprint>]\n"
977   "\n"
978   "Check whether the certificate with FINGERPRINT (SHA-1 hash of the\n"
979   "entire X.509 certificate blob) is valid or not by consulting the\n"
980   "CRL responsible for this certificate.  If the fingerprint has not\n"
981   "been given or the certificate is not known, the function \n"
982   "inquires the certificate using an\n"
983   "\n"
984   "  INQUIRE TARGETCERT\n"
985   "\n"
986   "and the caller is expected to return the certificate for the\n"
987   "request (which should match FINGERPRINT) as a binary blob.\n"
988   "Processing then takes place without further interaction; in\n"
989   "particular dirmngr tries to locate other required certificate by\n"
990   "its own mechanism which includes a local certificate store as well\n"
991   "as a list of trusted root certificates.\n"
992   "\n"
993   "The return value is the usual gpg-error code or 0 for ducesss;\n"
994   "i.e. the certificate validity has been confirmed by a valid CRL.";
995 static gpg_error_t
996 cmd_checkcrl (assuan_context_t ctx, char *line)
997 {
998   ctrl_t ctrl = assuan_get_pointer (ctx);
999   gpg_error_t err;
1000   unsigned char fprbuffer[20], *fpr;
1001   ksba_cert_t cert;
1002
1003   fpr = get_fingerprint_from_line (line, fprbuffer);
1004   cert = fpr? get_cert_byfpr (fpr) : NULL;
1005
1006   if (!cert)
1007     {
1008       /* We do not have this certificate yet or the fingerprint has
1009          not been given.  Inquire it from the client.  */
1010       unsigned char *value = NULL;
1011       size_t valuelen;
1012
1013       err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1014                            &value, &valuelen, MAX_CERT_LENGTH);
1015       if (err)
1016         {
1017           log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1018           goto leave;
1019         }
1020
1021       if (!valuelen) /* No data returned; return a comprehensible error. */
1022         err = gpg_error (GPG_ERR_MISSING_CERT);
1023       else
1024         {
1025           err = ksba_cert_new (&cert);
1026           if (!err)
1027             err = ksba_cert_init_from_mem (cert, value, valuelen);
1028         }
1029       xfree (value);
1030       if(err)
1031         goto leave;
1032     }
1033
1034   assert (cert);
1035
1036   err = crl_cache_cert_isvalid (ctrl, cert, ctrl->force_crl_refresh);
1037   if (gpg_err_code (err) == GPG_ERR_NO_CRL_KNOWN)
1038     {
1039       err = crl_cache_reload_crl (ctrl, cert);
1040       if (!err)
1041         err = crl_cache_cert_isvalid (ctrl, cert, 0);
1042     }
1043
1044  leave:
1045   ksba_cert_release (cert);
1046   return leave_cmd (ctx, err);
1047 }
1048
1049
1050 static const char hlp_checkocsp[] =
1051   "CHECKOCSP [--force-default-responder] [<fingerprint>]\n"
1052   "\n"
1053   "Check whether the certificate with FINGERPRINT (SHA-1 hash of the\n"
1054   "entire X.509 certificate blob) is valid or not by asking an OCSP\n"
1055   "responder responsible for this certificate.  The optional\n"
1056   "fingerprint may be used for a quick check in case an OCSP check has\n"
1057   "been done for this certificate recently (we always cache OCSP\n"
1058   "responses for a couple of minutes). If the fingerprint has not been\n"
1059   "given or there is no cached result, the function inquires the\n"
1060   "certificate using an\n"
1061   "\n"
1062   "   INQUIRE TARGETCERT\n"
1063   "\n"
1064   "and the caller is expected to return the certificate for the\n"
1065   "request (which should match FINGERPRINT) as a binary blob.\n"
1066   "Processing then takes place without further interaction; in\n"
1067   "particular dirmngr tries to locate other required certificates by\n"
1068   "its own mechanism which includes a local certificate store as well\n"
1069   "as a list of trusted root certifciates.\n"
1070   "\n"
1071   "If the option --force-default-responder is given, only the default\n"
1072   "OCSP responder will be used and any other methods of obtaining an\n"
1073   "OCSP responder URL won't be used.\n"
1074   "\n"
1075   "The return value is the usual gpg-error code or 0 for ducesss;\n"
1076   "i.e. the certificate validity has been confirmed by a valid CRL.";
1077 static gpg_error_t
1078 cmd_checkocsp (assuan_context_t ctx, char *line)
1079 {
1080   ctrl_t ctrl = assuan_get_pointer (ctx);
1081   gpg_error_t err;
1082   unsigned char fprbuffer[20], *fpr;
1083   ksba_cert_t cert;
1084   int force_default_responder;
1085
1086   force_default_responder = has_option (line, "--force-default-responder");
1087   line = skip_options (line);
1088
1089   fpr = get_fingerprint_from_line (line, fprbuffer);
1090   cert = fpr? get_cert_byfpr (fpr) : NULL;
1091
1092   if (!cert)
1093     {
1094       /* We do not have this certificate yet or the fingerprint has
1095          not been given.  Inquire it from the client.  */
1096       unsigned char *value = NULL;
1097       size_t valuelen;
1098
1099       err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1100                            &value, &valuelen, MAX_CERT_LENGTH);
1101       if (err)
1102         {
1103           log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1104           goto leave;
1105         }
1106
1107       if (!valuelen) /* No data returned; return a comprehensible error. */
1108         err = gpg_error (GPG_ERR_MISSING_CERT);
1109       else
1110         {
1111           err = ksba_cert_new (&cert);
1112           if (!err)
1113             err = ksba_cert_init_from_mem (cert, value, valuelen);
1114         }
1115       xfree (value);
1116       if(err)
1117         goto leave;
1118     }
1119
1120   assert (cert);
1121
1122   if (!opt.allow_ocsp)
1123     err = gpg_error (GPG_ERR_NOT_SUPPORTED);
1124   else
1125     err = ocsp_isvalid (ctrl, cert, NULL, force_default_responder);
1126
1127  leave:
1128   ksba_cert_release (cert);
1129   return leave_cmd (ctx, err);
1130 }
1131
1132
1133
1134 static int
1135 lookup_cert_by_url (assuan_context_t ctx, const char *url)
1136 {
1137   ctrl_t ctrl = assuan_get_pointer (ctx);
1138   gpg_error_t err = 0;
1139   unsigned char *value = NULL;
1140   size_t valuelen;
1141
1142   /* Fetch single certificate given it's URL.  */
1143   err = fetch_cert_by_url (ctrl, url, &value, &valuelen);
1144   if (err)
1145     {
1146       log_error (_("fetch_cert_by_url failed: %s\n"), gpg_strerror (err));
1147       goto leave;
1148     }
1149
1150   /* Send the data, flush the buffer and then send an END. */
1151   err = assuan_send_data (ctx, value, valuelen);
1152   if (!err)
1153     err = assuan_send_data (ctx, NULL, 0);
1154   if (!err)
1155     err = assuan_write_line (ctx, "END");
1156   if (err)
1157     {
1158       log_error (_("error sending data: %s\n"), gpg_strerror (err));
1159       goto leave;
1160     }
1161
1162  leave:
1163
1164   return err;
1165 }
1166
1167
1168 /* Send the certificate, flush the buffer and then send an END. */
1169 static gpg_error_t
1170 return_one_cert (void *opaque, ksba_cert_t cert)
1171 {
1172   assuan_context_t ctx = opaque;
1173   gpg_error_t err;
1174   const unsigned char *der;
1175   size_t derlen;
1176
1177   der = ksba_cert_get_image (cert, &derlen);
1178   if (!der)
1179     err = gpg_error (GPG_ERR_INV_CERT_OBJ);
1180   else
1181     {
1182       err = assuan_send_data (ctx, der, derlen);
1183       if (!err)
1184         err = assuan_send_data (ctx, NULL, 0);
1185       if (!err)
1186         err = assuan_write_line (ctx, "END");
1187     }
1188   if (err)
1189     log_error (_("error sending data: %s\n"), gpg_strerror (err));
1190   return err;
1191 }
1192
1193
1194 /* Lookup certificates from the internal cache or using the ldap
1195    servers. */
1196 static int
1197 lookup_cert_by_pattern (assuan_context_t ctx, char *line,
1198                         int single, int cache_only)
1199 {
1200   gpg_error_t err = 0;
1201   char *p;
1202   strlist_t sl, list = NULL;
1203   int truncated = 0, truncation_forced = 0;
1204   int count = 0;
1205   int local_count = 0;
1206 #if USE_LDAP
1207   ctrl_t ctrl = assuan_get_pointer (ctx);
1208   unsigned char *value = NULL;
1209   size_t valuelen;
1210   struct ldapserver_iter ldapserver_iter;
1211   cert_fetch_context_t fetch_context;
1212 #endif /*USE_LDAP*/
1213   int any_no_data = 0;
1214
1215   /* Break the line down into an STRLIST */
1216   for (p=line; *p; line = p)
1217     {
1218       while (*p && *p != ' ')
1219         p++;
1220       if (*p)
1221         *p++ = 0;
1222
1223       if (*line)
1224         {
1225           sl = xtrymalloc (sizeof *sl + strlen (line));
1226           if (!sl)
1227             {
1228               err = gpg_error_from_errno (errno);
1229               goto leave;
1230             }
1231           memset (sl, 0, sizeof *sl);
1232           strcpy_escaped_plus (sl->d, line);
1233           sl->next = list;
1234           list = sl;
1235         }
1236     }
1237
1238   /* First look through the internal cache.  The certifcates retruned
1239      here are not counted towards the truncation limit.  */
1240   if (single && !cache_only)
1241     ; /* Do not read from the local cache in this case.  */
1242   else
1243     {
1244       for (sl=list; sl; sl = sl->next)
1245         {
1246           err = get_certs_bypattern (sl->d, return_one_cert, ctx);
1247           if (!err)
1248             local_count++;
1249           if (!err && single)
1250             goto ready;
1251
1252           if (gpg_err_code (err) == GPG_ERR_NO_DATA)
1253             {
1254               err = 0;
1255               if (cache_only)
1256                 any_no_data = 1;
1257             }
1258           else if (gpg_err_code (err) == GPG_ERR_INV_NAME && !cache_only)
1259             {
1260               /* No real fault because the internal pattern lookup
1261                  can't yet cope with all types of pattern.  */
1262               err = 0;
1263             }
1264           if (err)
1265             goto ready;
1266         }
1267     }
1268
1269   /* Loop over all configured servers unless we want only the
1270      certificates from the cache.  */
1271 #if USE_LDAP
1272   for (ldapserver_iter_begin (&ldapserver_iter, ctrl);
1273        !cache_only && !ldapserver_iter_end_p (&ldapserver_iter)
1274          && ldapserver_iter.server->host && !truncation_forced;
1275        ldapserver_iter_next (&ldapserver_iter))
1276     {
1277       ldap_server_t ldapserver = ldapserver_iter.server;
1278
1279       if (DBG_LOOKUP)
1280         log_debug ("cmd_lookup: trying %s:%d base=%s\n",
1281                    ldapserver->host, ldapserver->port,
1282                    ldapserver->base?ldapserver->base : "[default]");
1283
1284       /* Fetch certificates matching pattern */
1285       err = start_cert_fetch (ctrl, &fetch_context, list, ldapserver);
1286       if ( gpg_err_code (err) == GPG_ERR_NO_DATA )
1287         {
1288           if (DBG_LOOKUP)
1289             log_debug ("cmd_lookup: no data\n");
1290           err = 0;
1291           any_no_data = 1;
1292           continue;
1293         }
1294       if (err)
1295         {
1296           log_error (_("start_cert_fetch failed: %s\n"), gpg_strerror (err));
1297           goto leave;
1298         }
1299
1300       /* Fetch the certificates for this query. */
1301       while (!truncation_forced)
1302         {
1303           xfree (value); value = NULL;
1304           err = fetch_next_cert (fetch_context, &value, &valuelen);
1305           if (gpg_err_code (err) == GPG_ERR_NO_DATA )
1306             {
1307               err = 0;
1308               any_no_data = 1;
1309               break; /* Ready. */
1310             }
1311           if (gpg_err_code (err) == GPG_ERR_TRUNCATED)
1312             {
1313               truncated = 1;
1314               err = 0;
1315               break;  /* Ready.  */
1316             }
1317           if (gpg_err_code (err) == GPG_ERR_EOF)
1318             {
1319               err = 0;
1320               break; /* Ready. */
1321             }
1322           if (!err && !value)
1323             {
1324               err = gpg_error (GPG_ERR_BUG);
1325               goto leave;
1326             }
1327           if (err)
1328             {
1329               log_error (_("fetch_next_cert failed: %s\n"),
1330                          gpg_strerror (err));
1331               end_cert_fetch (fetch_context);
1332               goto leave;
1333             }
1334
1335           if (DBG_LOOKUP)
1336             log_debug ("cmd_lookup: returning one cert%s\n",
1337                        truncated? " (truncated)":"");
1338
1339           /* Send the data, flush the buffer and then send an END line
1340              as a certificate delimiter. */
1341           err = assuan_send_data (ctx, value, valuelen);
1342           if (!err)
1343             err = assuan_send_data (ctx, NULL, 0);
1344           if (!err)
1345             err = assuan_write_line (ctx, "END");
1346           if (err)
1347             {
1348               log_error (_("error sending data: %s\n"), gpg_strerror (err));
1349               end_cert_fetch (fetch_context);
1350               goto leave;
1351             }
1352
1353           if (++count >= opt.max_replies )
1354             {
1355               truncation_forced = 1;
1356               log_info (_("max_replies %d exceeded\n"), opt.max_replies );
1357             }
1358           if (single)
1359             break;
1360         }
1361
1362       end_cert_fetch (fetch_context);
1363     }
1364 #endif /*USE_LDAP*/
1365
1366  ready:
1367   if (truncated || truncation_forced)
1368     {
1369       char str[50];
1370
1371       sprintf (str, "%d", count);
1372       assuan_write_status (ctx, "TRUNCATED", str);
1373     }
1374
1375   if (!err && !count && !local_count && any_no_data)
1376     err = gpg_error (GPG_ERR_NO_DATA);
1377
1378  leave:
1379   free_strlist (list);
1380   return err;
1381 }
1382
1383
1384 static const char hlp_lookup[] =
1385   "LOOKUP [--url] [--single] [--cache-only] <pattern>\n"
1386   "\n"
1387   "Lookup certificates matching PATTERN. With --url the pattern is\n"
1388   "expected to be one URL.\n"
1389   "\n"
1390   "If --url is not given:  To allow for multiple patterns (which are ORed)\n"
1391   "quoting is required: Spaces are translated to \"+\" or \"%20\";\n"
1392   "obviously this requires that the usual escape quoting rules are applied.\n"
1393   "\n"
1394   "If --url is given no special escaping is required because URLs are\n"
1395   "already escaped this way.\n"
1396   "\n"
1397   "If --single is given the first and only the first match will be\n"
1398   "returned.  If --cache-only is _not_ given, no local query will be\n"
1399   "done.\n"
1400   "\n"
1401   "If --cache-only is given no external lookup is done so that only\n"
1402   "certificates from the cache may get returned.";
1403 static gpg_error_t
1404 cmd_lookup (assuan_context_t ctx, char *line)
1405 {
1406   gpg_error_t err;
1407   int lookup_url, single, cache_only;
1408
1409   lookup_url = has_leading_option (line, "--url");
1410   single = has_leading_option (line, "--single");
1411   cache_only = has_leading_option (line, "--cache-only");
1412   line = skip_options (line);
1413
1414   if (lookup_url && cache_only)
1415     err = gpg_error (GPG_ERR_NOT_FOUND);
1416   else if (lookup_url && single)
1417     err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1418   else if (lookup_url)
1419     err = lookup_cert_by_url (ctx, line);
1420   else
1421     err = lookup_cert_by_pattern (ctx, line, single, cache_only);
1422
1423   return leave_cmd (ctx, err);
1424 }
1425
1426
1427 static const char hlp_loadcrl[] =
1428   "LOADCRL [--url] <filename|url>\n"
1429   "\n"
1430   "Load the CRL in the file with name FILENAME into our cache.  Note\n"
1431   "that FILENAME should be given with an absolute path because\n"
1432   "Dirmngrs cwd is not known.  With --url the CRL is directly loaded\n"
1433   "from the given URL.\n"
1434   "\n"
1435   "This command is usually used by gpgsm using the invocation \"gpgsm\n"
1436   "--call-dirmngr loadcrl <filename>\".  A direct invocation of Dirmngr\n"
1437   "is not useful because gpgsm might need to callback gpgsm to ask for\n"
1438   "the CA's certificate.";
1439 static gpg_error_t
1440 cmd_loadcrl (assuan_context_t ctx, char *line)
1441 {
1442   ctrl_t ctrl = assuan_get_pointer (ctx);
1443   gpg_error_t err = 0;
1444   int use_url = has_leading_option (line, "--url");
1445
1446   line = skip_options (line);
1447
1448   if (use_url)
1449     {
1450       ksba_reader_t reader;
1451
1452       err = crl_fetch (ctrl, line, &reader);
1453       if (err)
1454         log_error (_("fetching CRL from '%s' failed: %s\n"),
1455                    line, gpg_strerror (err));
1456       else
1457         {
1458           err = crl_cache_insert (ctrl, line, reader);
1459           if (err)
1460             log_error (_("processing CRL from '%s' failed: %s\n"),
1461                        line, gpg_strerror (err));
1462           crl_close_reader (reader);
1463         }
1464     }
1465   else
1466     {
1467       char *buf;
1468
1469       buf = xtrymalloc (strlen (line)+1);
1470       if (!buf)
1471         err = gpg_error_from_syserror ();
1472       else
1473         {
1474           strcpy_escaped_plus (buf, line);
1475           err = crl_cache_load (ctrl, buf);
1476           xfree (buf);
1477         }
1478     }
1479
1480   return leave_cmd (ctx, err);
1481 }
1482
1483
1484 static const char hlp_listcrls[] =
1485   "LISTCRLS\n"
1486   "\n"
1487   "List the content of all CRLs in a readable format.  This command is\n"
1488   "usually used by gpgsm using the invocation \"gpgsm --call-dirmngr\n"
1489   "listcrls\".  It may also be used directly using \"dirmngr\n"
1490   "--list-crls\".";
1491 static gpg_error_t
1492 cmd_listcrls (assuan_context_t ctx, char *line)
1493 {
1494   gpg_error_t err;
1495   estream_t fp;
1496
1497   (void)line;
1498
1499   fp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1500   if (!fp)
1501     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1502   else
1503     {
1504       err = crl_cache_list (fp);
1505       es_fclose (fp);
1506     }
1507   return leave_cmd (ctx, err);
1508 }
1509
1510
1511 static const char hlp_cachecert[] =
1512   "CACHECERT\n"
1513   "\n"
1514   "Put a certificate into the internal cache.  This command might be\n"
1515   "useful if a client knows in advance certificates required for a\n"
1516   "test and wants to make sure they get added to the internal cache.\n"
1517   "It is also helpful for debugging.  To get the actual certificate,\n"
1518   "this command immediately inquires it using\n"
1519   "\n"
1520   "  INQUIRE TARGETCERT\n"
1521   "\n"
1522   "and the caller is expected to return the certificate for the\n"
1523   "request as a binary blob.";
1524 static gpg_error_t
1525 cmd_cachecert (assuan_context_t ctx, char *line)
1526 {
1527   ctrl_t ctrl = assuan_get_pointer (ctx);
1528   gpg_error_t err;
1529   ksba_cert_t cert = NULL;
1530   unsigned char *value = NULL;
1531   size_t valuelen;
1532
1533   (void)line;
1534
1535   err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1536                        &value, &valuelen, MAX_CERT_LENGTH);
1537   if (err)
1538     {
1539       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1540       goto leave;
1541     }
1542
1543   if (!valuelen) /* No data returned; return a comprehensible error. */
1544     err = gpg_error (GPG_ERR_MISSING_CERT);
1545   else
1546     {
1547       err = ksba_cert_new (&cert);
1548       if (!err)
1549         err = ksba_cert_init_from_mem (cert, value, valuelen);
1550     }
1551   xfree (value);
1552   if(err)
1553     goto leave;
1554
1555   err = cache_cert (cert);
1556
1557  leave:
1558   ksba_cert_release (cert);
1559   return leave_cmd (ctx, err);
1560 }
1561
1562
1563 static const char hlp_validate[] =
1564   "VALIDATE\n"
1565   "\n"
1566   "Validate a certificate using the certificate validation function\n"
1567   "used internally by dirmngr.  This command is only useful for\n"
1568   "debugging.  To get the actual certificate, this command immediately\n"
1569   "inquires it using\n"
1570   "\n"
1571   "  INQUIRE TARGETCERT\n"
1572   "\n"
1573   "and the caller is expected to return the certificate for the\n"
1574   "request as a binary blob.";
1575 static gpg_error_t
1576 cmd_validate (assuan_context_t ctx, char *line)
1577 {
1578   ctrl_t ctrl = assuan_get_pointer (ctx);
1579   gpg_error_t err;
1580   ksba_cert_t cert = NULL;
1581   unsigned char *value = NULL;
1582   size_t valuelen;
1583
1584   (void)line;
1585
1586   err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1587                        &value, &valuelen, MAX_CERT_LENGTH);
1588   if (err)
1589     {
1590       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1591       goto leave;
1592     }
1593
1594   if (!valuelen) /* No data returned; return a comprehensible error. */
1595     err = gpg_error (GPG_ERR_MISSING_CERT);
1596   else
1597     {
1598       err = ksba_cert_new (&cert);
1599       if (!err)
1600         err = ksba_cert_init_from_mem (cert, value, valuelen);
1601     }
1602   xfree (value);
1603   if(err)
1604     goto leave;
1605
1606   /* If we have this certificate already in our cache, use the cached
1607      version for validation because this will take care of any cached
1608      results. */
1609   {
1610     unsigned char fpr[20];
1611     ksba_cert_t tmpcert;
1612
1613     cert_compute_fpr (cert, fpr);
1614     tmpcert = get_cert_byfpr (fpr);
1615     if (tmpcert)
1616       {
1617         ksba_cert_release (cert);
1618         cert = tmpcert;
1619       }
1620   }
1621
1622   err = validate_cert_chain (ctrl, cert, NULL, VALIDATE_MODE_CERT, NULL);
1623
1624  leave:
1625   ksba_cert_release (cert);
1626   return leave_cmd (ctx, err);
1627 }
1628
1629
1630 \f
1631 /* Parse an keyserver URI and store it in a new uri item which is
1632    returned at R_ITEM.  On error return an error code.  */
1633 static gpg_error_t
1634 make_keyserver_item (const char *uri, uri_item_t *r_item)
1635 {
1636   gpg_error_t err;
1637   uri_item_t item;
1638
1639   *r_item = NULL;
1640   item = xtrymalloc (sizeof *item + strlen (uri));
1641   if (!item)
1642     return gpg_error_from_syserror ();
1643
1644   item->next = NULL;
1645   item->parsed_uri = NULL;
1646   strcpy (item->uri, uri);
1647
1648 #if USE_LDAP
1649   if (ldap_uri_p (item->uri))
1650     err = ldap_parse_uri (&item->parsed_uri, uri);
1651   else
1652 #endif
1653     {
1654       err = http_parse_uri (&item->parsed_uri, uri, 1);
1655     }
1656
1657   if (err)
1658     xfree (item);
1659   else
1660     *r_item = item;
1661   return err;
1662 }
1663
1664
1665 /* If no keyserver is stored in CTRL but a global keyserver has been
1666    set, put that global keyserver into CTRL.  We need use this
1667    function to help migrate from the old gpg based keyserver
1668    configuration to the new dirmngr based configuration.  */
1669 static gpg_error_t
1670 ensure_keyserver (ctrl_t ctrl)
1671 {
1672   gpg_error_t err;
1673   uri_item_t item;
1674
1675   if (ctrl->server_local->keyservers)
1676     return 0; /* Already set for this session.  */
1677   if (!opt.keyserver)
1678     return 0; /* No global option set.  */
1679
1680   err = make_keyserver_item (opt.keyserver, &item);
1681   if (!err)
1682     ctrl->server_local->keyservers = item;
1683
1684   return err;
1685 }
1686
1687
1688 static const char hlp_keyserver[] =
1689   "KEYSERVER [<options>] [<uri>|<host>]\n"
1690   "Options are:\n"
1691   "  --help\n"
1692   "  --clear      Remove all configured keyservers\n"
1693   "  --resolve    Resolve HKP host names and rotate\n"
1694   "  --hosttable  Print table of known hosts and pools\n"
1695   "  --dead       Mark <host> as dead\n"
1696   "  --alive      Mark <host> as alive\n"
1697   "\n"
1698   "If called without arguments list all configured keyserver URLs.\n"
1699   "If called with an URI add this as keyserver.  Note that keyservers\n"
1700   "are configured on a per-session base.  A default keyserver may already be\n"
1701   "present, thus the \"--clear\" option must be used to get full control.\n"
1702   "If \"--clear\" and an URI are used together the clear command is\n"
1703   "obviously executed first.  A RESET command does not change the list\n"
1704   "of configured keyservers.";
1705 static gpg_error_t
1706 cmd_keyserver (assuan_context_t ctx, char *line)
1707 {
1708   ctrl_t ctrl = assuan_get_pointer (ctx);
1709   gpg_error_t err = 0;
1710   int clear_flag, add_flag, help_flag, host_flag, resolve_flag;
1711   int dead_flag, alive_flag;
1712   uri_item_t item = NULL; /* gcc 4.4.5 is not able to detect that it
1713                              is always initialized.  */
1714
1715   clear_flag = has_option (line, "--clear");
1716   help_flag = has_option (line, "--help");
1717   resolve_flag = has_option (line, "--resolve");
1718   host_flag = has_option (line, "--hosttable");
1719   dead_flag = has_option (line, "--dead");
1720   alive_flag = has_option (line, "--alive");
1721   line = skip_options (line);
1722   add_flag = !!*line;
1723
1724   if (help_flag)
1725     {
1726       err = ks_action_help (ctrl, line);
1727       goto leave;
1728     }
1729
1730   if (resolve_flag)
1731     {
1732       err = ensure_keyserver (ctrl);
1733       if (!err)
1734         err = ks_action_resolve (ctrl, ctrl->server_local->keyservers);
1735       if (err)
1736         goto leave;
1737     }
1738
1739   if (alive_flag && dead_flag)
1740     {
1741       err = set_error (GPG_ERR_ASS_PARAMETER, "no support for zombies");
1742       goto leave;
1743     }
1744   if (dead_flag)
1745     {
1746       err = check_owner_permission (ctx, "no permission to use --dead");
1747       if (err)
1748         goto leave;
1749     }
1750   if (alive_flag || dead_flag)
1751     {
1752       if (!*line)
1753         {
1754           err = set_error (GPG_ERR_ASS_PARAMETER, "name of host missing");
1755           goto leave;
1756         }
1757
1758       err = ks_hkp_mark_host (ctrl, line, alive_flag);
1759       if (err)
1760         goto leave;
1761     }
1762
1763   if (host_flag)
1764     {
1765       err = ks_hkp_print_hosttable (ctrl);
1766       if (err)
1767         goto leave;
1768     }
1769   if (resolve_flag || host_flag || alive_flag || dead_flag)
1770     goto leave;
1771
1772   if (add_flag)
1773     {
1774       err = make_keyserver_item (line, &item);
1775       if (err)
1776         goto leave;
1777     }
1778   if (clear_flag)
1779     release_ctrl_keyservers (ctrl);
1780   if (add_flag)
1781     {
1782       item->next = ctrl->server_local->keyservers;
1783       ctrl->server_local->keyservers = item;
1784     }
1785
1786   if (!add_flag && !clear_flag && !help_flag)
1787     {
1788       /* List configured keyservers.  However, we first add a global
1789          keyserver. */
1790       uri_item_t u;
1791
1792       err = ensure_keyserver (ctrl);
1793       if (err)
1794         {
1795           assuan_set_error (ctx, err,
1796                             "Bad keyserver configuration in dirmngr.conf");
1797           goto leave;
1798         }
1799
1800       for (u=ctrl->server_local->keyservers; u; u = u->next)
1801         dirmngr_status (ctrl, "KEYSERVER", u->uri, NULL);
1802     }
1803   err = 0;
1804
1805  leave:
1806   return leave_cmd (ctx, err);
1807 }
1808
1809
1810 \f
1811 static const char hlp_ks_search[] =
1812   "KS_SEARCH {<pattern>}\n"
1813   "\n"
1814   "Search the configured OpenPGP keyservers (see command KEYSERVER)\n"
1815   "for keys matching PATTERN";
1816 static gpg_error_t
1817 cmd_ks_search (assuan_context_t ctx, char *line)
1818 {
1819   ctrl_t ctrl = assuan_get_pointer (ctx);
1820   gpg_error_t err;
1821   strlist_t list, sl;
1822   char *p;
1823   estream_t outfp;
1824
1825   /* No options for now.  */
1826   line = skip_options (line);
1827
1828   /* Break the line down into an strlist.  Each pattern is
1829      percent-plus escaped. */
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   err = ensure_keyserver (ctrl);
1853   if (err)
1854     goto leave;
1855
1856   /* Setup an output stream and perform the search.  */
1857   outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1858   if (!outfp)
1859     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1860   else
1861     {
1862       err = ks_action_search (ctrl, ctrl->server_local->keyservers,
1863                               list, outfp);
1864       es_fclose (outfp);
1865     }
1866
1867  leave:
1868   free_strlist (list);
1869   return leave_cmd (ctx, err);
1870 }
1871
1872
1873 \f
1874 static const char hlp_ks_get[] =
1875   "KS_GET {<pattern>}\n"
1876   "\n"
1877   "Get the keys matching PATTERN from the configured OpenPGP keyservers\n"
1878   "(see command KEYSERVER).  Each pattern should be a keyid, a fingerprint,\n"
1879   "or an exact name indicated by the '=' prefix.";
1880 static gpg_error_t
1881 cmd_ks_get (assuan_context_t ctx, char *line)
1882 {
1883   ctrl_t ctrl = assuan_get_pointer (ctx);
1884   gpg_error_t err;
1885   strlist_t list, sl;
1886   char *p;
1887   estream_t outfp;
1888
1889   /* No options for now.  */
1890   line = skip_options (line);
1891
1892   /* Break the line into a strlist.  Each pattern is by
1893      definition percent-plus escaped.  However we only support keyids
1894      and fingerprints and thus the client has no need to apply the
1895      escaping.  */
1896   list = NULL;
1897   for (p=line; *p; line = p)
1898     {
1899       while (*p && *p != ' ')
1900         p++;
1901       if (*p)
1902         *p++ = 0;
1903       if (*line)
1904         {
1905           sl = xtrymalloc (sizeof *sl + strlen (line));
1906           if (!sl)
1907             {
1908               err = gpg_error_from_syserror ();
1909               goto leave;
1910             }
1911           sl->flags = 0;
1912           strcpy_escaped_plus (sl->d, line);
1913           sl->next = list;
1914           list = sl;
1915         }
1916     }
1917
1918   err = ensure_keyserver (ctrl);
1919   if (err)
1920     goto leave;
1921
1922   /* Setup an output stream and perform the get.  */
1923   outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1924   if (!outfp)
1925     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1926   else
1927     {
1928       err = ks_action_get (ctrl, ctrl->server_local->keyservers, list, outfp);
1929       es_fclose (outfp);
1930     }
1931
1932  leave:
1933   free_strlist (list);
1934   return leave_cmd (ctx, err);
1935 }
1936
1937
1938 static const char hlp_ks_fetch[] =
1939   "KS_FETCH <URL>\n"
1940   "\n"
1941   "Get the key(s) from URL.";
1942 static gpg_error_t
1943 cmd_ks_fetch (assuan_context_t ctx, char *line)
1944 {
1945   ctrl_t ctrl = assuan_get_pointer (ctx);
1946   gpg_error_t err;
1947   estream_t outfp;
1948
1949   /* No options for now.  */
1950   line = skip_options (line);
1951
1952   err = ensure_keyserver (ctrl);
1953   if (err)
1954     goto leave;
1955
1956   /* Setup an output stream and perform the get.  */
1957   outfp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1958   if (!outfp)
1959     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1960   else
1961     {
1962       err = ks_action_fetch (ctrl, line, outfp);
1963       es_fclose (outfp);
1964     }
1965
1966  leave:
1967   return leave_cmd (ctx, err);
1968 }
1969
1970
1971 \f
1972 static const char hlp_ks_put[] =
1973   "KS_PUT\n"
1974   "\n"
1975   "Send a key to the configured OpenPGP keyservers.  The actual key material\n"
1976   "is then requested by Dirmngr using\n"
1977   "\n"
1978   "  INQUIRE KEYBLOCK\n"
1979   "\n"
1980   "The client shall respond with a binary version of the keyblock (e.g.,\n"
1981   "the output of `gpg --export KEYID').  For LDAP\n"
1982   "keyservers Dirmngr may ask for meta information of the provided keyblock\n"
1983   "using:\n"
1984   "\n"
1985   "  INQUIRE KEYBLOCK_INFO\n"
1986   "\n"
1987   "The client shall respond with a colon delimited info lines (the output\n"
1988   "of 'for x in keys sigs; do gpg --list-$x --with-colons KEYID; done').\n";
1989 static gpg_error_t
1990 cmd_ks_put (assuan_context_t ctx, char *line)
1991 {
1992   ctrl_t ctrl = assuan_get_pointer (ctx);
1993   gpg_error_t err;
1994   unsigned char *value = NULL;
1995   size_t valuelen;
1996   unsigned char *info = NULL;
1997   size_t infolen;
1998
1999   /* No options for now.  */
2000   line = skip_options (line);
2001
2002   err = ensure_keyserver (ctrl);
2003   if (err)
2004     goto leave;
2005
2006   /* Ask for the key material.  */
2007   err = assuan_inquire (ctx, "KEYBLOCK",
2008                         &value, &valuelen, MAX_KEYBLOCK_LENGTH);
2009   if (err)
2010     {
2011       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
2012       goto leave;
2013     }
2014
2015   if (!valuelen) /* No data returned; return a comprehensible error. */
2016     {
2017       err = gpg_error (GPG_ERR_MISSING_CERT);
2018       goto leave;
2019     }
2020
2021   /* Ask for the key meta data. Not actually needed for HKP servers
2022      but we do it anyway to test the client implementaion.  */
2023   err = assuan_inquire (ctx, "KEYBLOCK_INFO",
2024                         &info, &infolen, MAX_KEYBLOCK_LENGTH);
2025   if (err)
2026     {
2027       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
2028       goto leave;
2029     }
2030
2031   /* Send the key.  */
2032   err = ks_action_put (ctrl, ctrl->server_local->keyservers,
2033                        value, valuelen, info, infolen);
2034
2035  leave:
2036   xfree (info);
2037   xfree (value);
2038   return leave_cmd (ctx, err);
2039 }
2040
2041
2042
2043 \f
2044 static const char hlp_getinfo[] =
2045   "GETINFO <what>\n"
2046   "\n"
2047   "Multi purpose command to return certain information.  \n"
2048   "Supported values of WHAT are:\n"
2049   "\n"
2050   "version     - Return the version of the program.\n"
2051   "pid         - Return the process id of the server.\n"
2052   "tor         - Return OK if running in TOR mode\n"
2053   "socket_name - Return the name of the socket.\n";
2054 static gpg_error_t
2055 cmd_getinfo (assuan_context_t ctx, char *line)
2056 {
2057   gpg_error_t err;
2058
2059   if (!strcmp (line, "version"))
2060     {
2061       const char *s = VERSION;
2062       err = assuan_send_data (ctx, s, strlen (s));
2063     }
2064   else if (!strcmp (line, "pid"))
2065     {
2066       char numbuf[50];
2067
2068       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
2069       err = assuan_send_data (ctx, numbuf, strlen (numbuf));
2070     }
2071   else if (!strcmp (line, "socket_name"))
2072     {
2073       const char *s = dirmngr_user_socket_name ();
2074
2075       if (!s)
2076         s = dirmngr_sys_socket_name ();
2077
2078       if (s)
2079         err = assuan_send_data (ctx, s, strlen (s));
2080       else
2081         err = gpg_error (GPG_ERR_NO_DATA);
2082     }
2083   else if (!strcmp (line, "tor"))
2084     {
2085       err = opt.use_tor? 0:set_error (GPG_ERR_GENERAL, "TOR mode not enabled");
2086     }
2087   else
2088     err = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
2089
2090   return leave_cmd (ctx, err);
2091 }
2092
2093
2094 \f
2095 static const char hlp_killdirmngr[] =
2096   "KILLDIRMNGR\n"
2097   "\n"
2098   "This command allows a user - given sufficient permissions -\n"
2099   "to kill this dirmngr process.\n";
2100 static gpg_error_t
2101 cmd_killdirmngr (assuan_context_t ctx, char *line)
2102 {
2103   ctrl_t ctrl = assuan_get_pointer (ctx);
2104   gpg_error_t err;
2105
2106   (void)line;
2107
2108   if (opt.system_daemon)
2109     {
2110       if (opt.system_service)
2111         err = set_error (GPG_ERR_NOT_SUPPORTED,
2112                          "can't do that whilst running as system service");
2113       else
2114         err = check_owner_permission (ctx,
2115                                       "no permission to kill this process");
2116     }
2117   else
2118     err = 0;
2119
2120   if (!err)
2121     {
2122       ctrl->server_local->stopme = 1;
2123       err = gpg_error (GPG_ERR_EOF);
2124     }
2125   return err;
2126 }
2127
2128
2129 static const char hlp_reloaddirmngr[] =
2130   "RELOADDIRMNGR\n"
2131   "\n"
2132   "This command is an alternative to SIGHUP\n"
2133   "to reload the configuration.";
2134 static gpg_error_t
2135 cmd_reloaddirmngr (assuan_context_t ctx, char *line)
2136 {
2137   (void)ctx;
2138   (void)line;
2139
2140  if (opt.system_daemon)
2141     {
2142 #ifndef HAVE_W32_SYSTEM
2143       {
2144         gpg_err_code_t ec;
2145         assuan_peercred_t cred;
2146
2147         ec = gpg_err_code (assuan_get_peercred (ctx, &cred));
2148         if (!ec && cred->uid)
2149           ec = GPG_ERR_EPERM; /* Only root may terminate.  */
2150         if (ec)
2151           return set_error (ec, "no permission to reload this process");
2152       }
2153 #endif
2154     }
2155
2156   dirmngr_sighup_action ();
2157   return 0;
2158 }
2159
2160
2161
2162 \f
2163 /* Tell the assuan library about our commands. */
2164 static int
2165 register_commands (assuan_context_t ctx)
2166 {
2167   static struct {
2168     const char *name;
2169     assuan_handler_t handler;
2170     const char * const help;
2171   } table[] = {
2172     { "DNS_CERT",   cmd_dns_cert,   hlp_dns_cert },
2173     { "LDAPSERVER", cmd_ldapserver, hlp_ldapserver },
2174     { "ISVALID",    cmd_isvalid,    hlp_isvalid },
2175     { "CHECKCRL",   cmd_checkcrl,   hlp_checkcrl },
2176     { "CHECKOCSP",  cmd_checkocsp,  hlp_checkocsp },
2177     { "LOOKUP",     cmd_lookup,     hlp_lookup },
2178     { "LOADCRL",    cmd_loadcrl,    hlp_loadcrl },
2179     { "LISTCRLS",   cmd_listcrls,   hlp_listcrls },
2180     { "CACHECERT",  cmd_cachecert,  hlp_cachecert },
2181     { "VALIDATE",   cmd_validate,   hlp_validate },
2182     { "KEYSERVER",  cmd_keyserver,  hlp_keyserver },
2183     { "KS_SEARCH",  cmd_ks_search,  hlp_ks_search },
2184     { "KS_GET",     cmd_ks_get,     hlp_ks_get },
2185     { "KS_FETCH",   cmd_ks_fetch,   hlp_ks_fetch },
2186     { "KS_PUT",     cmd_ks_put,     hlp_ks_put },
2187     { "GETINFO",    cmd_getinfo,    hlp_getinfo },
2188     { "KILLDIRMNGR",cmd_killdirmngr,hlp_killdirmngr },
2189     { "RELOADDIRMNGR",cmd_reloaddirmngr,hlp_reloaddirmngr },
2190     { NULL, NULL }
2191   };
2192   int i, j, rc;
2193
2194   for (i=j=0; table[i].name; i++)
2195     {
2196       rc = assuan_register_command (ctx, table[i].name, table[i].handler,
2197                                     table[i].help);
2198       if (rc)
2199         return rc;
2200     }
2201   return 0;
2202 }
2203
2204
2205 /* Note that we do not reset the list of configured keyservers.  */
2206 static gpg_error_t
2207 reset_notify (assuan_context_t ctx, char *line)
2208 {
2209   ctrl_t ctrl = assuan_get_pointer (ctx);
2210   (void)line;
2211
2212 #if USE_LDAP
2213   ldapserver_list_free (ctrl->server_local->ldapservers);
2214 #endif /*USE_LDAP*/
2215   ctrl->server_local->ldapservers = NULL;
2216   return 0;
2217 }
2218
2219
2220 /* Startup the server and run the main command loop.  With FD = -1,
2221    use stdin/stdout. */
2222 void
2223 start_command_handler (assuan_fd_t fd)
2224 {
2225   static const char hello[] = "Dirmngr " VERSION " at your service";
2226   static char *hello_line;
2227   int rc;
2228   assuan_context_t ctx;
2229   ctrl_t ctrl;
2230
2231   ctrl = xtrycalloc (1, sizeof *ctrl);
2232   if (ctrl)
2233     ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
2234   if (!ctrl || !ctrl->server_local)
2235     {
2236       log_error (_("can't allocate control structure: %s\n"),
2237                  strerror (errno));
2238       xfree (ctrl);
2239       return;
2240     }
2241
2242   dirmngr_init_default_ctrl (ctrl);
2243
2244   rc = assuan_new (&ctx);
2245   if (rc)
2246     {
2247       log_error (_("failed to allocate assuan context: %s\n"),
2248                  gpg_strerror (rc));
2249       dirmngr_exit (2);
2250     }
2251
2252   if (fd == ASSUAN_INVALID_FD)
2253     {
2254       assuan_fd_t filedes[2];
2255
2256       filedes[0] = assuan_fdopen (0);
2257       filedes[1] = assuan_fdopen (1);
2258       rc = assuan_init_pipe_server (ctx, filedes);
2259     }
2260   else
2261     {
2262       rc = assuan_init_socket_server (ctx, fd, ASSUAN_SOCKET_SERVER_ACCEPTED);
2263     }
2264
2265   if (rc)
2266     {
2267       assuan_release (ctx);
2268       log_error (_("failed to initialize the server: %s\n"),
2269                  gpg_strerror(rc));
2270       dirmngr_exit (2);
2271     }
2272
2273   rc = register_commands (ctx);
2274   if (rc)
2275     {
2276       log_error (_("failed to the register commands with Assuan: %s\n"),
2277                  gpg_strerror(rc));
2278       dirmngr_exit (2);
2279     }
2280
2281
2282   if (!hello_line)
2283     {
2284       size_t n;
2285       const char *cfgname;
2286
2287       cfgname = opt.config_filename? opt.config_filename : "[none]";
2288
2289       n = (30 + strlen (opt.homedir) + strlen (cfgname)
2290            + strlen (hello) + 1);
2291       hello_line = xmalloc (n+1);
2292       snprintf (hello_line, n,
2293                 "Home: %s\n"
2294                 "Config: %s\n"
2295                 "%s",
2296                 opt.homedir,
2297                 cfgname,
2298                 hello);
2299       hello_line[n] = 0;
2300     }
2301
2302   ctrl->server_local->assuan_ctx = ctx;
2303   assuan_set_pointer (ctx, ctrl);
2304
2305   assuan_set_hello_line (ctx, hello_line);
2306   assuan_register_option_handler (ctx, option_handler);
2307   assuan_register_reset_notify (ctx, reset_notify);
2308
2309   for (;;)
2310     {
2311       rc = assuan_accept (ctx);
2312       if (rc == -1)
2313         break;
2314       if (rc)
2315         {
2316           log_info (_("Assuan accept problem: %s\n"), gpg_strerror (rc));
2317           break;
2318         }
2319
2320 #ifndef HAVE_W32_SYSTEM
2321       if (opt.verbose)
2322         {
2323           assuan_peercred_t peercred;
2324
2325           if (!assuan_get_peercred (ctx, &peercred))
2326             log_info ("connection from process %ld (%ld:%ld)\n",
2327                       (long)peercred->pid, (long)peercred->uid,
2328                       (long)peercred->gid);
2329         }
2330 #endif
2331
2332       rc = assuan_process (ctx);
2333       if (rc)
2334         {
2335           log_info (_("Assuan processing failed: %s\n"), gpg_strerror (rc));
2336           continue;
2337         }
2338     }
2339
2340 #if USE_LDAP
2341   ldap_wrapper_connection_cleanup (ctrl);
2342
2343   ldapserver_list_free (ctrl->server_local->ldapservers);
2344 #endif /*USE_LDAP*/
2345   ctrl->server_local->ldapservers = NULL;
2346
2347   ctrl->server_local->assuan_ctx = NULL;
2348   assuan_release (ctx);
2349
2350   if (ctrl->server_local->stopme)
2351     dirmngr_exit (0);
2352
2353   if (ctrl->refcount)
2354     log_error ("oops: connection control structure still referenced (%d)\n",
2355                ctrl->refcount);
2356   else
2357     {
2358       release_ctrl_ocsp_certs (ctrl);
2359       xfree (ctrl->server_local);
2360       dirmngr_deinit_default_ctrl (ctrl);
2361       xfree (ctrl);
2362     }
2363 }
2364
2365
2366 /* Send a status line back to the client.  KEYWORD is the status
2367    keyword, the optional string arguments are blank separated added to
2368    the line, the last argument must be a NULL. */
2369 gpg_error_t
2370 dirmngr_status (ctrl_t ctrl, const char *keyword, ...)
2371 {
2372   gpg_error_t err = 0;
2373   va_list arg_ptr;
2374   const char *text;
2375
2376   va_start (arg_ptr, keyword);
2377
2378   if (ctrl->server_local)
2379     {
2380       assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2381       char buf[950], *p;
2382       size_t n;
2383
2384       p = buf;
2385       n = 0;
2386       while ( (text = va_arg (arg_ptr, const char *)) )
2387         {
2388           if (n)
2389             {
2390               *p++ = ' ';
2391               n++;
2392             }
2393           for ( ; *text && n < DIM (buf)-2; n++)
2394             *p++ = *text++;
2395         }
2396       *p = 0;
2397       err = assuan_write_status (ctx, keyword, buf);
2398     }
2399
2400   va_end (arg_ptr);
2401   return err;
2402 }
2403
2404
2405 /* Print a help status line.  TEXTLEN gives the length of the text
2406    from TEXT to be printed.  The function splits text at LFs.  */
2407 gpg_error_t
2408 dirmngr_status_help (ctrl_t ctrl, const char *text)
2409 {
2410   gpg_error_t err = 0;
2411
2412   if (ctrl->server_local)
2413     {
2414       assuan_context_t ctx = ctrl->server_local->assuan_ctx;
2415       char buf[950], *p;
2416       size_t n;
2417
2418       do
2419         {
2420           p = buf;
2421           n = 0;
2422           for ( ; *text && *text != '\n' && n < DIM (buf)-2; n++)
2423             *p++ = *text++;
2424           if (*text == '\n')
2425             text++;
2426           *p = 0;
2427           err = assuan_write_status (ctx, "#", buf);
2428         }
2429       while (!err && *text);
2430     }
2431
2432   return err;
2433 }
2434
2435 /* Send a tick progress indicator back.  Fixme: This is only done for
2436    the currently active channel.  */
2437 gpg_error_t
2438 dirmngr_tick (ctrl_t ctrl)
2439 {
2440   static time_t next_tick = 0;
2441   gpg_error_t err = 0;
2442   time_t now = time (NULL);
2443
2444   if (!next_tick)
2445     {
2446       next_tick = now + 1;
2447     }
2448   else if ( now > next_tick )
2449     {
2450       if (ctrl)
2451         {
2452           err = dirmngr_status (ctrl, "PROGRESS", "tick", "? 0 0", NULL);
2453           if (err)
2454             {
2455               /* Take this as in indication for a cancel request.  */
2456               err = gpg_error (GPG_ERR_CANCELED);
2457             }
2458           now = time (NULL);
2459         }
2460
2461       next_tick = now + 1;
2462     }
2463   return err;
2464 }