2006-12-21 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / sm / call-dirmngr.c
blob5cc34e1321157ca6c7fd4707c71cb3bc655b40a2
1 /* call-dirmngr.c - communication with the dromngr
2 * Copyright (C) 2002, 2003, 2005 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 2 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, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19 * USA.
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <time.h>
29 #include <assert.h>
30 #include <ctype.h>
32 #include "gpgsm.h"
33 #include <gcrypt.h>
34 #include <assuan.h>
36 #include "i18n.h"
37 #include "keydb.h"
39 /* The name of the socket for a system daemon. */
40 #define DEFAULT_SOCKET_NAME "/var/run/dirmngr/socket"
42 struct membuf {
43 size_t len;
44 size_t size;
45 char *buf;
46 int out_of_core;
51 static assuan_context_t dirmngr_ctx = NULL;
52 static int force_pipe_server = 0;
54 struct inq_certificate_parm_s {
55 assuan_context_t ctx;
56 ksba_cert_t cert;
57 ksba_cert_t issuer_cert;
60 struct isvalid_status_parm_s {
61 ctrl_t ctrl;
62 int seen;
63 unsigned char fpr[20];
67 struct lookup_parm_s {
68 ctrl_t ctrl;
69 assuan_context_t ctx;
70 void (*cb)(void *, ksba_cert_t);
71 void *cb_value;
72 struct membuf data;
73 int error;
76 struct run_command_parm_s {
77 assuan_context_t ctx;
81 /* A simple implementation of a dynamic buffer. Use init_membuf() to
82 create a buffer, put_membuf to append bytes and get_membuf to
83 release and return the buffer. Allocation errors are detected but
84 only returned at the final get_membuf(), this helps not to clutter
85 the code with out of core checks. */
87 static void
88 init_membuf (struct membuf *mb, int initiallen)
90 mb->len = 0;
91 mb->size = initiallen;
92 mb->out_of_core = 0;
93 mb->buf = xtrymalloc (initiallen);
94 if (!mb->buf)
95 mb->out_of_core = 1;
98 static void
99 put_membuf (struct membuf *mb, const void *buf, size_t len)
101 if (mb->out_of_core)
102 return;
104 if (mb->len + len >= mb->size)
106 char *p;
108 mb->size += len + 1024;
109 p = xtryrealloc (mb->buf, mb->size);
110 if (!p)
112 mb->out_of_core = 1;
113 return;
115 mb->buf = p;
117 memcpy (mb->buf + mb->len, buf, len);
118 mb->len += len;
121 static void *
122 get_membuf (struct membuf *mb, size_t *len)
124 char *p;
126 if (mb->out_of_core)
128 xfree (mb->buf);
129 mb->buf = NULL;
130 return NULL;
133 p = mb->buf;
134 *len = mb->len;
135 mb->buf = NULL;
136 mb->out_of_core = 1; /* don't allow a reuse */
137 return p;
144 /* Try to connect to the agent via socket or fork it off and work by
145 pipes. Handle the server's initial greeting */
146 static int
147 start_dirmngr (void)
149 int rc;
150 char *infostr, *p;
151 assuan_context_t ctx;
152 int try_default = 0;
154 if (dirmngr_ctx)
155 return 0; /* fixme: We need a context for each thread or serialize
156 the access to the dirmngr */
157 /* Note: if you change this to multiple connections, you also need
158 to take care of the implicit option sending caching. */
160 infostr = force_pipe_server? NULL : getenv ("DIRMNGR_INFO");
161 if (opt.prefer_system_dirmngr && !force_pipe_server
162 &&(!infostr || !*infostr))
164 infostr = DEFAULT_SOCKET_NAME;
165 try_default = 1;
167 if (!infostr || !*infostr)
169 const char *pgmname;
170 const char *argv[3];
171 int no_close_list[3];
172 int i;
174 if (!opt.dirmngr_program || !*opt.dirmngr_program)
175 opt.dirmngr_program = GNUPG_DEFAULT_DIRMNGR;
176 if ( !(pgmname = strrchr (opt.dirmngr_program, '/')))
177 pgmname = opt.dirmngr_program;
178 else
179 pgmname++;
181 if (opt.verbose)
182 log_info (_("no running dirmngr - starting `%s'\n"),
183 opt.dirmngr_program);
185 if (fflush (NULL))
187 gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
188 log_error ("error flushing pending output: %s\n", strerror (errno));
189 return tmperr;
192 argv[0] = pgmname;
193 argv[1] = "--server";
194 argv[2] = NULL;
196 i=0;
197 if (log_get_fd () != -1)
198 no_close_list[i++] = log_get_fd ();
199 no_close_list[i++] = fileno (stderr);
200 no_close_list[i] = -1;
202 /* connect to the agent and perform initial handshaking */
203 rc = assuan_pipe_connect (&ctx, opt.dirmngr_program, argv,
204 no_close_list);
206 else
208 int prot;
209 int pid;
211 infostr = xstrdup (infostr);
212 if (!try_default && *infostr)
214 if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
216 log_error (_("malformed DIRMNGR_INFO environment variable\n"));
217 xfree (infostr);
218 force_pipe_server = 1;
219 return start_dirmngr ();
221 *p++ = 0;
222 pid = atoi (p);
223 while (*p && *p != PATHSEP_C)
224 p++;
225 prot = *p? atoi (p+1) : 0;
226 if (prot != 1)
228 log_error (_("dirmngr protocol version %d is not supported\n"),
229 prot);
230 xfree (infostr);
231 force_pipe_server = 1;
232 return start_dirmngr ();
235 else
236 pid = -1;
238 rc = assuan_socket_connect (&ctx, infostr, pid);
239 xfree (infostr);
240 if (gpg_err_code (rc) == GPG_ERR_ASS_CONNECT_FAILED)
242 log_error (_("can't connect to the dirmngr - trying fall back\n"));
243 force_pipe_server = 1;
244 return start_dirmngr ();
248 if (rc)
250 log_error ("can't connect to the dirmngr: %s\n", gpg_strerror (rc));
251 return gpg_error (GPG_ERR_NO_DIRMNGR);
253 dirmngr_ctx = ctx;
255 if (DBG_ASSUAN)
256 log_debug ("connection to dirmngr established\n");
257 return 0;
262 /* Handle a SENDCERT inquiry. */
263 static int
264 inq_certificate (void *opaque, const char *line)
266 struct inq_certificate_parm_s *parm = opaque;
267 int rc;
268 const unsigned char *der;
269 size_t derlen;
270 int issuer_mode = 0;
271 ksba_sexp_t ski = NULL;
273 if (!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]))
275 line += 8;
277 else if (!strncmp (line, "SENDCERT_SKI", 12) && (line[12]==' ' || !line[12]))
279 size_t n;
281 /* Send a certificate where a sourceKeyIdentifier is included. */
282 line += 12;
283 while (*line == ' ')
284 line++;
285 ski = make_simple_sexp_from_hexstr (line, &n);
286 line += n;
287 while (*line == ' ')
288 line++;
290 else if (!strncmp (line, "SENDISSUERCERT", 14)
291 && (line[14] == ' ' || !line[14]))
293 line += 14;
294 issuer_mode = 1;
296 else
298 log_error ("unsupported inquiry `%s'\n", line);
299 return gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
302 if (!*line)
303 { /* Send the current certificate. */
304 der = ksba_cert_get_image (issuer_mode? parm->issuer_cert : parm->cert,
305 &derlen);
306 if (!der)
307 rc = gpg_error (GPG_ERR_INV_CERT_OBJ);
308 else
309 rc = assuan_send_data (parm->ctx, der, derlen);
311 else if (issuer_mode)
313 log_error ("sending specific issuer certificate back "
314 "is not yet implemented\n");
315 rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
317 else
318 { /* Send the given certificate. */
319 int err;
320 ksba_cert_t cert;
323 err = gpgsm_find_cert (line, ski, &cert);
324 if (err)
326 log_error ("certificate not found: %s\n", gpg_strerror (err));
327 rc = gpg_error (GPG_ERR_NOT_FOUND);
329 else
331 der = ksba_cert_get_image (cert, &derlen);
332 if (!der)
333 rc = gpg_error (GPG_ERR_INV_CERT_OBJ);
334 else
335 rc = assuan_send_data (parm->ctx, der, derlen);
336 ksba_cert_release (cert);
340 xfree (ski);
341 return rc;
345 /* Take a 20 byte hexencoded string and put it into the the provided
346 20 byte buffer FPR in binary format. */
347 static int
348 unhexify_fpr (const char *hexstr, unsigned char *fpr)
350 const char *s;
351 int n;
353 for (s=hexstr, n=0; hexdigitp (s); s++, n++)
355 if (*s || (n != 40))
356 return 0; /* no fingerprint (invalid or wrong length). */
357 n /= 2;
358 for (s=hexstr, n=0; *s; s += 2, n++)
359 fpr[n] = xtoi_2 (s);
360 return 1; /* okay */
364 static assuan_error_t
365 isvalid_status_cb (void *opaque, const char *line)
367 struct isvalid_status_parm_s *parm = opaque;
369 if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8]))
371 if (parm->ctrl)
373 for (line += 8; *line == ' '; line++)
375 if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
376 return gpg_error (GPG_ERR_ASS_CANCELED);
379 else if (!strncmp (line, "ONLY_VALID_IF_CERT_VALID", 24)
380 && (line[24]==' ' || !line[24]))
382 parm->seen++;
383 if (!line[24] || !unhexify_fpr (line+25, parm->fpr))
384 parm->seen++; /* Bumb it to indicate an error. */
386 return 0;
392 /* Call the directory manager to check whether the certificate is valid
393 Returns 0 for valid or usually one of the errors:
395 GPG_ERR_CERTIFICATE_REVOKED
396 GPG_ERR_NO_CRL_KNOWN
397 GPG_ERR_CRL_TOO_OLD
399 With USE_OCSP set to true, the dirmngr is asked to do an OCSP
400 request first.
403 gpgsm_dirmngr_isvalid (ctrl_t ctrl,
404 ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp)
406 static int did_options;
407 int rc;
408 char *certid;
409 char line[ASSUAN_LINELENGTH];
410 struct inq_certificate_parm_s parm;
411 struct isvalid_status_parm_s stparm;
414 rc = start_dirmngr ();
415 if (rc)
416 return rc;
418 if (use_ocsp)
420 certid = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
422 else
424 certid = gpgsm_get_certid (cert);
425 if (!certid)
427 log_error ("error getting the certificate ID\n");
428 return gpg_error (GPG_ERR_GENERAL);
432 if (opt.verbose > 1)
434 char *fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1);
435 log_info ("asking dirmngr about %s%s\n", fpr,
436 use_ocsp? " (using OCSP)":"");
437 xfree (fpr);
440 parm.ctx = dirmngr_ctx;
441 parm.cert = cert;
442 parm.issuer_cert = issuer_cert;
444 stparm.ctrl = ctrl;
445 stparm.seen = 0;
446 memset (stparm.fpr, 0, 20);
448 /* FIXME: If --disable-crl-checks has been set, we should pass an
449 option to dirmngr, so that no fallback CRL check is done after an
450 ocsp check. */
452 /* It is sufficient to send the options only once because we have
453 one connection per process only. */
454 if (!did_options)
456 if (opt.force_crl_refresh)
457 assuan_transact (dirmngr_ctx, "OPTION force-crl-refresh=1",
458 NULL, NULL, NULL, NULL, NULL, NULL);
459 did_options = 1;
461 snprintf (line, DIM(line)-1, "ISVALID %s", certid);
462 line[DIM(line)-1] = 0;
463 xfree (certid);
465 rc = assuan_transact (dirmngr_ctx, line, NULL, NULL,
466 inq_certificate, &parm,
467 isvalid_status_cb, &stparm);
468 if (opt.verbose > 1)
469 log_info ("response of dirmngr: %s\n", rc? gpg_strerror (rc): "okay");
470 rc = rc;
472 if (!rc && stparm.seen)
474 /* Need to also check the certificate validity. */
475 if (stparm.seen != 1)
477 log_error ("communication problem with dirmngr detected\n");
478 rc = gpg_error (GPG_ERR_INV_CRL);
480 else
482 KEYDB_HANDLE kh;
483 ksba_cert_t rspcert = NULL;
485 /* Fixme: First try to get the certificate from the
486 dirmngr's cache - it should be there. */
487 kh = keydb_new (0);
488 if (!kh)
489 rc = gpg_error (GPG_ERR_ENOMEM);
490 if (!rc)
491 rc = keydb_search_fpr (kh, stparm.fpr);
492 if (!rc)
493 rc = keydb_get_cert (kh, &rspcert);
494 if (rc)
496 log_error ("unable to find the certificate used "
497 "by the dirmngr: %s\n", gpg_strerror (rc));
498 rc = gpg_error (GPG_ERR_INV_CRL);
500 keydb_release (kh);
502 if (!rc)
504 rc = gpgsm_cert_use_ocsp_p (rspcert);
505 if (rc)
506 rc = gpg_error (GPG_ERR_INV_CRL);
507 else
509 /* Note, the flag = 1: This avoids checking this
510 certificate over and over again. */
511 rc = gpgsm_validate_chain (ctrl, rspcert, NULL, 0, NULL, 1);
512 if (rc)
514 log_error ("invalid certificate used for CRL/OCSP: %s\n",
515 gpg_strerror (rc));
516 rc = gpg_error (GPG_ERR_INV_CRL);
520 ksba_cert_release (rspcert);
523 return rc;
528 /* Lookup helpers*/
529 static int
530 lookup_cb (void *opaque, const void *buffer, size_t length)
532 struct lookup_parm_s *parm = opaque;
533 size_t len;
534 char *buf;
535 ksba_cert_t cert;
536 int rc;
538 if (parm->error)
539 return 0;
541 if (buffer)
543 put_membuf (&parm->data, buffer, length);
544 return 0;
546 /* END encountered - process what we have */
547 buf = get_membuf (&parm->data, &len);
548 if (!buf)
550 parm->error = gpg_error (GPG_ERR_ENOMEM);
551 return 0;
554 rc = ksba_cert_new (&cert);
555 if (rc)
557 parm->error = rc;
558 return 0;
560 rc = ksba_cert_init_from_mem (cert, buf, len);
561 if (rc)
563 log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
565 else
567 parm->cb (parm->cb_value, cert);
570 ksba_cert_release (cert);
571 init_membuf (&parm->data, 4096);
572 return 0;
575 /* Return a properly escaped pattern from NAMES. The only error
576 return is NULL to indicate a malloc failure. */
577 static char *
578 pattern_from_strlist (strlist_t names)
580 strlist_t sl;
581 int n;
582 const char *s;
583 char *pattern, *p;
585 for (n=0, sl=names; sl; sl = sl->next)
587 for (s=sl->d; *s; s++, n++)
589 if (*s == '%' || *s == ' ' || *s == '+')
590 n += 2;
592 n++;
595 p = pattern = xtrymalloc (n+1);
596 if (!pattern)
597 return NULL;
599 for (n=0, sl=names; sl; sl = sl->next)
601 for (s=sl->d; *s; s++)
603 switch (*s)
605 case '%':
606 *p++ = '%';
607 *p++ = '2';
608 *p++ = '5';
609 break;
610 case ' ':
611 *p++ = '%';
612 *p++ = '2';
613 *p++ = '0';
614 break;
615 case '+':
616 *p++ = '%';
617 *p++ = '2';
618 *p++ = 'B';
619 break;
620 default:
621 *p++ = *s;
622 break;
625 *p++ = ' ';
627 if (p == pattern)
628 *pattern = 0; /* is empty */
629 else
630 p[-1] = '\0'; /* remove trailing blank */
632 return pattern;
635 static int
636 lookup_status_cb (void *opaque, const char *line)
638 struct lookup_parm_s *parm = opaque;
640 if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8]))
642 if (parm->ctrl)
644 for (line += 8; *line == ' '; line++)
646 if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
647 return gpg_error (GPG_ERR_ASS_CANCELED);
650 else if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9]))
652 if (parm->ctrl)
654 for (line +=9; *line == ' '; line++)
656 gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line);
659 return 0;
663 /* Run the Directroy Managers lookup command using the pattern
664 compiled from the strings given in NAMES. The caller must provide
665 the callback CB which will be passed cert by cert. Note that CTRL
666 is optional. */
667 int
668 gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names,
669 void (*cb)(void*, ksba_cert_t), void *cb_value)
671 int rc;
672 char *pattern;
673 char line[ASSUAN_LINELENGTH];
674 struct lookup_parm_s parm;
675 size_t len;
677 rc = start_dirmngr ();
678 if (rc)
679 return rc;
681 pattern = pattern_from_strlist (names);
682 if (!pattern)
683 return out_of_core ();
684 snprintf (line, DIM(line)-1, "LOOKUP %s", pattern);
685 line[DIM(line)-1] = 0;
686 xfree (pattern);
688 parm.ctrl = ctrl;
689 parm.ctx = dirmngr_ctx;
690 parm.cb = cb;
691 parm.cb_value = cb_value;
692 parm.error = 0;
693 init_membuf (&parm.data, 4096);
695 rc = assuan_transact (dirmngr_ctx, line, lookup_cb, &parm,
696 NULL, NULL, lookup_status_cb, &parm);
697 xfree (get_membuf (&parm.data, &len));
698 if (rc)
699 return rc;
700 return parm.error;
705 /* Run Command helpers*/
707 /* Fairly simple callback to write all output of dirmngr to stdout. */
708 static int
709 run_command_cb (void *opaque, const void *buffer, size_t length)
711 if (buffer)
713 if ( fwrite (buffer, length, 1, stdout) != 1 )
714 log_error ("error writing to stdout: %s\n", strerror (errno));
716 return 0;
719 /* Handle inquiries from the dirmngr COMMAND. */
720 static int
721 run_command_inq_cb (void *opaque, const char *line)
723 struct run_command_parm_s *parm = opaque;
724 int rc = 0;
726 if ( !strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]) )
727 { /* send the given certificate */
728 int err;
729 ksba_cert_t cert;
730 const unsigned char *der;
731 size_t derlen;
733 line += 8;
734 if (!*line)
735 return gpg_error (GPG_ERR_ASS_PARAMETER);
737 err = gpgsm_find_cert (line, NULL, &cert);
738 if (err)
740 log_error ("certificate not found: %s\n", gpg_strerror (err));
741 rc = gpg_error (GPG_ERR_NOT_FOUND);
743 else
745 der = ksba_cert_get_image (cert, &derlen);
746 if (!der)
747 rc = gpg_error (GPG_ERR_INV_CERT_OBJ);
748 else
749 rc = assuan_send_data (parm->ctx, der, derlen);
750 ksba_cert_release (cert);
753 else if ( !strncmp (line, "PRINTINFO", 9) && (line[9] == ' ' || !line[9]) )
754 { /* Simply show the message given in the argument. */
755 line += 9;
756 log_info ("dirmngr: %s\n", line);
758 else
760 log_error ("unsupported inquiry `%s'\n", line);
761 rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
764 return rc;
767 static int
768 run_command_status_cb (void *opaque, const char *line)
770 ctrl_t ctrl = opaque;
772 if (opt.verbose)
774 log_info ("dirmngr status: %s\n", line);
776 if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8]))
778 if (ctrl)
780 for (line += 8; *line == ' '; line++)
782 if (gpgsm_status (ctrl, STATUS_PROGRESS, line))
783 return gpg_error (GPG_ERR_ASS_CANCELED);
786 return 0;
791 /* Pass COMMAND to dirmngr and print all output generated by Dirmngr
792 to stdout. A couple of inquiries are defined (see above). ARGC
793 arguments in ARGV are given to the Dirmngr. Spaces, plus and
794 percent characters within the argument strings are percent escaped
795 so that blanks can act as delimiters. */
797 gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
798 int argc, char **argv)
800 int rc;
801 int i;
802 const char *s;
803 char *line, *p;
804 size_t len;
805 struct run_command_parm_s parm;
807 rc = start_dirmngr ();
808 if (rc)
809 return rc;
811 parm.ctx = dirmngr_ctx;
813 len = strlen (command) + 1;
814 for (i=0; i < argc; i++)
815 len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
816 line = xtrymalloc (len);
817 if (!line)
818 return out_of_core ();
820 p = stpcpy (line, command);
821 for (i=0; i < argc; i++)
823 *p++ = ' ';
824 for (s=argv[i]; *s; s++)
826 if (!isascii (*s))
827 *p++ = *s;
828 else if (*s == ' ')
829 *p++ = '+';
830 else if (!isprint (*s) || *s == '+')
832 sprintf (p, "%%%02X", *(const unsigned char *)s);
833 p += 3;
835 else
836 *p++ = *s;
839 *p = 0;
841 rc = assuan_transact (dirmngr_ctx, line,
842 run_command_cb, NULL,
843 run_command_inq_cb, &parm,
844 run_command_status_cb, ctrl);
845 xfree (line);
846 log_info ("response of dirmngr: %s\n", rc? gpg_strerror (rc): "okay");
847 return rc;