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