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