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