Explain the "server is older than xxx warning".
[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 <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);
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.
495      2 = Do 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;
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   if (use_ocsp)
513     {
514       certid = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
515     }
516   else
517     {
518       certid = gpgsm_get_certid (cert);
519       if (!certid)
520         {
521           log_error ("error getting the certificate ID\n");
522           release_dirmngr (ctrl);
523           return gpg_error (GPG_ERR_GENERAL);
524         }
525     }
526
527   if (opt.verbose > 1)
528     {
529       char *fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1);
530       log_info ("asking dirmngr about %s%s\n", fpr,
531                 use_ocsp? " (using OCSP)":"");
532       xfree (fpr);
533     }
534
535   parm.ctx = dirmngr_ctx;
536   parm.ctrl = ctrl;
537   parm.cert = cert;
538   parm.issuer_cert = issuer_cert;
539
540   stparm.ctrl = ctrl;
541   stparm.seen = 0;
542   memset (stparm.fpr, 0, 20);
543
544   /* FIXME: If --disable-crl-checks has been set, we should pass an
545      option to dirmngr, so that no fallback CRL check is done after an
546      ocsp check.  It is not a problem right now as dirmngr does not
547      fallback to CRL checking.  */
548
549   /* It is sufficient to send the options only once because we have
550      one connection per process only. */
551   if (!did_options)
552     {
553       if (opt.force_crl_refresh)
554         assuan_transact (dirmngr_ctx, "OPTION force-crl-refresh=1",
555                          NULL, NULL, NULL, NULL, NULL, NULL);
556       did_options = 1;
557     }
558   snprintf (line, DIM(line), "ISVALID%s %s",
559             use_ocsp == 2? " --only-ocsp --force-default-responder":"",
560             certid);
561   xfree (certid);
562
563   rc = assuan_transact (dirmngr_ctx, line, NULL, NULL,
564                         inq_certificate, &parm,
565                         isvalid_status_cb, &stparm);
566   if (opt.verbose > 1)
567     log_info ("response of dirmngr: %s\n", rc? gpg_strerror (rc): "okay");
568
569   if (!rc && stparm.seen)
570     {
571       /* Need to also check the certificate validity. */
572       if (stparm.seen != 1)
573         {
574           log_error ("communication problem with dirmngr detected\n");
575           rc = gpg_error (GPG_ERR_INV_CRL);
576         }
577       else
578         {
579           ksba_cert_t rspcert = NULL;
580
581           if (get_cached_cert (dirmngr_ctx, stparm.fpr, &rspcert))
582             {
583               /* Ooops: Something went wrong getting the certificate
584                  from the dirmngr.  Try our own cert store now.  */
585               KEYDB_HANDLE kh;
586
587               kh = keydb_new ();
588               if (!kh)
589                 rc = gpg_error (GPG_ERR_ENOMEM);
590               if (!rc)
591                 rc = keydb_search_fpr (ctrl, kh, stparm.fpr);
592               if (!rc)
593                 rc = keydb_get_cert (kh, &rspcert);
594               if (rc)
595                 {
596                   log_error ("unable to find the certificate used "
597                              "by the dirmngr: %s\n", gpg_strerror (rc));
598                   rc = gpg_error (GPG_ERR_INV_CRL);
599                 }
600               keydb_release (kh);
601             }
602
603           if (!rc)
604             {
605               rc = gpgsm_cert_use_ocsp_p (rspcert);
606               if (rc)
607                 rc = gpg_error (GPG_ERR_INV_CRL);
608               else
609                 {
610                   /* Note the no_dirmngr flag: This avoids checking
611                      this certificate over and over again. */
612                   rc = gpgsm_validate_chain (ctrl, rspcert, "", NULL, 0, NULL,
613                                              VALIDATE_FLAG_NO_DIRMNGR, NULL);
614                   if (rc)
615                     {
616                       log_error ("invalid certificate used for CRL/OCSP: %s\n",
617                                  gpg_strerror (rc));
618                       rc = gpg_error (GPG_ERR_INV_CRL);
619                     }
620                 }
621             }
622           ksba_cert_release (rspcert);
623         }
624     }
625   release_dirmngr (ctrl);
626   return rc;
627 }
628
629
630 \f
631 /* Lookup helpers*/
632 static gpg_error_t
633 lookup_cb (void *opaque, const void *buffer, size_t length)
634 {
635   struct lookup_parm_s *parm = opaque;
636   size_t len;
637   char *buf;
638   ksba_cert_t cert;
639   int rc;
640
641   if (parm->error)
642     return 0;
643
644   if (buffer)
645     {
646       put_membuf (&parm->data, buffer, length);
647       return 0;
648     }
649   /* END encountered - process what we have */
650   buf = get_membuf (&parm->data, &len);
651   if (!buf)
652     {
653       parm->error = gpg_error (GPG_ERR_ENOMEM);
654       return 0;
655     }
656
657   rc = ksba_cert_new (&cert);
658   if (rc)
659     {
660       parm->error = rc;
661       return 0;
662     }
663   rc = ksba_cert_init_from_mem (cert, buf, len);
664   if (rc)
665     {
666       log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
667     }
668   else
669     {
670       parm->cb (parm->cb_value, cert);
671     }
672
673   ksba_cert_release (cert);
674   init_membuf (&parm->data, 4096);
675   return 0;
676 }
677
678 /* Return a properly escaped pattern from NAMES.  The only error
679    return is NULL to indicate a malloc failure. */
680 static char *
681 pattern_from_strlist (strlist_t names)
682 {
683   strlist_t sl;
684   int n;
685   const char *s;
686   char *pattern, *p;
687
688   for (n=0, sl=names; sl; sl = sl->next)
689     {
690       for (s=sl->d; *s; s++, n++)
691         {
692           if (*s == '%' || *s == ' ' || *s == '+')
693             n += 2;
694         }
695       n++;
696     }
697
698   p = pattern = xtrymalloc (n+1);
699   if (!pattern)
700     return NULL;
701
702   for (sl=names; sl; sl = sl->next)
703     {
704       for (s=sl->d; *s; s++)
705         {
706           switch (*s)
707             {
708             case '%':
709               *p++ = '%';
710               *p++ = '2';
711               *p++ = '5';
712               break;
713             case ' ':
714               *p++ = '%';
715               *p++ = '2';
716               *p++ = '0';
717               break;
718             case '+':
719               *p++ = '%';
720               *p++ = '2';
721               *p++ = 'B';
722               break;
723             default:
724               *p++ = *s;
725               break;
726             }
727         }
728       *p++ = ' ';
729     }
730   if (p == pattern)
731     *pattern = 0; /* is empty */
732   else
733     p[-1] = '\0'; /* remove trailing blank */
734
735   return pattern;
736 }
737
738 static gpg_error_t
739 lookup_status_cb (void *opaque, const char *line)
740 {
741   struct lookup_parm_s *parm = opaque;
742   const char *s;
743
744   if ((s = has_leading_keyword (line, "PROGRESS")))
745     {
746       if (parm->ctrl)
747         {
748           line = s;
749           if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
750             return gpg_error (GPG_ERR_ASS_CANCELED);
751         }
752     }
753   else if ((s = has_leading_keyword (line, "TRUNCATED")))
754     {
755       if (parm->ctrl)
756         {
757           line = s;
758           gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line);
759         }
760     }
761   return 0;
762 }
763
764
765 /* Run the Directory Manager's lookup command using the pattern
766    compiled from the strings given in NAMES.  The caller must provide
767    the callback CB which will be passed cert by cert.  Note that CTRL
768    is optional.  With CACHE_ONLY the dirmngr will search only its own
769    key cache. */
770 int
771 gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, int cache_only,
772                       void (*cb)(void*, ksba_cert_t), void *cb_value)
773 {
774   int rc;
775   char *pattern;
776   char line[ASSUAN_LINELENGTH];
777   struct lookup_parm_s parm;
778   size_t len;
779   assuan_context_t ctx;
780
781   /* The lookup function can be invoked from the callback of a lookup
782      function, for example to walk the chain.  */
783   if (!dirmngr_ctx_locked)
784     {
785       rc = start_dirmngr (ctrl);
786       if (rc)
787         return rc;
788       ctx = dirmngr_ctx;
789     }
790   else if (!dirmngr2_ctx_locked)
791     {
792       rc = start_dirmngr2 (ctrl);
793       if (rc)
794         return rc;
795       ctx = dirmngr2_ctx;
796     }
797   else
798     {
799       log_fatal ("both dirmngr contexts are in use\n");
800     }
801
802   pattern = pattern_from_strlist (names);
803   if (!pattern)
804     {
805       if (ctx == dirmngr_ctx)
806         release_dirmngr (ctrl);
807       else
808         release_dirmngr2 (ctrl);
809
810       return out_of_core ();
811     }
812   snprintf (line, DIM(line), "LOOKUP%s %s",
813             cache_only? " --cache-only":"", pattern);
814   xfree (pattern);
815
816   parm.ctrl = ctrl;
817   parm.ctx = ctx;
818   parm.cb = cb;
819   parm.cb_value = cb_value;
820   parm.error = 0;
821   init_membuf (&parm.data, 4096);
822
823   rc = assuan_transact (ctx, line, lookup_cb, &parm,
824                         NULL, NULL, lookup_status_cb, &parm);
825   xfree (get_membuf (&parm.data, &len));
826
827   if (ctx == dirmngr_ctx)
828     release_dirmngr (ctrl);
829   else
830     release_dirmngr2 (ctrl);
831
832   if (rc)
833       return rc;
834   return parm.error;
835 }
836
837
838 \f
839 static gpg_error_t
840 get_cached_cert_data_cb (void *opaque, const void *buffer, size_t length)
841 {
842   struct membuf *mb = opaque;
843
844   if (buffer)
845     put_membuf (mb, buffer, length);
846   return 0;
847 }
848
849 /* Return a certificate from the Directory Manager's cache.  This
850    function only returns one certificate which must be specified using
851    the fingerprint FPR and will be stored at R_CERT.  On error NULL is
852    stored at R_CERT and an error code returned.  Note that the caller
853    must provide the locked dirmngr context CTX. */
854 static gpg_error_t
855 get_cached_cert (assuan_context_t ctx,
856                  const unsigned char *fpr, ksba_cert_t *r_cert)
857 {
858   gpg_error_t err;
859   char line[ASSUAN_LINELENGTH];
860   char hexfpr[2*20+1];
861   struct membuf mb;
862   char *buf;
863   size_t buflen = 0;
864   ksba_cert_t cert;
865
866   *r_cert = NULL;
867
868   bin2hex (fpr, 20, hexfpr);
869   snprintf (line, DIM(line), "LOOKUP --single --cache-only 0x%s", hexfpr);
870
871   init_membuf (&mb, 4096);
872   err = assuan_transact (ctx, line, get_cached_cert_data_cb, &mb,
873                          NULL, NULL, NULL, NULL);
874   buf = get_membuf (&mb, &buflen);
875   if (err)
876     {
877       xfree (buf);
878       return err;
879     }
880   if (!buf)
881     return gpg_error (GPG_ERR_ENOMEM);
882
883   err = ksba_cert_new (&cert);
884   if (err)
885     {
886       xfree (buf);
887       return err;
888     }
889   err = ksba_cert_init_from_mem (cert, buf, buflen);
890   xfree (buf);
891   if (err)
892     {
893       log_error ("failed to parse a certificate: %s\n", gpg_strerror (err));
894       ksba_cert_release (cert);
895       return err;
896     }
897
898   *r_cert = cert;
899   return 0;
900 }
901
902
903 \f
904 /* Run Command helpers*/
905
906 /* Fairly simple callback to write all output of dirmngr to stdout. */
907 static gpg_error_t
908 run_command_cb (void *opaque, const void *buffer, size_t length)
909 {
910   (void)opaque;
911
912   if (buffer)
913     {
914       if ( fwrite (buffer, length, 1, stdout) != 1 )
915         log_error ("error writing to stdout: %s\n", strerror (errno));
916     }
917   return 0;
918 }
919
920 /* Handle inquiries from the dirmngr COMMAND. */
921 static gpg_error_t
922 run_command_inq_cb (void *opaque, const char *line)
923 {
924   struct run_command_parm_s *parm = opaque;
925   const char *s;
926   int rc = 0;
927
928   if ((s = has_leading_keyword (line, "SENDCERT")))
929     { /* send the given certificate */
930       int err;
931       ksba_cert_t cert;
932       const unsigned char *der;
933       size_t derlen;
934
935       line = s;
936       if (!*line)
937         return gpg_error (GPG_ERR_ASS_PARAMETER);
938
939       err = gpgsm_find_cert (parm->ctrl, line, NULL, &cert);
940       if (err)
941         {
942           log_error ("certificate not found: %s\n", gpg_strerror (err));
943           rc = gpg_error (GPG_ERR_NOT_FOUND);
944         }
945       else
946         {
947           der = ksba_cert_get_image (cert, &derlen);
948           if (!der)
949             rc = gpg_error (GPG_ERR_INV_CERT_OBJ);
950           else
951             rc = assuan_send_data (parm->ctx, der, derlen);
952           ksba_cert_release (cert);
953         }
954     }
955   else if ((s = has_leading_keyword (line, "PRINTINFO")))
956     { /* Simply show the message given in the argument. */
957       line = s;
958       log_info ("dirmngr: %s\n", line);
959     }
960   else
961     {
962       log_error ("unsupported inquiry '%s'\n", line);
963       rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
964     }
965
966   return rc;
967 }
968
969 static gpg_error_t
970 run_command_status_cb (void *opaque, const char *line)
971 {
972   ctrl_t ctrl = opaque;
973   const char *s;
974
975   if (opt.verbose)
976     {
977       log_info ("dirmngr status: %s\n", line);
978     }
979   if ((s = has_leading_keyword (line, "PROGRESS")))
980     {
981       if (ctrl)
982         {
983           line = s;
984           if (gpgsm_status (ctrl, STATUS_PROGRESS, line))
985             return gpg_error (GPG_ERR_ASS_CANCELED);
986         }
987     }
988   return 0;
989 }
990
991
992
993 /* Pass COMMAND to dirmngr and print all output generated by Dirmngr
994    to stdout.  A couple of inquiries are defined (see above).  ARGC
995    arguments in ARGV are given to the Dirmngr.  Spaces, plus and
996    percent characters within the argument strings are percent escaped
997    so that blanks can act as delimiters. */
998 int
999 gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
1000                            int argc, char **argv)
1001 {
1002   int rc;
1003   int i;
1004   const char *s;
1005   char *line, *p;
1006   size_t len;
1007   struct run_command_parm_s parm;
1008
1009   rc = start_dirmngr (ctrl);
1010   if (rc)
1011     return rc;
1012
1013   parm.ctrl = ctrl;
1014   parm.ctx = dirmngr_ctx;
1015
1016   len = strlen (command) + 1;
1017   for (i=0; i < argc; i++)
1018     len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
1019   line = xtrymalloc (len);
1020   if (!line)
1021     {
1022       release_dirmngr (ctrl);
1023       return out_of_core ();
1024     }
1025
1026   p = stpcpy (line, command);
1027   for (i=0; i < argc; i++)
1028     {
1029       *p++ = ' ';
1030       for (s=argv[i]; *s; s++)
1031         {
1032           if (!isascii (*s))
1033             *p++ = *s;
1034           else if (*s == ' ')
1035             *p++ = '+';
1036           else if (!isprint (*s) || *s == '+')
1037             {
1038               sprintf (p, "%%%02X", *(const unsigned char *)s);
1039               p += 3;
1040             }
1041           else
1042             *p++ = *s;
1043         }
1044     }
1045   *p = 0;
1046
1047   rc = assuan_transact (dirmngr_ctx, line,
1048                         run_command_cb, NULL,
1049                         run_command_inq_cb, &parm,
1050                         run_command_status_cb, ctrl);
1051   xfree (line);
1052   log_info ("response of dirmngr: %s\n", rc? gpg_strerror (rc): "okay");
1053   release_dirmngr (ctrl);
1054   return rc;
1055 }