f561bb08c7377307e54b8262ab81a9c41c63fb02
[gnupg.git] / sm / call-dirmngr.c
1 /* call-dirmngr.c - Communication with the dirmngr
2  * Copyright (C) 2002, 2003, 2005, 2007, 2008,
3  *               2010  Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG 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 3 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG 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 <string.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <time.h>
28 #include <assert.h>
29 #include <ctype.h>
30
31 #include "gpgsm.h"
32 #include <gcrypt.h>
33 #include <assuan.h>
34
35 #include "i18n.h"
36 #include "keydb.h"
37 #include "asshelp.h"
38
39
40 struct membuf {
41   size_t len;
42   size_t size;
43   char *buf;
44   int out_of_core;
45 };
46
47
48
49 /* fixme: We need a context for each thread or serialize the access to
50    the dirmngr.  */
51 static assuan_context_t dirmngr_ctx = NULL;
52 static assuan_context_t dirmngr2_ctx = NULL;
53
54 static int dirmngr_ctx_locked;
55 static int dirmngr2_ctx_locked;
56
57 struct inq_certificate_parm_s {
58   ctrl_t ctrl;
59   assuan_context_t ctx;
60   ksba_cert_t cert;
61   ksba_cert_t issuer_cert;
62 };
63
64 struct isvalid_status_parm_s {
65   ctrl_t ctrl;
66   int seen;
67   unsigned char fpr[20];
68 };
69
70
71 struct lookup_parm_s {
72   ctrl_t ctrl;
73   assuan_context_t ctx;
74   void (*cb)(void *, ksba_cert_t);
75   void *cb_value;
76   struct membuf data;
77   int error;
78 };
79
80 struct run_command_parm_s {
81   assuan_context_t ctx;
82 };
83
84
85
86 static gpg_error_t get_cached_cert (assuan_context_t ctx,
87                                     const unsigned char *fpr,
88                                     ksba_cert_t *r_cert);
89
90
91 \f
92 /* A simple implementation of a dynamic buffer.  Use init_membuf() to
93    create a buffer, put_membuf to append bytes and get_membuf to
94    release and return the buffer.  Allocation errors are detected but
95    only returned at the final get_membuf(), this helps not to clutter
96    the code with out of core checks.  */
97
98 static void
99 init_membuf (struct membuf *mb, int initiallen)
100 {
101   mb->len = 0;
102   mb->size = initiallen;
103   mb->out_of_core = 0;
104   mb->buf = xtrymalloc (initiallen);
105   if (!mb->buf)
106       mb->out_of_core = 1;
107 }
108
109 static void
110 put_membuf (struct membuf *mb, const void *buf, size_t len)
111 {
112   if (mb->out_of_core)
113     return;
114
115   if (mb->len + len >= mb->size)
116     {
117       char *p;
118
119       mb->size += len + 1024;
120       p = xtryrealloc (mb->buf, mb->size);
121       if (!p)
122         {
123           mb->out_of_core = 1;
124           return;
125         }
126       mb->buf = p;
127     }
128   memcpy (mb->buf + mb->len, buf, len);
129   mb->len += len;
130 }
131
132 static void *
133 get_membuf (struct membuf *mb, size_t *len)
134 {
135   char *p;
136
137   if (mb->out_of_core)
138     {
139       xfree (mb->buf);
140       mb->buf = NULL;
141       return NULL;
142     }
143
144   p = mb->buf;
145   *len = mb->len;
146   mb->buf = NULL;
147   mb->out_of_core = 1; /* don't allow a reuse */
148   return p;
149 }
150
151
152 /* Print a warning if the server's version number is less than our
153    version number.  Returns an error code on a connection problem.  */
154 static gpg_error_t
155 warn_version_mismatch (ctrl_t ctrl, assuan_context_t ctx,
156                        const char *servername, int mode)
157 {
158   gpg_error_t err;
159   char *serverversion;
160   const char *myversion = strusage (13);
161
162   err = get_assuan_server_version (ctx, mode, &serverversion);
163   if (err)
164     log_error (_("error getting version from '%s': %s\n"),
165                servername, gpg_strerror (err));
166   else if (!compare_version_strings (serverversion, myversion))
167     {
168       char *warn;
169
170       warn = xtryasprintf (_("server '%s' is older than us (%s < %s)"),
171                            servername, serverversion, myversion);
172       if (!warn)
173         err = gpg_error_from_syserror ();
174       else
175         {
176           log_info (_("WARNING: %s\n"), warn);
177           gpgsm_status2 (ctrl, STATUS_WARNING, "server_version_mismatch 0",
178                          warn, NULL);
179           xfree (warn);
180         }
181     }
182   xfree (serverversion);
183   return err;
184 }
185
186
187 /* This function prepares the dirmngr for a new session.  The
188    audit-events option is used so that other dirmngr clients won't get
189    disturbed by such events.  */
190 static void
191 prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err)
192 {
193   struct keyserver_spec *server;
194
195   if (!err)
196     err = warn_version_mismatch (ctrl, ctx, DIRMNGR_NAME, 0);
197
198   if (!err)
199     {
200       err = assuan_transact (ctx, "OPTION audit-events=1",
201                              NULL, NULL, NULL, NULL, NULL, NULL);
202       if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
203         err = 0;  /* Allow the use of old dirmngr versions.  */
204     }
205   audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err);
206
207   if (!ctx || err)
208     return;
209
210   server = opt.keyserver;
211   while (server)
212     {
213       char line[ASSUAN_LINELENGTH];
214       char *user = server->user ? server->user : "";
215       char *pass = server->pass ? server->pass : "";
216       char *base = server->base ? server->base : "";
217
218       snprintf (line, DIM (line) - 1, "LDAPSERVER %s:%i:%s:%s:%s",
219                 server->host, server->port, user, pass, base);
220       line[DIM (line) - 1] = 0;
221
222       assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
223       /* The code below is not required because we don't return an error.  */
224       /* err = [above call]  */
225       /* if (gpg_err_code (err) == GPG_ERR_ASS_UNKNOWN_CMD) */
226       /*   err = 0;  /\* Allow the use of old dirmngr versions.  *\/ */
227
228       server = server->next;
229     }
230 }
231
232
233 \f
234 /* Return a new assuan context for a Dirmngr connection.  */
235 static gpg_error_t
236 start_dirmngr_ext (ctrl_t ctrl, assuan_context_t *ctx_r)
237 {
238   gpg_error_t err;
239   assuan_context_t ctx;
240
241   if (opt.disable_dirmngr || ctrl->offline)
242     return gpg_error (GPG_ERR_NO_DIRMNGR);
243
244   if (*ctx_r)
245     return 0;
246
247   /* Note: if you change this to multiple connections, you also need
248      to take care of the implicit option sending caching. */
249
250   err = start_new_dirmngr (&ctx, GPG_ERR_SOURCE_DEFAULT,
251                            opt.dirmngr_program,
252                            opt.autostart, opt.verbose, DBG_IPC,
253                            gpgsm_status2, ctrl);
254   if (!opt.autostart && gpg_err_code (err) == GPG_ERR_NO_DIRMNGR)
255     {
256       static int shown;
257
258       if (!shown)
259         {
260           shown = 1;
261           log_info (_("no dirmngr running in this session\n"));
262         }
263     }
264   prepare_dirmngr (ctrl, ctx, err);
265   if (err)
266     return err;
267
268   *ctx_r = ctx;
269   return 0;
270 }
271
272
273 static int
274 start_dirmngr (ctrl_t ctrl)
275 {
276   gpg_error_t err;
277
278   assert (! dirmngr_ctx_locked);
279   dirmngr_ctx_locked = 1;
280
281   err = start_dirmngr_ext (ctrl, &dirmngr_ctx);
282   /* We do not check ERR but the existence of a context because the
283      error might come from a failed command send to the dirmngr.
284      Fixme: Why don't we close the drimngr context if we encountered
285      an error in prepare_dirmngr?  */
286   if (!dirmngr_ctx)
287     dirmngr_ctx_locked = 0;
288   return err;
289 }
290
291
292 static void
293 release_dirmngr (ctrl_t ctrl)
294 {
295   (void)ctrl;
296
297   if (!dirmngr_ctx_locked)
298     log_error ("WARNING: trying to release a non-locked dirmngr ctx\n");
299   dirmngr_ctx_locked = 0;
300 }
301
302
303 static int
304 start_dirmngr2 (ctrl_t ctrl)
305 {
306   gpg_error_t err;
307
308   assert (! dirmngr2_ctx_locked);
309   dirmngr2_ctx_locked = 1;
310
311   err = start_dirmngr_ext (ctrl, &dirmngr2_ctx);
312   if (!dirmngr2_ctx)
313     dirmngr2_ctx_locked = 0;
314   return err;
315 }
316
317
318 static void
319 release_dirmngr2 (ctrl_t ctrl)
320 {
321   (void)ctrl;
322
323   if (!dirmngr2_ctx_locked)
324     log_error ("WARNING: trying to release a non-locked dirmngr2 ctx\n");
325   dirmngr2_ctx_locked = 0;
326 }
327
328
329 \f
330 /* Handle a SENDCERT inquiry. */
331 static gpg_error_t
332 inq_certificate (void *opaque, const char *line)
333 {
334   struct inq_certificate_parm_s *parm = opaque;
335   const char *s;
336   int rc;
337   size_t n;
338   const unsigned char *der;
339   size_t derlen;
340   int issuer_mode = 0;
341   ksba_sexp_t ski = NULL;
342
343   if ((s = has_leading_keyword (line, "SENDCERT")))
344     {
345       line = s;
346     }
347   else if ((s = has_leading_keyword (line, "SENDCERT_SKI")))
348     {
349       /* Send a certificate where a sourceKeyIdentifier is included. */
350       line = s;
351       ski = make_simple_sexp_from_hexstr (line, &n);
352       line += n;
353       while (*line == ' ')
354         line++;
355     }
356   else if ((s = has_leading_keyword (line, "SENDISSUERCERT")))
357     {
358       line = s;
359       issuer_mode = 1;
360     }
361   else if ((s = has_leading_keyword (line, "ISTRUSTED")))
362     {
363       /* The server is asking us whether the certificate is a trusted
364          root certificate.  */
365       char fpr[41];
366       struct rootca_flags_s rootca_flags;
367
368       line = s;
369
370       for (s=line,n=0; hexdigitp (s); s++, n++)
371         ;
372       if (*s || n != 40)
373         return gpg_error (GPG_ERR_ASS_PARAMETER);
374       for (s=line, n=0; n < 40; s++, n++)
375         fpr[n] = (*s >= 'a')? (*s & 0xdf): *s;
376       fpr[n] = 0;
377
378       if (!gpgsm_agent_istrusted (parm->ctrl, NULL, fpr, &rootca_flags))
379         rc = assuan_send_data (parm->ctx, "1", 1);
380       else
381         rc = 0;
382       return rc;
383     }
384   else
385     {
386       log_error ("unsupported inquiry '%s'\n", line);
387       return gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
388     }
389
390   if (!*line)
391     { /* Send the current certificate. */
392       der = ksba_cert_get_image (issuer_mode? parm->issuer_cert : parm->cert,
393                                  &derlen);
394       if (!der)
395         rc = gpg_error (GPG_ERR_INV_CERT_OBJ);
396       else
397         rc = assuan_send_data (parm->ctx, der, derlen);
398     }
399   else if (issuer_mode)
400     {
401       log_error ("sending specific issuer certificate back "
402                  "is not yet implemented\n");
403       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
404     }
405   else
406     { /* Send the given certificate. */
407       int err;
408       ksba_cert_t cert;
409
410
411       err = gpgsm_find_cert (line, ski, &cert);
412       if (err)
413         {
414           log_error ("certificate not found: %s\n", gpg_strerror (err));
415           rc = gpg_error (GPG_ERR_NOT_FOUND);
416         }
417       else
418         {
419           der = ksba_cert_get_image (cert, &derlen);
420           if (!der)
421             rc = gpg_error (GPG_ERR_INV_CERT_OBJ);
422           else
423             rc = assuan_send_data (parm->ctx, der, derlen);
424           ksba_cert_release (cert);
425         }
426     }
427
428   xfree (ski);
429   return rc;
430 }
431
432
433 /* Take a 20 byte hexencoded string and put it into the the provided
434    20 byte buffer FPR in binary format. */
435 static int
436 unhexify_fpr (const char *hexstr, unsigned char *fpr)
437 {
438   const char *s;
439   int n;
440
441   for (s=hexstr, n=0; hexdigitp (s); s++, n++)
442     ;
443   if (*s || (n != 40))
444     return 0; /* no fingerprint (invalid or wrong length). */
445   for (s=hexstr, n=0; *s; s += 2, n++)
446     fpr[n] = xtoi_2 (s);
447   return 1; /* okay */
448 }
449
450
451 static gpg_error_t
452 isvalid_status_cb (void *opaque, const char *line)
453 {
454   struct isvalid_status_parm_s *parm = opaque;
455   const char *s;
456
457   if ((s = has_leading_keyword (line, "PROGRESS")))
458     {
459       if (parm->ctrl)
460         {
461           line = s;
462           if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
463             return gpg_error (GPG_ERR_ASS_CANCELED);
464         }
465     }
466   else if ((s = has_leading_keyword (line, "ONLY_VALID_IF_CERT_VALID")))
467     {
468       parm->seen++;
469       if (!*s || !unhexify_fpr (s, parm->fpr))
470         parm->seen++; /* Bumb it to indicate an error. */
471     }
472   return 0;
473 }
474
475
476
477 \f
478 /* Call the directory manager to check whether the certificate is valid
479    Returns 0 for valid or usually one of the errors:
480
481   GPG_ERR_CERTIFICATE_REVOKED
482   GPG_ERR_NO_CRL_KNOWN
483   GPG_ERR_CRL_TOO_OLD
484
485   Values for USE_OCSP:
486      0 = Do CRL check.
487      1 = Do an OCSP check.
488      2 = Do an OCSP check using only the default responder.
489  */
490 int
491 gpgsm_dirmngr_isvalid (ctrl_t ctrl,
492                        ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp)
493 {
494   static int did_options;
495   int rc;
496   char *certid;
497   char line[ASSUAN_LINELENGTH];
498   struct inq_certificate_parm_s parm;
499   struct isvalid_status_parm_s stparm;
500
501   rc = start_dirmngr (ctrl);
502   if (rc)
503     return rc;
504
505   if (use_ocsp)
506     {
507       certid = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
508     }
509   else
510     {
511       certid = gpgsm_get_certid (cert);
512       if (!certid)
513         {
514           log_error ("error getting the certificate ID\n");
515           release_dirmngr (ctrl);
516           return gpg_error (GPG_ERR_GENERAL);
517         }
518     }
519
520   if (opt.verbose > 1)
521     {
522       char *fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1);
523       log_info ("asking dirmngr about %s%s\n", fpr,
524                 use_ocsp? " (using OCSP)":"");
525       xfree (fpr);
526     }
527
528   parm.ctx = dirmngr_ctx;
529   parm.ctrl = ctrl;
530   parm.cert = cert;
531   parm.issuer_cert = issuer_cert;
532
533   stparm.ctrl = ctrl;
534   stparm.seen = 0;
535   memset (stparm.fpr, 0, 20);
536
537   /* FIXME: If --disable-crl-checks has been set, we should pass an
538      option to dirmngr, so that no fallback CRL check is done after an
539      ocsp check.  It is not a problem right now as dirmngr does not
540      fallback to CRL checking.  */
541
542   /* It is sufficient to send the options only once because we have
543      one connection per process only. */
544   if (!did_options)
545     {
546       if (opt.force_crl_refresh)
547         assuan_transact (dirmngr_ctx, "OPTION force-crl-refresh=1",
548                          NULL, NULL, NULL, NULL, NULL, NULL);
549       did_options = 1;
550     }
551   snprintf (line, DIM(line)-1, "ISVALID%s %s",
552             use_ocsp == 2? " --only-ocsp --force-default-responder":"",
553             certid);
554   line[DIM(line)-1] = 0;
555   xfree (certid);
556
557   rc = assuan_transact (dirmngr_ctx, line, NULL, NULL,
558                         inq_certificate, &parm,
559                         isvalid_status_cb, &stparm);
560   if (opt.verbose > 1)
561     log_info ("response of dirmngr: %s\n", rc? gpg_strerror (rc): "okay");
562
563   if (!rc && stparm.seen)
564     {
565       /* Need to also check the certificate validity. */
566       if (stparm.seen != 1)
567         {
568           log_error ("communication problem with dirmngr detected\n");
569           rc = gpg_error (GPG_ERR_INV_CRL);
570         }
571       else
572         {
573           ksba_cert_t rspcert = NULL;
574
575           if (get_cached_cert (dirmngr_ctx, stparm.fpr, &rspcert))
576             {
577               /* Ooops: Something went wrong getting the certificate
578                  from the dirmngr.  Try our own cert store now.  */
579               KEYDB_HANDLE kh;
580
581               kh = keydb_new (0);
582               if (!kh)
583                 rc = gpg_error (GPG_ERR_ENOMEM);
584               if (!rc)
585                 rc = keydb_search_fpr (kh, stparm.fpr);
586               if (!rc)
587                 rc = keydb_get_cert (kh, &rspcert);
588               if (rc)
589                 {
590                   log_error ("unable to find the certificate used "
591                              "by the dirmngr: %s\n", gpg_strerror (rc));
592                   rc = gpg_error (GPG_ERR_INV_CRL);
593                 }
594               keydb_release (kh);
595             }
596
597           if (!rc)
598             {
599               rc = gpgsm_cert_use_ocsp_p (rspcert);
600               if (rc)
601                 rc = gpg_error (GPG_ERR_INV_CRL);
602               else
603                 {
604                   /* Note the no_dirmngr flag: This avoids checking
605                      this certificate over and over again. */
606                   rc = gpgsm_validate_chain (ctrl, rspcert, "", NULL, 0, NULL,
607                                              VALIDATE_FLAG_NO_DIRMNGR, NULL);
608                   if (rc)
609                     {
610                       log_error ("invalid certificate used for CRL/OCSP: %s\n",
611                                  gpg_strerror (rc));
612                       rc = gpg_error (GPG_ERR_INV_CRL);
613                     }
614                 }
615             }
616           ksba_cert_release (rspcert);
617         }
618     }
619   release_dirmngr (ctrl);
620   return rc;
621 }
622
623
624 \f
625 /* Lookup helpers*/
626 static gpg_error_t
627 lookup_cb (void *opaque, const void *buffer, size_t length)
628 {
629   struct lookup_parm_s *parm = opaque;
630   size_t len;
631   char *buf;
632   ksba_cert_t cert;
633   int rc;
634
635   if (parm->error)
636     return 0;
637
638   if (buffer)
639     {
640       put_membuf (&parm->data, buffer, length);
641       return 0;
642     }
643   /* END encountered - process what we have */
644   buf = get_membuf (&parm->data, &len);
645   if (!buf)
646     {
647       parm->error = gpg_error (GPG_ERR_ENOMEM);
648       return 0;
649     }
650
651   rc = ksba_cert_new (&cert);
652   if (rc)
653     {
654       parm->error = rc;
655       return 0;
656     }
657   rc = ksba_cert_init_from_mem (cert, buf, len);
658   if (rc)
659     {
660       log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
661     }
662   else
663     {
664       parm->cb (parm->cb_value, cert);
665     }
666
667   ksba_cert_release (cert);
668   init_membuf (&parm->data, 4096);
669   return 0;
670 }
671
672 /* Return a properly escaped pattern from NAMES.  The only error
673    return is NULL to indicate a malloc failure. */
674 static char *
675 pattern_from_strlist (strlist_t names)
676 {
677   strlist_t sl;
678   int n;
679   const char *s;
680   char *pattern, *p;
681
682   for (n=0, sl=names; sl; sl = sl->next)
683     {
684       for (s=sl->d; *s; s++, n++)
685         {
686           if (*s == '%' || *s == ' ' || *s == '+')
687             n += 2;
688         }
689       n++;
690     }
691
692   p = pattern = xtrymalloc (n+1);
693   if (!pattern)
694     return NULL;
695
696   for (sl=names; sl; sl = sl->next)
697     {
698       for (s=sl->d; *s; s++)
699         {
700           switch (*s)
701             {
702             case '%':
703               *p++ = '%';
704               *p++ = '2';
705               *p++ = '5';
706               break;
707             case ' ':
708               *p++ = '%';
709               *p++ = '2';
710               *p++ = '0';
711               break;
712             case '+':
713               *p++ = '%';
714               *p++ = '2';
715               *p++ = 'B';
716               break;
717             default:
718               *p++ = *s;
719               break;
720             }
721         }
722       *p++ = ' ';
723     }
724   if (p == pattern)
725     *pattern = 0; /* is empty */
726   else
727     p[-1] = '\0'; /* remove trailing blank */
728
729   return pattern;
730 }
731
732 static gpg_error_t
733 lookup_status_cb (void *opaque, const char *line)
734 {
735   struct lookup_parm_s *parm = opaque;
736   const char *s;
737
738   if ((s = has_leading_keyword (line, "PROGRESS")))
739     {
740       if (parm->ctrl)
741         {
742           line = s;
743           if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
744             return gpg_error (GPG_ERR_ASS_CANCELED);
745         }
746     }
747   else if ((s = has_leading_keyword (line, "TRUNCATED")))
748     {
749       if (parm->ctrl)
750         {
751           line = s;
752           gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line);
753         }
754     }
755   return 0;
756 }
757
758
759 /* Run the Directory Manager's lookup command using the pattern
760    compiled from the strings given in NAMES.  The caller must provide
761    the callback CB which will be passed cert by cert.  Note that CTRL
762    is optional.  With CACHE_ONLY the dirmngr will search only its own
763    key cache. */
764 int
765 gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, int cache_only,
766                       void (*cb)(void*, ksba_cert_t), void *cb_value)
767 {
768   int rc;
769   char *pattern;
770   char line[ASSUAN_LINELENGTH];
771   struct lookup_parm_s parm;
772   size_t len;
773   assuan_context_t ctx;
774
775   /* The lookup function can be invoked from the callback of a lookup
776      function, for example to walk the chain.  */
777   if (!dirmngr_ctx_locked)
778     {
779       rc = start_dirmngr (ctrl);
780       if (rc)
781         return rc;
782       ctx = dirmngr_ctx;
783     }
784   else if (!dirmngr2_ctx_locked)
785     {
786       rc = start_dirmngr2 (ctrl);
787       if (rc)
788         return rc;
789       ctx = dirmngr2_ctx;
790     }
791   else
792     {
793       log_fatal ("both dirmngr contexts are in use\n");
794     }
795
796   pattern = pattern_from_strlist (names);
797   if (!pattern)
798     {
799       if (ctx == dirmngr_ctx)
800         release_dirmngr (ctrl);
801       else
802         release_dirmngr2 (ctrl);
803
804       return out_of_core ();
805     }
806   snprintf (line, DIM(line)-1, "LOOKUP%s %s",
807             cache_only? " --cache-only":"", pattern);
808   line[DIM(line)-1] = 0;
809   xfree (pattern);
810
811   parm.ctrl = ctrl;
812   parm.ctx = ctx;
813   parm.cb = cb;
814   parm.cb_value = cb_value;
815   parm.error = 0;
816   init_membuf (&parm.data, 4096);
817
818   rc = assuan_transact (ctx, line, lookup_cb, &parm,
819                         NULL, NULL, lookup_status_cb, &parm);
820   xfree (get_membuf (&parm.data, &len));
821
822   if (ctx == dirmngr_ctx)
823     release_dirmngr (ctrl);
824   else
825     release_dirmngr2 (ctrl);
826
827   if (rc)
828       return rc;
829   return parm.error;
830 }
831
832
833 \f
834 static gpg_error_t
835 get_cached_cert_data_cb (void *opaque, const void *buffer, size_t length)
836 {
837   struct membuf *mb = opaque;
838
839   if (buffer)
840     put_membuf (mb, buffer, length);
841   return 0;
842 }
843
844 /* Return a certificate from the Directory Manager's cache.  This
845    function only returns one certificate which must be specified using
846    the fingerprint FPR and will be stored at R_CERT.  On error NULL is
847    stored at R_CERT and an error code returned.  Note that the caller
848    must provide the locked dirmngr context CTX. */
849 static gpg_error_t
850 get_cached_cert (assuan_context_t ctx,
851                  const unsigned char *fpr, ksba_cert_t *r_cert)
852 {
853   gpg_error_t err;
854   char line[ASSUAN_LINELENGTH];
855   char hexfpr[2*20+1];
856   struct membuf mb;
857   char *buf;
858   size_t buflen = 0;
859   ksba_cert_t cert;
860
861   *r_cert = NULL;
862
863   bin2hex (fpr, 20, hexfpr);
864   snprintf (line, DIM(line)-1, "LOOKUP --single --cache-only 0x%s", hexfpr);
865
866   init_membuf (&mb, 4096);
867   err = assuan_transact (ctx, line, get_cached_cert_data_cb, &mb,
868                          NULL, NULL, NULL, NULL);
869   buf = get_membuf (&mb, &buflen);
870   if (err)
871     {
872       xfree (buf);
873       return err;
874     }
875   if (!buf)
876     return gpg_error (GPG_ERR_ENOMEM);
877
878   err = ksba_cert_new (&cert);
879   if (err)
880     {
881       xfree (buf);
882       return err;
883     }
884   err = ksba_cert_init_from_mem (cert, buf, buflen);
885   xfree (buf);
886   if (err)
887     {
888       log_error ("failed to parse a certificate: %s\n", gpg_strerror (err));
889       ksba_cert_release (cert);
890       return err;
891     }
892
893   *r_cert = cert;
894   return 0;
895 }
896
897
898 \f
899 /* Run Command helpers*/
900
901 /* Fairly simple callback to write all output of dirmngr to stdout. */
902 static gpg_error_t
903 run_command_cb (void *opaque, const void *buffer, size_t length)
904 {
905   (void)opaque;
906
907   if (buffer)
908     {
909       if ( fwrite (buffer, length, 1, stdout) != 1 )
910         log_error ("error writing to stdout: %s\n", strerror (errno));
911     }
912   return 0;
913 }
914
915 /* Handle inquiries from the dirmngr COMMAND. */
916 static gpg_error_t
917 run_command_inq_cb (void *opaque, const char *line)
918 {
919   struct run_command_parm_s *parm = opaque;
920   const char *s;
921   int rc = 0;
922
923   if ((s = has_leading_keyword (line, "SENDCERT")))
924     { /* send the given certificate */
925       int err;
926       ksba_cert_t cert;
927       const unsigned char *der;
928       size_t derlen;
929
930       line = s;
931       if (!*line)
932         return gpg_error (GPG_ERR_ASS_PARAMETER);
933
934       err = gpgsm_find_cert (line, NULL, &cert);
935       if (err)
936         {
937           log_error ("certificate not found: %s\n", gpg_strerror (err));
938           rc = gpg_error (GPG_ERR_NOT_FOUND);
939         }
940       else
941         {
942           der = ksba_cert_get_image (cert, &derlen);
943           if (!der)
944             rc = gpg_error (GPG_ERR_INV_CERT_OBJ);
945           else
946             rc = assuan_send_data (parm->ctx, der, derlen);
947           ksba_cert_release (cert);
948         }
949     }
950   else if ((s = has_leading_keyword (line, "PRINTINFO")))
951     { /* Simply show the message given in the argument. */
952       line = s;
953       log_info ("dirmngr: %s\n", line);
954     }
955   else
956     {
957       log_error ("unsupported inquiry '%s'\n", line);
958       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
959     }
960
961   return rc;
962 }
963
964 static gpg_error_t
965 run_command_status_cb (void *opaque, const char *line)
966 {
967   ctrl_t ctrl = opaque;
968   const char *s;
969
970   if (opt.verbose)
971     {
972       log_info ("dirmngr status: %s\n", line);
973     }
974   if ((s = has_leading_keyword (line, "PROGRESS")))
975     {
976       if (ctrl)
977         {
978           line = s;
979           if (gpgsm_status (ctrl, STATUS_PROGRESS, line))
980             return gpg_error (GPG_ERR_ASS_CANCELED);
981         }
982     }
983   return 0;
984 }
985
986
987
988 /* Pass COMMAND to dirmngr and print all output generated by Dirmngr
989    to stdout.  A couple of inquiries are defined (see above).  ARGC
990    arguments in ARGV are given to the Dirmngr.  Spaces, plus and
991    percent characters within the argument strings are percent escaped
992    so that blanks can act as delimiters. */
993 int
994 gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
995                            int argc, char **argv)
996 {
997   int rc;
998   int i;
999   const char *s;
1000   char *line, *p;
1001   size_t len;
1002   struct run_command_parm_s parm;
1003
1004   rc = start_dirmngr (ctrl);
1005   if (rc)
1006     return rc;
1007
1008   parm.ctx = dirmngr_ctx;
1009
1010   len = strlen (command) + 1;
1011   for (i=0; i < argc; i++)
1012     len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
1013   line = xtrymalloc (len);
1014   if (!line)
1015     {
1016       release_dirmngr (ctrl);
1017       return out_of_core ();
1018     }
1019
1020   p = stpcpy (line, command);
1021   for (i=0; i < argc; i++)
1022     {
1023       *p++ = ' ';
1024       for (s=argv[i]; *s; s++)
1025         {
1026           if (!isascii (*s))
1027             *p++ = *s;
1028           else if (*s == ' ')
1029             *p++ = '+';
1030           else if (!isprint (*s) || *s == '+')
1031             {
1032               sprintf (p, "%%%02X", *(const unsigned char *)s);
1033               p += 3;
1034             }
1035           else
1036             *p++ = *s;
1037         }
1038     }
1039   *p = 0;
1040
1041   rc = assuan_transact (dirmngr_ctx, line,
1042                         run_command_cb, NULL,
1043                         run_command_inq_cb, &parm,
1044                         run_command_status_cb, ctrl);
1045   xfree (line);
1046   log_info ("response of dirmngr: %s\n", rc? gpg_strerror (rc): "okay");
1047   release_dirmngr (ctrl);
1048   return rc;
1049 }