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