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