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