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