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