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