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