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