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