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