Add help strings for all commands.
[gnupg.git] / sm / call-dirmngr.c
blob17d557838fccf12043e594a48329edadd3d1ea0f
1 /* call-dirmngr.c - communication with the dromngr
2 * Copyright (C) 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
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.
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.
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/>.
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>
30 #include "gpgsm.h"
31 #include <gcrypt.h>
32 #include <assuan.h>
34 #include "i18n.h"
35 #include "keydb.h"
38 struct membuf {
39 size_t len;
40 size_t size;
41 char *buf;
42 int out_of_core;
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;
52 static int dirmngr_ctx_locked;
53 static int dirmngr2_ctx_locked;
55 static int force_pipe_server = 0;
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;
64 struct isvalid_status_parm_s {
65 ctrl_t ctrl;
66 int seen;
67 unsigned char fpr[20];
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;
80 struct run_command_parm_s {
81 assuan_context_t ctx;
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. */
91 static void
92 init_membuf (struct membuf *mb, int initiallen)
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;
102 static void
103 put_membuf (struct membuf *mb, const void *buf, size_t len)
105 if (mb->out_of_core)
106 return;
108 if (mb->len + len >= mb->size)
110 char *p;
112 mb->size += len + 1024;
113 p = xtryrealloc (mb->buf, mb->size);
114 if (!p)
116 mb->out_of_core = 1;
117 return;
119 mb->buf = p;
121 memcpy (mb->buf + mb->len, buf, len);
122 mb->len += len;
125 static void *
126 get_membuf (struct membuf *mb, size_t *len)
128 char *p;
130 if (mb->out_of_core)
132 xfree (mb->buf);
133 mb->buf = NULL;
134 return NULL;
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;
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)
151 struct keyserver_spec *server;
153 if (!err)
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. */
160 audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err);
162 if (!ctx || err)
163 return;
165 server = opt.keyserver;
166 while (server)
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 : "";
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;
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. */
181 server = server->next;
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)
192 int rc;
193 char *infostr, *p;
194 assuan_context_t ctx = NULL;
195 int try_default = 0;
197 if (opt.disable_dirmngr)
198 return gpg_error (GPG_ERR_NO_DIRMNGR);
200 if (*ctx_r)
201 return 0;
203 /* Note: if you change this to multiple connections, you also need
204 to take care of the implicit option sending caching. */
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);
217 if (opt.prefer_system_dirmngr && !force_pipe_server && !infostr)
219 infostr = xstrdup (dirmngr_socket_name ());
220 try_default = 1;
223 rc = assuan_new (&ctx);
224 if (rc)
226 log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc));
227 return rc;
230 if (!infostr)
232 const char *pgmname;
233 const char *argv[3];
234 int no_close_list[3];
235 int i;
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++;
244 if (opt.verbose)
245 log_info (_("no running dirmngr - starting `%s'\n"),
246 opt.dirmngr_program);
248 if (fflush (NULL))
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;
255 argv[0] = pgmname;
256 argv[1] = "--server";
257 argv[2] = NULL;
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;
265 /* connect to the agent and perform initial handshaking */
266 rc = assuan_pipe_connect (ctx, opt.dirmngr_program, argv,
267 no_close_list);
269 else
271 int prot;
272 int pid;
274 if (!try_default)
276 if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
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);
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)
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);
297 else
298 pid = -1;
300 rc = assuan_socket_connect (ctx, infostr, pid);
301 #ifdef HAVE_W32_SYSTEM
302 if (rc)
303 log_debug ("connecting dirmngr at `%s' failed\n", infostr);
304 #endif
306 xfree (infostr);
307 #ifndef HAVE_W32_SYSTEM
308 if (gpg_err_code (rc) == GPG_ERR_ASS_CONNECT_FAILED)
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);
314 #endif /*!HAVE_W32_SYSTEM*/
317 prepare_dirmngr (ctrl, ctx, rc);
319 if (rc)
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);
325 *ctx_r = ctx;
327 if (DBG_ASSUAN)
328 log_debug ("connection to dirmngr established\n");
329 return 0;
333 static int
334 start_dirmngr (ctrl_t ctrl)
336 gpg_error_t err;
338 assert (! dirmngr_ctx_locked);
339 dirmngr_ctx_locked = 1;
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;
352 static void
353 release_dirmngr (ctrl_t ctrl)
355 (void)ctrl;
357 if (!dirmngr_ctx_locked)
358 log_error ("WARNING: trying to release a non-locked dirmngr ctx\n");
359 dirmngr_ctx_locked = 0;
363 static int
364 start_dirmngr2 (ctrl_t ctrl)
366 gpg_error_t err;
368 assert (! dirmngr2_ctx_locked);
369 dirmngr2_ctx_locked = 1;
371 err = start_dirmngr_ext (ctrl, &dirmngr2_ctx);
372 if (!dirmngr2_ctx)
373 dirmngr2_ctx_locked = 0;
374 return err;
378 static void
379 release_dirmngr2 (ctrl_t ctrl)
381 (void)ctrl;
383 if (!dirmngr2_ctx_locked)
384 log_error ("WARNING: trying to release a non-locked dirmngr2 ctx\n");
385 dirmngr2_ctx_locked = 0;
390 /* Handle a SENDCERT inquiry. */
391 static gpg_error_t
392 inq_certificate (void *opaque, const char *line)
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;
401 if (!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]))
403 line += 8;
405 else if (!strncmp (line, "SENDCERT_SKI", 12) && (line[12]==' ' || !line[12]))
407 size_t n;
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++;
418 else if (!strncmp (line, "SENDISSUERCERT", 14)
419 && (line[14] == ' ' || !line[14]))
421 line += 14;
422 issuer_mode = 1;
424 else if (!strncmp (line, "ISTRUSTED", 9) && (line[9]==' ' || !line[9]))
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;
433 line += 9;
434 while (*line == ' ')
435 line++;
437 for (s=line,n=0; hexdigitp (s); s++, n++)
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;
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;
451 else
453 log_error ("unsupported inquiry `%s'\n", line);
454 return gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
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);
466 else if (issuer_mode)
468 log_error ("sending specific issuer certificate back "
469 "is not yet implemented\n");
470 rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
472 else
473 { /* Send the given certificate. */
474 int err;
475 ksba_cert_t cert;
478 err = gpgsm_find_cert (line, ski, &cert);
479 if (err)
481 log_error ("certificate not found: %s\n", gpg_strerror (err));
482 rc = gpg_error (GPG_ERR_NOT_FOUND);
484 else
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);
495 xfree (ski);
496 return rc;
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)
505 const char *s;
506 int n;
508 for (s=hexstr, n=0; hexdigitp (s); s++, n++)
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 */
519 static gpg_error_t
520 isvalid_status_cb (void *opaque, const char *line)
522 struct isvalid_status_parm_s *parm = opaque;
524 if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8]))
526 if (parm->ctrl)
528 for (line += 8; *line == ' '; line++)
530 if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
531 return gpg_error (GPG_ERR_ASS_CANCELED);
534 else if (!strncmp (line, "ONLY_VALID_IF_CERT_VALID", 24)
535 && (line[24]==' ' || !line[24]))
537 parm->seen++;
538 if (!line[24] || !unhexify_fpr (line+25, parm->fpr))
539 parm->seen++; /* Bumb it to indicate an error. */
541 return 0;
547 /* Call the directory manager to check whether the certificate is valid
548 Returns 0 for valid or usually one of the errors:
550 GPG_ERR_CERTIFICATE_REVOKED
551 GPG_ERR_NO_CRL_KNOWN
552 GPG_ERR_CRL_TOO_OLD
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.
560 gpgsm_dirmngr_isvalid (ctrl_t ctrl,
561 ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp)
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;
570 rc = start_dirmngr (ctrl);
571 if (rc)
572 return rc;
574 if (use_ocsp)
576 certid = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
578 else
580 certid = gpgsm_get_certid (cert);
581 if (!certid)
583 log_error ("error getting the certificate ID\n");
584 release_dirmngr (ctrl);
585 return gpg_error (GPG_ERR_GENERAL);
589 if (opt.verbose > 1)
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);
597 parm.ctx = dirmngr_ctx;
598 parm.ctrl = ctrl;
599 parm.cert = cert;
600 parm.issuer_cert = issuer_cert;
602 stparm.ctrl = ctrl;
603 stparm.seen = 0;
604 memset (stparm.fpr, 0, 20);
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. */
611 /* It is sufficient to send the options only once because we have
612 one connection per process only. */
613 if (!did_options)
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;
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);
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;
633 if (!rc && stparm.seen)
635 /* Need to also check the certificate validity. */
636 if (stparm.seen != 1)
638 log_error ("communication problem with dirmngr detected\n");
639 rc = gpg_error (GPG_ERR_INV_CRL);
641 else
643 KEYDB_HANDLE kh;
644 ksba_cert_t rspcert = NULL;
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)
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);
661 keydb_release (kh);
663 if (!rc)
665 rc = gpgsm_cert_use_ocsp_p (rspcert);
666 if (rc)
667 rc = gpg_error (GPG_ERR_INV_CRL);
668 else
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)
676 log_error ("invalid certificate used for CRL/OCSP: %s\n",
677 gpg_strerror (rc));
678 rc = gpg_error (GPG_ERR_INV_CRL);
682 ksba_cert_release (rspcert);
685 release_dirmngr (ctrl);
686 return rc;
691 /* Lookup helpers*/
692 static gpg_error_t
693 lookup_cb (void *opaque, const void *buffer, size_t length)
695 struct lookup_parm_s *parm = opaque;
696 size_t len;
697 char *buf;
698 ksba_cert_t cert;
699 int rc;
701 if (parm->error)
702 return 0;
704 if (buffer)
706 put_membuf (&parm->data, buffer, length);
707 return 0;
709 /* END encountered - process what we have */
710 buf = get_membuf (&parm->data, &len);
711 if (!buf)
713 parm->error = gpg_error (GPG_ERR_ENOMEM);
714 return 0;
717 rc = ksba_cert_new (&cert);
718 if (rc)
720 parm->error = rc;
721 return 0;
723 rc = ksba_cert_init_from_mem (cert, buf, len);
724 if (rc)
726 log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
728 else
730 parm->cb (parm->cb_value, cert);
733 ksba_cert_release (cert);
734 init_membuf (&parm->data, 4096);
735 return 0;
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)
743 strlist_t sl;
744 int n;
745 const char *s;
746 char *pattern, *p;
748 for (n=0, sl=names; sl; sl = sl->next)
750 for (s=sl->d; *s; s++, n++)
752 if (*s == '%' || *s == ' ' || *s == '+')
753 n += 2;
755 n++;
758 p = pattern = xtrymalloc (n+1);
759 if (!pattern)
760 return NULL;
762 for (sl=names; sl; sl = sl->next)
764 for (s=sl->d; *s; s++)
766 switch (*s)
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;
788 *p++ = ' ';
790 if (p == pattern)
791 *pattern = 0; /* is empty */
792 else
793 p[-1] = '\0'; /* remove trailing blank */
795 return pattern;
798 static gpg_error_t
799 lookup_status_cb (void *opaque, const char *line)
801 struct lookup_parm_s *parm = opaque;
803 if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8]))
805 if (parm->ctrl)
807 for (line += 8; *line == ' '; line++)
809 if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
810 return gpg_error (GPG_ERR_ASS_CANCELED);
813 else if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9]))
815 if (parm->ctrl)
817 for (line +=9; *line == ' '; line++)
819 gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line);
822 return 0;
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)
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;
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)
846 rc = start_dirmngr (ctrl);
847 if (rc)
848 return rc;
849 ctx = dirmngr_ctx;
851 else if (!dirmngr2_ctx_locked)
853 rc = start_dirmngr2 (ctrl);
854 if (rc)
855 return rc;
856 ctx = dirmngr2_ctx;
858 else
860 log_fatal ("both dirmngr contexts are in use\n");
863 pattern = pattern_from_strlist (names);
864 if (!pattern)
866 if (ctx == dirmngr_ctx)
867 release_dirmngr (ctrl);
868 else
869 release_dirmngr2 (ctrl);
871 return out_of_core ();
873 snprintf (line, DIM(line)-1, "LOOKUP%s %s",
874 cache_only? " --cache-only":"", pattern);
875 line[DIM(line)-1] = 0;
876 xfree (pattern);
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);
885 rc = assuan_transact (ctx, line, lookup_cb, &parm,
886 NULL, NULL, lookup_status_cb, &parm);
887 xfree (get_membuf (&parm.data, &len));
889 if (ctx == dirmngr_ctx)
890 release_dirmngr (ctrl);
891 else
892 release_dirmngr2 (ctrl);
894 if (rc)
895 return rc;
896 return parm.error;
901 /* Run Command helpers*/
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)
907 (void)opaque;
909 if (buffer)
911 if ( fwrite (buffer, length, 1, stdout) != 1 )
912 log_error ("error writing to stdout: %s\n", strerror (errno));
914 return 0;
917 /* Handle inquiries from the dirmngr COMMAND. */
918 static gpg_error_t
919 run_command_inq_cb (void *opaque, const char *line)
921 struct run_command_parm_s *parm = opaque;
922 int rc = 0;
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;
931 line += 8;
932 if (!*line)
933 return gpg_error (GPG_ERR_ASS_PARAMETER);
935 err = gpgsm_find_cert (line, NULL, &cert);
936 if (err)
938 log_error ("certificate not found: %s\n", gpg_strerror (err));
939 rc = gpg_error (GPG_ERR_NOT_FOUND);
941 else
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);
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);
956 else
958 log_error ("unsupported inquiry `%s'\n", line);
959 rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
962 return rc;
965 static gpg_error_t
966 run_command_status_cb (void *opaque, const char *line)
968 ctrl_t ctrl = opaque;
970 if (opt.verbose)
972 log_info ("dirmngr status: %s\n", line);
974 if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8]))
976 if (ctrl)
978 for (line += 8; *line == ' '; line++)
980 if (gpgsm_status (ctrl, STATUS_PROGRESS, line))
981 return gpg_error (GPG_ERR_ASS_CANCELED);
984 return 0;
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. */
995 gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
996 int argc, char **argv)
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;
1005 rc = start_dirmngr (ctrl);
1006 if (rc)
1007 return rc;
1009 parm.ctx = dirmngr_ctx;
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)
1017 release_dirmngr (ctrl);
1018 return out_of_core ();
1021 p = stpcpy (line, command);
1022 for (i=0; i < argc; i++)
1024 *p++ = ' ';
1025 for (s=argv[i]; *s; s++)
1027 if (!isascii (*s))
1028 *p++ = *s;
1029 else if (*s == ' ')
1030 *p++ = '+';
1031 else if (!isprint (*s) || *s == '+')
1033 sprintf (p, "%%%02X", *(const unsigned char *)s);
1034 p += 3;
1036 else
1037 *p++ = *s;
1040 *p = 0;
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;