Fix a build_sources problem
[gnupg.git] / dirmngr / server.c
1 /* dirmngr.c - LDAP access
2  *      Copyright (C) 2002 Klarälvdalens Datakonsult AB
3  *      Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 g10 Code GmbH
4  *
5  * This file is part of DirMngr.
6  *
7  * DirMngr is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * DirMngr is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stddef.h>
25 #include <string.h>
26 #include <assert.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include <errno.h>
31
32 #define JNLIB_NEED_LOG_LOGV
33 #include "dirmngr.h"
34 #include <assuan.h>
35
36 #include "crlcache.h"
37 #include "crlfetch.h"
38 #include "ldapserver.h"
39 #include "ocsp.h"
40 #include "certcache.h"
41 #include "validate.h"
42 #include "misc.h"
43 #include "ldap-wrapper.h"
44
45 /* To avoid DoS attacks we limit the size of a certificate to
46    something reasonable. */
47 #define MAX_CERT_LENGTH (8*1024)
48
49 #define PARM_ERROR(t) assuan_set_error (ctx, \
50                                         gpg_error (GPG_ERR_ASS_PARAMETER), (t))
51 #define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
52
53
54
55 /* Control structure per connection. */
56 struct server_local_s 
57 {
58   /* Data used to associate an Assuan context with local server data */
59   assuan_context_t assuan_ctx;
60
61   /* Per-session LDAP serfver.  */
62   ldap_server_t ldapservers;
63
64   /* If this flag is set to true this dirmngr process will be
65      terminated after the end of this session.  */
66   int stopme;
67 };
68
69
70 /* Cookie definition for assuan data line output.  */
71 static ssize_t data_line_cookie_write (void *cookie,
72                                        const void *buffer, size_t size);
73 static int data_line_cookie_close (void *cookie);
74 static es_cookie_io_functions_t data_line_cookie_functions =
75   {
76     NULL,
77     data_line_cookie_write,
78     NULL,
79     data_line_cookie_close
80   };
81
82
83
84
85 \f
86 /* Accessor for the local ldapservers variable. */
87 ldap_server_t
88 get_ldapservers_from_ctrl (ctrl_t ctrl)
89 {
90   if (ctrl && ctrl->server_local)
91     return ctrl->server_local->ldapservers;
92   else
93     return NULL;
94 }
95
96
97 /* Helper to print a message while leaving a command.  */
98 static gpg_error_t
99 leave_cmd (assuan_context_t ctx, gpg_error_t err)
100 {
101   if (err)
102     {
103       const char *name = assuan_get_command_name (ctx);
104       if (!name)
105         name = "?";
106       if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
107         log_error ("command '%s' failed: %s\n", name,
108                    gpg_strerror (err));
109       else
110         log_error ("command '%s' failed: %s <%s>\n", name,
111                    gpg_strerror (err), gpg_strsource (err));
112     }
113   return err;
114 }
115
116 /* A write handler used by es_fopencookie to write assuan data
117    lines.  */
118 static ssize_t
119 data_line_cookie_write (void *cookie, const void *buffer, size_t size)
120 {
121   assuan_context_t ctx = cookie;
122
123   if (assuan_send_data (ctx, buffer, size))
124     {
125       gpg_err_set_errno (EIO);
126       return -1;
127     }
128
129   return size;
130 }
131
132 static int
133 data_line_cookie_close (void *cookie)
134 {
135   assuan_context_t ctx = cookie;
136
137   if (assuan_send_data (ctx, NULL, 0))
138     {
139       gpg_err_set_errno (EIO);
140       return -1;
141     }
142
143   return 0;
144 }
145
146
147 /* Copy the % and + escaped string S into the buffer D and replace the
148    escape sequences.  Note, that it is sufficient to allocate the
149    target string D as long as the source string S, i.e.: strlen(s)+1.
150    NOte further that If S contains an escaped binary nul the resulting
151    string D will contain the 0 as well as all other characters but it
152    will be impossible to know whether this is the original EOS or a
153    copied Nul. */
154 static void
155 strcpy_escaped_plus (char *d, const unsigned char *s)
156 {
157   while (*s)
158     {
159       if (*s == '%' && s[1] && s[2])
160         {
161           s++;
162           *d++ = xtoi_2 ( s);
163           s += 2;
164         }
165       else if (*s == '+')
166         *d++ = ' ', s++;
167       else
168         *d++ = *s++;
169     }
170   *d = 0;
171 }
172
173
174 /* Check whether the option NAME appears in LINE */
175 static int
176 has_option (const char *line, const char *name)
177 {
178   const char *s;
179   int n = strlen (name);
180
181   s = strstr (line, name);
182   return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
183 }
184
185 /* Same as has_option but only considers options at the begin of the
186    line.  This is useful for commands which allow arbitrary strings on
187    the line.  */
188 static int
189 has_leading_option (const char *line, const char *name)
190 {
191   const char *s;
192   int n;
193
194   if (name[0] != '-' || name[1] != '-' || !name[2] || spacep (name+2))
195     return 0;
196   n = strlen (name);
197   while ( *line == '-' && line[1] == '-' )
198     {
199       s = line;
200       while (*line && !spacep (line))
201         line++;
202       if (n == (line - s) && !strncmp (s, name, n))
203         return 1;
204       while (spacep (line))
205         line++;
206     }
207   return 0;
208 }
209
210
211 /* Same as has_option but does only test for the name of the option
212    and ignores an argument, i.e. with NAME being "--hash" it would
213    return a pointer for "--hash" as well as for "--hash=foo".  If
214    thhere is no such option NULL is returned.  The pointer returned
215    points right behind the option name, this may be an equal sign, Nul
216    or a space.  */
217 /* static const char * */
218 /* has_option_name (const char *line, const char *name) */
219 /* { */
220 /*   const char *s; */
221 /*   int n = strlen (name); */
222
223 /*   s = strstr (line, name); */
224 /*   return (s && (s == line || spacep (s-1)) */
225 /*           && (!s[n] || spacep (s+n) || s[n] == '=')) ? (s+n) : NULL; */
226 /* } */
227
228
229 /* Skip over options.  It is assumed that leading spaces have been
230    removed (this is the case for lines passed to a handler from
231    assuan).  Blanks after the options are also removed. */
232 static char *
233 skip_options (char *line)
234 {
235   while ( *line == '-' && line[1] == '-' )
236     {
237       while (*line && !spacep (line))
238         line++;
239       while (spacep (line))
240         line++;
241     }
242   return line;
243 }
244
245
246 /* Common code for get_cert_local and get_issuer_cert_local. */
247 static ksba_cert_t 
248 do_get_cert_local (ctrl_t ctrl, const char *name, const char *command)
249 {
250   unsigned char *value;
251   size_t valuelen; 
252   int rc;
253   char *buf;
254   ksba_cert_t cert;
255
256   if (name)
257     {
258       buf = xmalloc ( strlen (command) + 1 + strlen(name) + 1);
259       strcpy (stpcpy (stpcpy (buf, command), " "), name);
260     }
261   else
262     buf = xstrdup (command);
263
264   rc = assuan_inquire (ctrl->server_local->assuan_ctx, buf,
265                        &value, &valuelen, MAX_CERT_LENGTH);
266   xfree (buf);
267   if (rc)
268     {
269       log_error (_("assuan_inquire(%s) failed: %s\n"),
270                  command, gpg_strerror (rc));
271       return NULL;
272     }
273   
274   if (!valuelen)
275     {
276       xfree (value);
277       return NULL;
278     }
279
280   rc = ksba_cert_new (&cert);
281   if (!rc)
282     {
283       rc = ksba_cert_init_from_mem (cert, value, valuelen);
284       if (rc)
285         {
286           ksba_cert_release (cert);
287           cert = NULL;
288         }
289     }
290   xfree (value);
291   return cert;
292 }
293
294
295
296 /* Ask back to return a certificate for name, given as a regular
297    gpgsm certificate indentificates (e.g. fingerprint or one of the
298    other methods).  Alternatively, NULL may be used for NAME to
299    return the current target certificate. Either return the certificate
300    in a KSBA object or NULL if it is not available.
301 */
302 ksba_cert_t 
303 get_cert_local (ctrl_t ctrl, const char *name)
304 {
305   if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
306     {
307       if (opt.debug)
308         log_debug ("get_cert_local called w/o context\n");
309       return NULL;
310     }
311   return do_get_cert_local (ctrl, name, "SENDCERT");
312
313 }
314        
315 /* Ask back to return the issuing certificate for name, given as a
316    regular gpgsm certificate indentificates (e.g. fingerprint or one
317    of the other methods).  Alternatively, NULL may be used for NAME to
318    return thecurrent target certificate. Either return the certificate
319    in a KSBA object or NULL if it is not available.
320    
321 */
322 ksba_cert_t 
323 get_issuing_cert_local (ctrl_t ctrl, const char *name)
324 {
325   if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
326     {
327       if (opt.debug)
328         log_debug ("get_issuing_cert_local called w/o context\n");
329       return NULL;
330     }
331   return do_get_cert_local (ctrl, name, "SENDISSUERCERT");
332 }
333
334 /* Ask back to return a certificate with subject NAME and a
335    subjectKeyIdentifier of KEYID. */
336 ksba_cert_t 
337 get_cert_local_ski (ctrl_t ctrl, const char *name, ksba_sexp_t keyid)
338 {
339   unsigned char *value;
340   size_t valuelen; 
341   int rc;
342   char *buf;
343   ksba_cert_t cert;
344   char *hexkeyid;
345
346   if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx)
347     {
348       if (opt.debug)
349         log_debug ("get_cert_local_ski called w/o context\n");
350       return NULL;
351     }
352   if (!name || !keyid)
353     {
354       log_debug ("get_cert_local_ski called with insufficient arguments\n");
355       return NULL;
356     }
357
358   hexkeyid = serial_hex (keyid);
359   if (!hexkeyid)
360     {
361       log_debug ("serial_hex() failed\n");
362       return NULL;
363     }
364
365   buf = xtrymalloc (15 + strlen (hexkeyid) + 2 + strlen(name) + 1);
366   if (!buf)
367     {
368
369       log_error ("can't allocate enough memory: %s\n", strerror (errno));
370       xfree (hexkeyid);
371       return NULL;
372     }
373   strcpy (stpcpy (stpcpy (stpcpy (buf, "SENDCERT_SKI "), hexkeyid)," /"),name);
374   xfree (hexkeyid);
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"), "SENDCERT_SKI",
382                  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 /* Ask the client via an inquiry to check the istrusted status of the
408    certificate specified by the hexified fingerprint HEXFPR.  Returns
409    0 if the certificate is trusted by the client or an error code.  */
410 gpg_error_t
411 get_istrusted_from_client (ctrl_t ctrl, const char *hexfpr)
412 {
413   unsigned char *value;
414   size_t valuelen; 
415   int rc;
416   char request[100];
417
418   if (!ctrl || !ctrl->server_local || !ctrl->server_local->assuan_ctx
419       || !hexfpr)
420     return gpg_error (GPG_ERR_INV_ARG);
421   
422   snprintf (request, sizeof request, "ISTRUSTED %s", hexfpr);
423   rc = assuan_inquire (ctrl->server_local->assuan_ctx, request,
424                        &value, &valuelen, 100);
425   if (rc)
426     {
427       log_error (_("assuan_inquire(%s) failed: %s\n"),
428                  request, gpg_strerror (rc));
429       return rc;
430     }
431   /* The expected data is: "1" or "1 cruft" (not a C-string).  */
432   if (valuelen && *value == '1' && (valuelen == 1 || spacep (value+1)))
433     rc = 0;
434   else
435     rc = gpg_error (GPG_ERR_NOT_TRUSTED);
436   xfree (value);
437   return rc;
438 }
439
440
441
442
443 /* Ask the client to return the certificate associated with the
444    current command. This is sometimes needed because the client usually
445    sends us just the cert ID, assuming that the request can be
446    satisfied from the cache, where the cert ID is used as key. */
447 static int
448 inquire_cert_and_load_crl (assuan_context_t ctx)
449 {
450   ctrl_t ctrl = assuan_get_pointer (ctx);
451   gpg_error_t err;
452   unsigned char *value = NULL;
453   size_t valuelen; 
454   ksba_cert_t cert = NULL;
455
456   err = assuan_inquire( ctx, "SENDCERT", &value, &valuelen, 0);
457   if (err)
458     return err;
459
460 /*   { */
461 /*     FILE *fp = fopen ("foo.der", "r"); */
462 /*     value = xmalloc (2000); */
463 /*     valuelen = fread (value, 1, 2000, fp); */
464 /*     fclose (fp); */
465 /*   } */
466
467   if (!valuelen) /* No data returned; return a comprehensible error. */
468     return gpg_error (GPG_ERR_MISSING_CERT);
469
470   err = ksba_cert_new (&cert);
471   if (err)
472     goto leave;
473   err = ksba_cert_init_from_mem (cert, value, valuelen);
474   if(err)
475     goto leave;
476   xfree (value); value = NULL;
477
478   err = crl_cache_reload_crl (ctrl, cert);
479
480  leave:
481   ksba_cert_release (cert);
482   xfree (value);
483   return err;
484 }
485
486
487 /* Handle OPTION commands. */
488 static gpg_error_t
489 option_handler (assuan_context_t ctx, const char *key, const char *value)
490 {
491   ctrl_t ctrl = assuan_get_pointer (ctx);
492
493   if (!strcmp (key, "force-crl-refresh"))
494     {
495       int i = *value? atoi (value) : 0;
496       ctrl->force_crl_refresh = i;
497     }
498   else if (!strcmp (key, "audit-events"))
499     {
500       int i = *value? atoi (value) : 0;
501       ctrl->audit_events = i;
502     }
503   else
504     return gpg_error (GPG_ERR_UNKNOWN_OPTION);
505
506   return 0;
507 }
508
509 static const char hlp_ldapserver[] = 
510   "LDAPSERVER <data>\n"
511   "\n"
512   "Add a new LDAP server to the list of configured LDAP servers.\n"
513   "DATA is in the same format as expected in the configure file.";
514 static gpg_error_t
515 cmd_ldapserver (assuan_context_t ctx, char *line)
516 {
517   ctrl_t ctrl = assuan_get_pointer (ctx);
518   ldap_server_t server;
519   ldap_server_t *last_next_p;
520
521   while (spacep (line))
522     line++;
523   if (*line == '\0')
524     return leave_cmd (ctx, PARM_ERROR (_("ldapserver missing")));
525
526   server = ldapserver_parse_one (line, "", 0);
527   if (! server)
528     return leave_cmd (ctx, gpg_error (GPG_ERR_INV_ARG));
529
530   last_next_p = &ctrl->server_local->ldapservers;
531   while (*last_next_p)
532     last_next_p = &(*last_next_p)->next;
533   *last_next_p = server;
534   return leave_cmd (ctx, 0);
535 }
536
537
538 static const char hlp_isvalid[] = 
539   "ISVALID [--only-ocsp] [--force-default-responder]"
540   " <certificate_id>|<certificate_fpr>\n"
541   "\n"
542   "This command checks whether the certificate identified by the\n"
543   "certificate_id is valid.  This is done by consulting CRLs or\n"
544   "whatever has been configured.  Note, that the returned error codes\n"
545   "are from gpg-error.h.  The command may callback using the inquire\n"
546   "function.  See the manual for details.\n"
547   "\n"
548   "The CERTIFICATE_ID is a hex encoded string consisting of two parts,\n"
549   "delimited by a single dot.  The first part is the SHA-1 hash of the\n"
550   "issuer name and the second part the serial number.\n"
551   "\n"
552   "Alternatively the certificate's fingerprint may be given in which\n"
553   "case an OCSP request is done before consulting the CRL.\n"
554   "\n"
555   "If the option --only-ocsp is given, no fallback to a CRL check will\n"
556   "be used.\n"
557   "\n"
558   "If the option --force-default-responder is given, only the default\n"
559   "OCSP responder will be used and any other methods of obtaining an\n"
560   "OCSP responder URL won't be used.";
561 static gpg_error_t
562 cmd_isvalid (assuan_context_t ctx, char *line)
563 {
564   ctrl_t ctrl = assuan_get_pointer (ctx);
565   char *issuerhash, *serialno;
566   gpg_error_t err;
567   int did_inquire = 0;
568   int ocsp_mode = 0;
569   int only_ocsp;
570   int force_default_responder;
571   
572   only_ocsp = has_option (line, "--only-ocsp");
573   force_default_responder = has_option (line, "--force-default-responder");
574   line = skip_options (line);
575
576   issuerhash = xstrdup (line); /* We need to work on a copy of the
577                                   line because that same Assuan
578                                   context may be used for an inquiry.
579                                   That is because Assuan reuses its
580                                   line buffer.
581                                    */
582
583   serialno = strchr (issuerhash, '.');
584   if (serialno)
585     *serialno++ = 0;
586   else
587     {
588       char *endp = strchr (issuerhash, ' ');
589       if (endp)
590         *endp = 0;
591       if (strlen (issuerhash) != 40)
592         {
593           xfree (issuerhash);
594           return leave_cmd (ctx, PARM_ERROR (_("serialno missing in cert ID")));
595         }
596       ocsp_mode = 1;
597     }
598
599
600  again:
601   if (ocsp_mode)
602     {
603       /* Note, that we ignore the given issuer hash and instead rely
604          on the current certificate semantics used with this
605          command. */
606       if (!opt.allow_ocsp)
607         err = gpg_error (GPG_ERR_NOT_SUPPORTED);
608       else
609         err = ocsp_isvalid (ctrl, NULL, NULL, force_default_responder);
610       /* Fixme: If we got no ocsp response and --only-ocsp is not used
611          we should fall back to CRL mode.  Thus we need to clear
612          OCSP_MODE, get the issuerhash and the serialno from the
613          current certificate and jump to again. */
614     }
615   else if (only_ocsp)
616     err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
617   else 
618     {
619       switch (crl_cache_isvalid (ctrl,
620                                  issuerhash, serialno,
621                                  ctrl->force_crl_refresh))
622         {
623         case CRL_CACHE_VALID:
624           err = 0;
625           break;
626         case CRL_CACHE_INVALID:
627           err = gpg_error (GPG_ERR_CERT_REVOKED);
628           break;
629         case CRL_CACHE_DONTKNOW: 
630           if (did_inquire)
631             err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
632           else if (!(err = inquire_cert_and_load_crl (ctx)))
633             {
634               did_inquire = 1;
635               goto again;
636             }
637           break;
638         case CRL_CACHE_CANTUSE: 
639           err = gpg_error (GPG_ERR_NO_CRL_KNOWN);
640           break;
641         default:
642           log_fatal ("crl_cache_isvalid returned invalid code\n");
643         }
644     }
645
646   xfree (issuerhash);
647   return leave_cmd (ctx, err);
648 }
649
650
651 /* If the line contains a SHA-1 fingerprint as the first argument,
652    return the FPR vuffer on success.  The function checks that the
653    fingerprint consists of valid characters and prints and error
654    message if it does not and returns NULL.  Fingerprints are
655    considered optional and thus no explicit error is returned. NULL is
656    also returned if there is no fingerprint at all available. 
657    FPR must be a caller provided buffer of at least 20 bytes.
658
659    Note that colons within the fingerprint are allowed to separate 2
660    hex digits; this allows for easier cutting and pasting using the
661    usual fingerprint rendering.
662 */
663 static unsigned char *
664 get_fingerprint_from_line (const char *line, unsigned char *fpr)
665 {
666   const char *s;
667   int i;
668
669   for (s=line, i=0; *s && *s != ' '; s++ )
670     {
671       if ( hexdigitp (s) && hexdigitp (s+1) )
672         {
673           if ( i >= 20 )
674             return NULL;  /* Fingerprint too long.  */
675           fpr[i++] = xtoi_2 (s);
676           s++;
677         }
678       else if ( *s != ':' )
679         return NULL; /* Invalid.  */
680     }
681   if ( i != 20 )
682     return NULL; /* Fingerprint to short.  */
683   return fpr;
684 }
685
686
687
688 static const char hlp_checkcrl[] = 
689   "CHECKCRL [<fingerprint>]\n"
690   "\n"
691   "Check whether the certificate with FINGERPRINT (SHA-1 hash of the\n"
692   "entire X.509 certificate blob) is valid or not by consulting the\n"
693   "CRL responsible for this certificate.  If the fingerprint has not\n"
694   "been given or the certificate is not known, the function \n"
695   "inquires the certificate using an\n"
696   "\n"
697   "  INQUIRE TARGETCERT\n"
698   "\n"
699   "and the caller is expected to return the certificate for the\n"
700   "request (which should match FINGERPRINT) as a binary blob.\n"
701   "Processing then takes place without further interaction; in\n"
702   "particular dirmngr tries to locate other required certificate by\n"
703   "its own mechanism which includes a local certificate store as well\n"
704   "as a list of trusted root certificates.\n"
705   "\n"
706   "The return value is the usual gpg-error code or 0 for ducesss;\n"
707   "i.e. the certificate validity has been confirmed by a valid CRL.";
708 static gpg_error_t
709 cmd_checkcrl (assuan_context_t ctx, char *line)
710 {
711   ctrl_t ctrl = assuan_get_pointer (ctx);
712   gpg_error_t err;
713   unsigned char fprbuffer[20], *fpr;
714   ksba_cert_t cert;
715
716   fpr = get_fingerprint_from_line (line, fprbuffer);
717   cert = fpr? get_cert_byfpr (fpr) : NULL;
718   
719   if (!cert)
720     {
721       /* We do not have this certificate yet or the fingerprint has
722          not been given.  Inquire it from the client.  */
723       unsigned char *value = NULL;
724       size_t valuelen; 
725       
726       err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
727                            &value, &valuelen, MAX_CERT_LENGTH);
728       if (err)
729         {
730           log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
731           goto leave;
732         }
733   
734       if (!valuelen) /* No data returned; return a comprehensible error. */
735         err = gpg_error (GPG_ERR_MISSING_CERT);
736       else
737         {
738           err = ksba_cert_new (&cert);
739           if (!err)
740             err = ksba_cert_init_from_mem (cert, value, valuelen);
741         }
742       xfree (value);
743       if(err)
744         goto leave;
745     }
746
747   assert (cert);
748
749   err = crl_cache_cert_isvalid (ctrl, cert, ctrl->force_crl_refresh);
750   if (gpg_err_code (err) == GPG_ERR_NO_CRL_KNOWN)
751     {
752       err = crl_cache_reload_crl (ctrl, cert);
753       if (!err)
754         err = crl_cache_cert_isvalid (ctrl, cert, 0);
755     }
756
757  leave:
758   ksba_cert_release (cert);
759   return leave_cmd (ctx, err);
760 }
761
762
763 static const char hlp_checkocsp[] = 
764   "CHECKOCSP [--force-default-responder] [<fingerprint>]\n"
765   "\n"
766   "Check whether the certificate with FINGERPRINT (SHA-1 hash of the\n"
767   "entire X.509 certificate blob) is valid or not by asking an OCSP\n"
768   "responder responsible for this certificate.  The optional\n"
769   "fingerprint may be used for a quick check in case an OCSP check has\n"
770   "been done for this certificate recently (we always cache OCSP\n"
771   "responses for a couple of minutes). If the fingerprint has not been\n"
772   "given or there is no cached result, the function inquires the\n"
773   "certificate using an\n"
774   "\n"
775   "   INQUIRE TARGETCERT\n"
776   "\n"
777   "and the caller is expected to return the certificate for the\n"
778   "request (which should match FINGERPRINT) as a binary blob.\n"
779   "Processing then takes place without further interaction; in\n"
780   "particular dirmngr tries to locate other required certificates by\n"
781   "its own mechanism which includes a local certificate store as well\n"
782   "as a list of trusted root certifciates.\n"
783   "\n"
784   "If the option --force-default-responder is given, only the default\n"
785   "OCSP responder will be used and any other methods of obtaining an\n"
786   "OCSP responder URL won't be used.\n"
787   "\n"
788   "The return value is the usual gpg-error code or 0 for ducesss;\n"
789   "i.e. the certificate validity has been confirmed by a valid CRL.";
790 static gpg_error_t
791 cmd_checkocsp (assuan_context_t ctx, char *line)
792 {
793   ctrl_t ctrl = assuan_get_pointer (ctx);
794   gpg_error_t err;
795   unsigned char fprbuffer[20], *fpr;
796   ksba_cert_t cert;
797   int force_default_responder;
798   
799   force_default_responder = has_option (line, "--force-default-responder");
800   line = skip_options (line);
801
802   fpr = get_fingerprint_from_line (line, fprbuffer);
803   cert = fpr? get_cert_byfpr (fpr) : NULL;
804   
805   if (!cert)
806     {
807       /* We do not have this certificate yet or the fingerprint has
808          not been given.  Inquire it from the client.  */
809       unsigned char *value = NULL;
810       size_t valuelen; 
811       
812       err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
813                            &value, &valuelen, MAX_CERT_LENGTH);
814       if (err)
815         {
816           log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
817           goto leave;
818         }
819   
820       if (!valuelen) /* No data returned; return a comprehensible error. */
821         err = gpg_error (GPG_ERR_MISSING_CERT);
822       else
823         {
824           err = ksba_cert_new (&cert);
825           if (!err)
826             err = ksba_cert_init_from_mem (cert, value, valuelen);
827         }
828       xfree (value);
829       if(err)
830         goto leave;
831     }
832
833   assert (cert);
834
835   if (!opt.allow_ocsp)
836     err = gpg_error (GPG_ERR_NOT_SUPPORTED);
837   else
838     err = ocsp_isvalid (ctrl, cert, NULL, force_default_responder);
839
840  leave:
841   ksba_cert_release (cert);
842   return leave_cmd (ctx, err);
843 }
844
845
846
847 static int
848 lookup_cert_by_url (assuan_context_t ctx, const char *url)
849 {
850   ctrl_t ctrl = assuan_get_pointer (ctx);
851   gpg_error_t err = 0;
852   unsigned char *value = NULL;
853   size_t valuelen; 
854
855   /* Fetch single certificate given it's URL.  */
856   err = fetch_cert_by_url (ctrl, url, &value, &valuelen);
857   if (err)
858     {
859       log_error (_("fetch_cert_by_url failed: %s\n"), gpg_strerror (err));
860       goto leave;
861     }
862
863   /* Send the data, flush the buffer and then send an END. */
864   err = assuan_send_data (ctx, value, valuelen);      
865   if (!err)
866     err = assuan_send_data (ctx, NULL, 0);
867   if (!err)
868     err = assuan_write_line (ctx, "END");
869   if (err) 
870     {
871       log_error (_("error sending data: %s\n"), gpg_strerror (err));
872       goto leave;
873     }
874
875  leave:
876
877   return err;
878 }
879
880
881 /* Send the certificate, flush the buffer and then send an END. */
882 static gpg_error_t
883 return_one_cert (void *opaque, ksba_cert_t cert)
884 {
885   assuan_context_t ctx = opaque;
886   gpg_error_t err;
887   const unsigned char *der;
888   size_t derlen;
889
890   der = ksba_cert_get_image (cert, &derlen);
891   if (!der)
892     err = gpg_error (GPG_ERR_INV_CERT_OBJ);
893   else
894     {
895       err = assuan_send_data (ctx, der, derlen);      
896       if (!err)
897         err = assuan_send_data (ctx, NULL, 0);
898       if (!err)
899         err = assuan_write_line (ctx, "END");
900     }
901   if (err) 
902     log_error (_("error sending data: %s\n"), gpg_strerror (err));
903   return err;
904 }
905
906
907 /* Lookup certificates from the internal cache or using the ldap
908    servers. */
909 static int
910 lookup_cert_by_pattern (assuan_context_t ctx, char *line, 
911                         int single, int cache_only)
912 {
913   ctrl_t ctrl = assuan_get_pointer (ctx);
914   gpg_error_t err = 0;
915   char *p;
916   strlist_t sl, list = NULL;
917   int truncated = 0, truncation_forced = 0;
918   int count = 0;
919   int local_count = 0;
920   unsigned char *value = NULL;
921   size_t valuelen; 
922   struct ldapserver_iter ldapserver_iter;
923   cert_fetch_context_t fetch_context;
924   int any_no_data = 0;
925
926   /* Break the line down into an STRLIST */
927   for (p=line; *p; line = p)
928     {
929       while (*p && *p != ' ')
930         p++;
931       if (*p) 
932         *p++ = 0;
933
934       if (*line)
935         {
936           sl = xtrymalloc (sizeof *sl + strlen (line));
937           if (!sl)
938             {
939               err = gpg_error_from_errno (errno);
940               goto leave;
941             }
942           memset (sl, 0, sizeof *sl);
943           strcpy_escaped_plus (sl->d, line);
944           sl->next = list;
945           list = sl;
946         }
947     }
948
949   /* First look through the internal cache.  The certifcates retruned
950      here are not counted towards the truncation limit.  */
951   if (single && !cache_only)
952     ; /* Do not read from the local cache in this case.  */
953   else
954     {
955       for (sl=list; sl; sl = sl->next)
956         {
957           err = get_certs_bypattern (sl->d, return_one_cert, ctx);
958           if (!err)
959             local_count++;
960           if (!err && single)
961             goto ready; 
962
963           if (gpg_err_code (err) == GPG_ERR_NO_DATA)
964             {
965               err = 0;
966               if (cache_only)
967                 any_no_data = 1;
968             }
969           else if (gpg_err_code (err) == GPG_ERR_INV_NAME && !cache_only)
970             {
971               /* No real fault because the internal pattern lookup
972                  can't yet cope with all types of pattern.  */
973               err = 0;
974             }
975           if (err)
976             goto ready;
977         }
978     }
979
980   /* Loop over all configured servers unless we want only the
981      certificates from the cache.  */
982   for (ldapserver_iter_begin (&ldapserver_iter, ctrl);
983        !cache_only && !ldapserver_iter_end_p (&ldapserver_iter)
984          && ldapserver_iter.server->host && !truncation_forced;
985        ldapserver_iter_next (&ldapserver_iter))
986     {
987       ldap_server_t ldapserver = ldapserver_iter.server;
988       
989       if (DBG_LOOKUP)
990         log_debug ("cmd_lookup: trying %s:%d base=%s\n", 
991                    ldapserver->host, ldapserver->port,
992                    ldapserver->base?ldapserver->base : "[default]");
993
994       /* Fetch certificates matching pattern */
995       err = start_cert_fetch (ctrl, &fetch_context, list, ldapserver);
996       if ( gpg_err_code (err) == GPG_ERR_NO_DATA )
997         {
998           if (DBG_LOOKUP)
999             log_debug ("cmd_lookup: no data\n");
1000           err = 0;
1001           any_no_data = 1;
1002           continue;
1003         }
1004       if (err)
1005         {
1006           log_error (_("start_cert_fetch failed: %s\n"), gpg_strerror (err));
1007           goto leave;
1008         }
1009
1010       /* Fetch the certificates for this query. */
1011       while (!truncation_forced)
1012         {
1013           xfree (value); value = NULL;
1014           err = fetch_next_cert (fetch_context, &value, &valuelen);
1015           if (gpg_err_code (err) == GPG_ERR_NO_DATA )
1016             {
1017               err = 0;
1018               any_no_data = 1;
1019               break; /* Ready. */
1020             }
1021           if (gpg_err_code (err) == GPG_ERR_TRUNCATED)
1022             {
1023               truncated = 1;
1024               err = 0;
1025               break;  /* Ready.  */
1026             }
1027           if (gpg_err_code (err) == GPG_ERR_EOF)
1028             {
1029               err = 0;
1030               break; /* Ready. */
1031             }
1032           if (!err && !value)
1033             {
1034               err = gpg_error (GPG_ERR_BUG);
1035               goto leave;
1036             }
1037           if (err)
1038             {
1039               log_error (_("fetch_next_cert failed: %s\n"),
1040                          gpg_strerror (err));
1041               end_cert_fetch (fetch_context);
1042               goto leave;
1043             }
1044           
1045           if (DBG_LOOKUP)
1046             log_debug ("cmd_lookup: returning one cert%s\n",
1047                        truncated? " (truncated)":"");
1048           
1049           /* Send the data, flush the buffer and then send an END line
1050              as a certificate delimiter. */
1051           err = assuan_send_data (ctx, value, valuelen);      
1052           if (!err)
1053             err = assuan_send_data (ctx, NULL, 0);
1054           if (!err)
1055             err = assuan_write_line (ctx, "END");
1056           if (err) 
1057             {
1058               log_error (_("error sending data: %s\n"), gpg_strerror (err));
1059               end_cert_fetch (fetch_context);
1060               goto leave;
1061             }
1062           
1063           if (++count >= opt.max_replies )
1064             {
1065               truncation_forced = 1;
1066               log_info (_("max_replies %d exceeded\n"), opt.max_replies );
1067             }
1068           if (single)
1069             break;
1070         }
1071
1072       end_cert_fetch (fetch_context);
1073     }
1074
1075  ready:
1076   if (truncated || truncation_forced)
1077     {
1078       char str[50];
1079
1080       sprintf (str, "%d", count);
1081       assuan_write_status (ctx, "TRUNCATED", str);    
1082     }
1083
1084   if (!err && !count && !local_count && any_no_data)
1085     err = gpg_error (GPG_ERR_NO_DATA);
1086
1087  leave:
1088   free_strlist (list);
1089   return err;
1090 }
1091
1092
1093 static const char hlp_lookup[] = 
1094   "LOOKUP [--url] [--single] [--cache-only] <pattern>\n"
1095   "\n"
1096   "Lookup certificates matching PATTERN. With --url the pattern is\n"
1097   "expected to be one URL.\n"
1098   "\n"
1099   "If --url is not given:  To allow for multiple patterns (which are ORed)\n"
1100   "quoting is required: Spaces are translated to \"+\" or \"%20\";\n"
1101   "obviously this requires that the usual escape quoting rules are applied.\n"
1102   "\n"
1103   "If --url is given no special escaping is required because URLs are\n"
1104   "already escaped this way.\n"
1105   "\n"
1106   "If --single is given the first and only the first match will be\n"
1107   "returned.  If --cache-only is _not_ given, no local query will be\n"
1108   "done.\n"
1109   "\n"
1110   "If --cache-only is given no external lookup is done so that only\n"
1111   "certificates from the cache may get returned.";
1112 static gpg_error_t
1113 cmd_lookup (assuan_context_t ctx, char *line)
1114 {
1115   gpg_error_t err;
1116   int lookup_url, single, cache_only;
1117
1118   lookup_url = has_leading_option (line, "--url");
1119   single = has_leading_option (line, "--single");
1120   cache_only = has_leading_option (line, "--cache-only");
1121   line = skip_options (line);
1122
1123   if (lookup_url && cache_only)
1124     err = gpg_error (GPG_ERR_NOT_FOUND);
1125   else if (lookup_url && single)
1126     err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
1127   else if (lookup_url)
1128     err = lookup_cert_by_url (ctx, line);
1129   else
1130     err = lookup_cert_by_pattern (ctx, line, single, cache_only);
1131
1132   return leave_cmd (ctx, err);
1133 }
1134
1135
1136 static const char hlp_loadcrl[] =
1137   "LOADCRL [--url] <filename|url>\n"
1138   "\n"
1139   "Load the CRL in the file with name FILENAME into our cache.  Note\n"
1140   "that FILENAME should be given with an absolute path because\n"
1141   "Dirmngrs cwd is not known.  With --url the CRL is directly loaded\n"
1142   "from the given URL.\n"
1143   "\n"
1144   "This command is usually used by gpgsm using the invocation \"gpgsm\n"
1145   "--call-dirmngr loadcrl <filename>\".  A direct invocation of Dirmngr\n"
1146   "is not useful because gpgsm might need to callback gpgsm to ask for\n"
1147   "the CA's certificate.";
1148 static gpg_error_t
1149 cmd_loadcrl (assuan_context_t ctx, char *line)
1150 {
1151   ctrl_t ctrl = assuan_get_pointer (ctx);
1152   gpg_error_t err = 0;
1153   int use_url = has_leading_option (line, "--url");
1154
1155   line = skip_options (line);
1156
1157   if (use_url)
1158     {
1159       ksba_reader_t reader;
1160
1161       err = crl_fetch (ctrl, line, &reader);
1162       if (err)
1163         log_error (_("fetching CRL from `%s' failed: %s\n"),
1164                    line, gpg_strerror (err));
1165       else
1166         {
1167           err = crl_cache_insert (ctrl, line, reader); 
1168           if (err)
1169             log_error (_("processing CRL from `%s' failed: %s\n"),
1170                        line, gpg_strerror (err));
1171           crl_close_reader (reader);
1172         }
1173     }
1174   else
1175     {
1176       char *buf;
1177
1178       buf = xtrymalloc (strlen (line)+1);
1179       if (!buf)
1180         err = gpg_error_from_syserror ();
1181       else
1182         {
1183           strcpy_escaped_plus (buf, line);
1184           err = crl_cache_load (ctrl, buf);
1185           xfree (buf);
1186         }
1187     }
1188
1189   return leave_cmd (ctx, err);
1190 }
1191
1192
1193 static const char hlp_listcrls[] =
1194   "LISTCRLS\n"
1195   "\n"
1196   "List the content of all CRLs in a readable format.  This command is\n"
1197   "usually used by gpgsm using the invocation \"gpgsm --call-dirmngr\n"
1198   "listcrls\".  It may also be used directly using \"dirmngr\n"
1199   "--list-crls\".";
1200 static gpg_error_t
1201 cmd_listcrls (assuan_context_t ctx, char *line)
1202 {
1203   gpg_error_t err;
1204   estream_t fp;
1205
1206   (void)line;
1207
1208   fp = es_fopencookie (ctx, "w", data_line_cookie_functions);
1209   if (!fp)
1210     err = set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream");
1211   else
1212     {
1213       err = crl_cache_list (fp);
1214       es_fclose (fp);
1215     }
1216   return leave_cmd (ctx, err);
1217 }
1218
1219
1220 static const char hlp_cachecert[] = 
1221   "CACHECERT\n"
1222   "\n"
1223   "Put a certificate into the internal cache.  This command might be\n"
1224   "useful if a client knows in advance certificates required for a\n"
1225   "test and wants to make sure they get added to the internal cache.\n"
1226   "It is also helpful for debugging.  To get the actual certificate,\n"
1227   "this command immediately inquires it using\n"
1228   "\n"
1229   "  INQUIRE TARGETCERT\n"
1230   "\n"
1231   "and the caller is expected to return the certificate for the\n"
1232   "request as a binary blob.";
1233 static gpg_error_t
1234 cmd_cachecert (assuan_context_t ctx, char *line)
1235 {
1236   ctrl_t ctrl = assuan_get_pointer (ctx);
1237   gpg_error_t err;
1238   ksba_cert_t cert = NULL;
1239   unsigned char *value = NULL;
1240   size_t valuelen; 
1241
1242   (void)line;
1243       
1244   err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1245                        &value, &valuelen, MAX_CERT_LENGTH);
1246   if (err)
1247     {
1248       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1249       goto leave;
1250     }
1251   
1252   if (!valuelen) /* No data returned; return a comprehensible error. */
1253     err = gpg_error (GPG_ERR_MISSING_CERT);
1254   else
1255     {
1256       err = ksba_cert_new (&cert);
1257       if (!err)
1258         err = ksba_cert_init_from_mem (cert, value, valuelen);
1259     }
1260   xfree (value);
1261   if(err)
1262     goto leave;
1263
1264   err = cache_cert (cert);
1265
1266  leave:
1267   ksba_cert_release (cert);
1268   return leave_cmd (ctx, err);
1269 }
1270
1271
1272 static const char hlp_validate[] =
1273   "VALIDATE\n"
1274   "\n"
1275   "Validate a certificate using the certificate validation function\n"
1276   "used internally by dirmngr.  This command is only useful for\n"
1277   "debugging.  To get the actual certificate, this command immediately\n"
1278   "inquires it using\n"
1279   "\n"
1280   "  INQUIRE TARGETCERT\n"
1281   "\n"
1282   "and the caller is expected to return the certificate for the\n"
1283   "request as a binary blob.";
1284 static gpg_error_t
1285 cmd_validate (assuan_context_t ctx, char *line)
1286 {
1287   ctrl_t ctrl = assuan_get_pointer (ctx);
1288   gpg_error_t err;
1289   ksba_cert_t cert = NULL;
1290   unsigned char *value = NULL;
1291   size_t valuelen; 
1292
1293   (void)line;
1294     
1295   err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT",
1296                        &value, &valuelen, MAX_CERT_LENGTH);
1297   if (err)
1298     {
1299       log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err));
1300       goto leave;
1301     }
1302   
1303   if (!valuelen) /* No data returned; return a comprehensible error. */
1304     err = gpg_error (GPG_ERR_MISSING_CERT);
1305   else
1306     {
1307       err = ksba_cert_new (&cert);
1308       if (!err)
1309         err = ksba_cert_init_from_mem (cert, value, valuelen);
1310     }
1311   xfree (value);
1312   if(err)
1313     goto leave;
1314
1315   /* If we have this certificate already in our cache, use the cached
1316      version for validation because this will take care of any cached
1317      results. */
1318   { 
1319     unsigned char fpr[20];
1320     ksba_cert_t tmpcert;
1321
1322     cert_compute_fpr (cert, fpr);
1323     tmpcert = get_cert_byfpr (fpr);
1324     if (tmpcert)
1325       {
1326         ksba_cert_release (cert);
1327         cert = tmpcert;
1328       }
1329   }
1330
1331   err = validate_cert_chain (ctrl, cert, NULL, VALIDATE_MODE_CERT, NULL);
1332
1333  leave:
1334   ksba_cert_release (cert);
1335   return leave_cmd (ctx, err);
1336 }
1337
1338
1339 \f
1340 static const char hlp_getinfo[] = 
1341   "GETINFO <what>\n"
1342   "\n"
1343   "Multi purpose command to return certain information.  \n"
1344   "Supported values of WHAT are:\n"
1345   "\n"
1346   "version     - Return the version of the program.\n"
1347   "pid         - Return the process id of the server.\n"
1348   "\n"
1349   "socket_name - Return the name of the socket.\n";
1350 static gpg_error_t
1351 cmd_getinfo (assuan_context_t ctx, char *line)
1352 {
1353   gpg_error_t err;
1354
1355   if (!strcmp (line, "version"))
1356     {
1357       const char *s = VERSION;
1358       err = assuan_send_data (ctx, s, strlen (s));
1359     }
1360   else if (!strcmp (line, "pid"))
1361     {
1362       char numbuf[50];
1363
1364       snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ());
1365       err = assuan_send_data (ctx, numbuf, strlen (numbuf));
1366     }
1367   else if (!strcmp (line, "socket_name"))
1368     {
1369       const char *s = dirmngr_socket_name ();
1370
1371       if (s)
1372         err = assuan_send_data (ctx, s, strlen (s));
1373       else
1374         err = gpg_error (GPG_ERR_NO_DATA);
1375     }
1376   else
1377     err = set_error (GPG_ERR_ASS_PARAMETER, "unknown value for WHAT");
1378
1379   return leave_cmd (ctx, err);
1380 }
1381
1382
1383 \f
1384 static const char hlp_killdirmngr[] =
1385   "KILLDIRMNGR\n"
1386   "\n"
1387   "This command allows a user - given sufficient permissions -\n"
1388   "to kill this dirmngr process.\n";
1389 static gpg_error_t
1390 cmd_killdirmngr (assuan_context_t ctx, char *line)
1391 {
1392   ctrl_t ctrl = assuan_get_pointer (ctx);
1393
1394   (void)line;
1395   
1396   if (opt.system_daemon)
1397     {
1398       if (opt.system_service)
1399         return set_error (GPG_ERR_NOT_SUPPORTED,
1400                           "can't do that whilst running as system service");
1401 #ifndef HAVE_W32_SYSTEM
1402       {
1403         gpg_err_code_t ec;
1404         assuan_peercred_t cred;
1405
1406         ec = gpg_err_code (assuan_get_peercred (ctx, &cred));
1407         if (!ec && cred->uid)
1408           ec = GPG_ERR_EPERM; /* Only root may terminate.  */
1409         if (ec)
1410           return set_error (ec, "no permission to kill this process");
1411       }
1412 #endif
1413     }
1414
1415   ctrl->server_local->stopme = 1;
1416   return gpg_error (GPG_ERR_EOF);
1417 }
1418
1419
1420 static const char hlp_reloaddirmngr[] =
1421   "RELOADDIRMNGR\n"
1422   "\n"
1423   "This command is an alternative to SIGHUP\n"
1424   "to reload the configuration.";
1425 static gpg_error_t
1426 cmd_reloaddirmngr (assuan_context_t ctx, char *line)
1427 {
1428   (void)ctx;
1429   (void)line;
1430
1431  if (opt.system_daemon)
1432     {
1433 #ifndef HAVE_W32_SYSTEM
1434       {
1435         gpg_err_code_t ec;
1436         assuan_peercred_t cred;
1437
1438         ec = gpg_err_code (assuan_get_peercred (ctx, &cred));
1439         if (!ec && cred->uid)
1440           ec = GPG_ERR_EPERM; /* Only root may terminate.  */
1441         if (ec)
1442           return set_error (ec, "no permission to reload this process");
1443       }
1444 #endif
1445     }
1446
1447   dirmngr_sighup_action ();
1448   return 0;
1449 }
1450
1451
1452
1453 \f
1454 /* Tell the assuan library about our commands. */
1455 static int
1456 register_commands (assuan_context_t ctx)
1457 {
1458   static struct {
1459     const char *name;
1460     assuan_handler_t handler;
1461     const char * const help;
1462   } table[] = {
1463     { "LDAPSERVER", cmd_ldapserver, hlp_ldapserver },
1464     { "ISVALID",    cmd_isvalid,    hlp_isvalid },
1465     { "CHECKCRL",   cmd_checkcrl,   hlp_checkcrl },
1466     { "CHECKOCSP",  cmd_checkocsp,  hlp_checkocsp },
1467     { "LOOKUP",     cmd_lookup,     hlp_lookup },
1468     { "LOADCRL",    cmd_loadcrl,    hlp_loadcrl },
1469     { "LISTCRLS",   cmd_listcrls,   hlp_listcrls },
1470     { "CACHECERT",  cmd_cachecert,  hlp_cachecert },
1471     { "VALIDATE",   cmd_validate,   hlp_validate },
1472     { "GETINFO",    cmd_getinfo,    hlp_getinfo },
1473     { "KILLDIRMNGR",cmd_killdirmngr,hlp_killdirmngr },
1474     { "RELOADDIRMNGR",cmd_reloaddirmngr,hlp_reloaddirmngr },
1475     { NULL, NULL }
1476   };
1477   int i, j, rc;
1478
1479   for (i=j=0; table[i].name; i++)
1480     {
1481       rc = assuan_register_command (ctx, table[i].name, table[i].handler,
1482                                     table[i].help);
1483       if (rc)
1484         return rc;
1485     }
1486   return 0;
1487 }
1488
1489
1490 static gpg_error_t
1491 reset_notify (assuan_context_t ctx, char *line)
1492 {
1493   ctrl_t ctrl = assuan_get_pointer (ctx);
1494   (void)line;
1495
1496   ldapserver_list_free (ctrl->server_local->ldapservers);
1497   ctrl->server_local->ldapservers = NULL;
1498   return 0;
1499 }
1500
1501
1502 /* Startup the server and run the main command loop.  With FD = -1
1503    used stdin/stdout. */
1504 void
1505 start_command_handler (assuan_fd_t fd)
1506 {
1507   static const char hello[] = "Dirmngr " VERSION " at your service";
1508   static char *hello_line;
1509   int rc;
1510   assuan_context_t ctx;
1511   ctrl_t ctrl;
1512
1513   ctrl = xtrycalloc (1, sizeof *ctrl);
1514   if (ctrl)
1515     ctrl->server_local = xtrycalloc (1, sizeof *ctrl->server_local);
1516   if (!ctrl || !ctrl->server_local)
1517     {
1518       log_error (_("can't allocate control structure: %s\n"),
1519                  strerror (errno));
1520       xfree (ctrl);
1521       return;
1522     }
1523     
1524   dirmngr_init_default_ctrl (ctrl);
1525
1526   rc = assuan_new (&ctx);
1527   if (rc)
1528     {
1529       log_error (_("failed to allocate assuan context: %s\n"),
1530                  gpg_strerror (rc));
1531       dirmngr_exit (2);
1532     }
1533
1534   if (fd == ASSUAN_INVALID_FD)
1535     {
1536       assuan_fd_t filedes[2];
1537       
1538       filedes[0] = assuan_fdopen (0);
1539       filedes[1] = assuan_fdopen (1);
1540       rc = assuan_init_pipe_server (ctx, filedes);
1541     }
1542   else
1543     {
1544       rc = assuan_init_socket_server (ctx, fd, ASSUAN_SOCKET_SERVER_ACCEPTED);
1545     }
1546
1547   if (rc)
1548     {
1549       assuan_release (ctx);
1550       log_error (_("failed to initialize the server: %s\n"),
1551                  gpg_strerror(rc));
1552       dirmngr_exit (2);
1553     }
1554
1555   rc = register_commands (ctx);
1556   if (rc)
1557     {
1558       log_error (_("failed to the register commands with Assuan: %s\n"),
1559                  gpg_strerror(rc));
1560       dirmngr_exit (2);
1561     }
1562
1563
1564   if (!hello_line)
1565     {
1566       size_t n;
1567       const char *cfgname;
1568
1569       cfgname = opt.config_filename? opt.config_filename : "[none]";
1570
1571       n = (30 + strlen (opt.homedir) + strlen (cfgname)
1572            + strlen (hello) + 1);
1573       hello_line = xmalloc (n+1);
1574       snprintf (hello_line, n,
1575                 "Home: %s\n"
1576                 "Config: %s\n"
1577                 "%s",
1578                 opt.homedir,
1579                 cfgname,
1580                 hello);
1581       hello_line[n] = 0;
1582     }
1583
1584   ctrl->server_local->assuan_ctx = ctx;
1585   assuan_set_pointer (ctx, ctrl);
1586
1587   assuan_set_hello_line (ctx, hello_line);
1588   assuan_register_option_handler (ctx, option_handler);
1589   assuan_register_reset_notify (ctx, reset_notify);
1590
1591   for (;;) 
1592     {
1593       rc = assuan_accept (ctx);
1594       if (rc == -1)
1595         break;
1596       if (rc)
1597         {
1598           log_info (_("Assuan accept problem: %s\n"), gpg_strerror (rc));
1599           break;
1600         }
1601
1602 #ifndef HAVE_W32_SYSTEM
1603       if (opt.verbose)
1604         {
1605           assuan_peercred_t peercred;
1606
1607           if (!assuan_get_peercred (ctx, &peercred))
1608             log_info ("connection from process %ld (%ld:%ld)\n",
1609                       (long)peercred->pid, (long)peercred->uid,
1610                       (long)peercred->gid);
1611         }
1612 #endif
1613
1614       rc = assuan_process (ctx);
1615       if (rc)
1616         {
1617           log_info (_("Assuan processing failed: %s\n"), gpg_strerror (rc));
1618           continue;
1619         }
1620     }
1621   
1622   ldap_wrapper_connection_cleanup (ctrl);
1623
1624   ldapserver_list_free (ctrl->server_local->ldapservers);
1625   ctrl->server_local->ldapservers = NULL;
1626
1627   ctrl->server_local->assuan_ctx = NULL;
1628   assuan_release (ctx);
1629
1630   if (ctrl->server_local->stopme)
1631     dirmngr_exit (0);
1632
1633   if (ctrl->refcount)
1634     log_error ("oops: connection control structure still referenced (%d)\n",
1635                ctrl->refcount);
1636   else
1637     {
1638       release_ctrl_ocsp_certs (ctrl);
1639       xfree (ctrl->server_local);
1640       xfree (ctrl);
1641     }
1642 }
1643
1644
1645 /* Send a status line back to the client.  KEYWORD is the status
1646    keyword, the optioal string argumenst are blank separated added to
1647    the line, the last argument must be a NULL. */
1648 gpg_error_t
1649 dirmngr_status (ctrl_t ctrl, const char *keyword, ...)
1650 {
1651   gpg_error_t err = 0;
1652   va_list arg_ptr;
1653   const char *text;
1654
1655   va_start (arg_ptr, keyword);
1656
1657   if (ctrl->server_local)
1658     {
1659       assuan_context_t ctx = ctrl->server_local->assuan_ctx;
1660       char buf[950], *p;
1661       size_t n;
1662       
1663       p = buf; 
1664       n = 0;
1665       while ( (text = va_arg (arg_ptr, const char *)) )
1666         {
1667           if (n)
1668             {
1669               *p++ = ' ';
1670               n++;
1671             }
1672           for ( ; *text && n < DIM (buf)-2; n++)
1673             *p++ = *text++;
1674         }
1675       *p = 0;
1676       err = assuan_write_status (ctx, keyword, buf);
1677     }
1678
1679   va_end (arg_ptr);
1680   return err;
1681 }
1682
1683
1684 /* Note, that we ignore CTRL for now but use the first connection to
1685    send the progress info back. */
1686 gpg_error_t
1687 dirmngr_tick (ctrl_t ctrl)
1688 {
1689   static time_t next_tick = 0;
1690   gpg_error_t err = 0;
1691   time_t now = time (NULL);
1692
1693   if (!next_tick)
1694     {
1695       next_tick = now + 1;
1696     }
1697   else if ( now > next_tick )
1698     {
1699       if (ctrl)
1700         {
1701           err = dirmngr_status (ctrl, "PROGRESS", "tick", "? 0 0", NULL);
1702           if (err)
1703             {
1704               /* Take this as in indication for a cancel request.  */
1705               err = gpg_error (GPG_ERR_CANCELED);
1706             }
1707           now = time (NULL);
1708         }
1709
1710       next_tick = now + 1;
1711     }
1712   return err;
1713 }