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 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/>.
47 static assuan_context_t dirmngr_ctx = NULL;
48 static int force_pipe_server = 0;
50 struct inq_certificate_parm_s {
53 ksba_cert_t issuer_cert;
56 struct isvalid_status_parm_s {
59 unsigned char fpr[20];
63 struct lookup_parm_s {
66 void (*cb)(void *, ksba_cert_t);
72 struct run_command_parm_s {
77 /* A simple implementation of a dynamic buffer. Use init_membuf() to
78 create a buffer, put_membuf to append bytes and get_membuf to
79 release and return the buffer. Allocation errors are detected but
80 only returned at the final get_membuf(), this helps not to clutter
81 the code with out of core checks. */
84 init_membuf (struct membuf *mb, int initiallen)
87 mb->size = initiallen;
89 mb->buf = xtrymalloc (initiallen);
95 put_membuf (struct membuf *mb, const void *buf, size_t len)
100 if (mb->len + len >= mb->size)
104 mb->size += len + 1024;
105 p = xtryrealloc (mb->buf, mb->size);
113 memcpy (mb->buf + mb->len, buf, len);
118 get_membuf (struct membuf *mb, size_t *len)
132 mb->out_of_core = 1; /* don't allow a reuse */
140 /* Try to connect to the agent via socket or fork it off and work by
141 pipes. Handle the server's initial greeting */
147 assuan_context_t ctx;
151 return 0; /* fixme: We need a context for each thread or serialize
152 the access to the dirmngr */
153 /* Note: if you change this to multiple connections, you also need
154 to take care of the implicit option sending caching. */
156 #ifdef HAVE_W32_SYSTEM
158 opt.prefer_system_dirmngr = 1;
160 infostr = force_pipe_server? NULL : getenv ("DIRMNGR_INFO");
161 #endif /*HAVE_W32_SYSTEM*/
162 if (infostr && !*infostr)
165 infostr = xstrdup (infostr);
167 if (opt.prefer_system_dirmngr && !force_pipe_server && !infostr)
169 infostr = xstrdup (dirmngr_socket_name ());
176 int no_close_list[3];
179 if (!opt.dirmngr_program || !*opt.dirmngr_program)
180 opt.dirmngr_program = gnupg_module_name (GNUPG_MODULE_NAME_DIRMNGR);
181 if ( !(pgmname = strrchr (opt.dirmngr_program, '/')))
182 pgmname = opt.dirmngr_program;
187 log_info (_("no running dirmngr - starting `%s'\n"),
188 opt.dirmngr_program);
192 gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
193 log_error ("error flushing pending output: %s\n", strerror (errno));
198 argv[1] = "--server";
202 if (log_get_fd () != -1)
203 no_close_list[i++] = log_get_fd ();
204 no_close_list[i++] = fileno (stderr);
205 no_close_list[i] = -1;
207 /* connect to the agent and perform initial handshaking */
208 rc = assuan_pipe_connect (&ctx, opt.dirmngr_program, argv,
218 if ( !(p = strchr (infostr, PATHSEP_C)) || p == infostr)
220 log_error (_("malformed DIRMNGR_INFO environment variable\n"));
222 force_pipe_server = 1;
223 return start_dirmngr ();
227 while (*p && *p != PATHSEP_C)
229 prot = *p? atoi (p+1) : 0;
232 log_error (_("dirmngr protocol version %d is not supported\n"),
235 force_pipe_server = 1;
236 return start_dirmngr ();
242 rc = assuan_socket_connect (&ctx, infostr, pid);
243 #ifdef HAVE_W32_SYSTEM
245 log_debug ("connecting dirmngr at `%s' failed\n", infostr);
249 #ifndef HAVE_W32_SYSTEM
250 if (gpg_err_code (rc) == GPG_ERR_ASS_CONNECT_FAILED)
252 log_error (_("can't connect to the dirmngr - trying fall back\n"));
253 force_pipe_server = 1;
254 return start_dirmngr ();
256 #endif /*!HAVE_W32_SYSTEM*/
261 log_error ("can't connect to the dirmngr: %s\n", gpg_strerror (rc));
262 return gpg_error (GPG_ERR_NO_DIRMNGR);
267 log_debug ("connection to dirmngr established\n");
273 /* Handle a SENDCERT inquiry. */
275 inq_certificate (void *opaque, const char *line)
277 struct inq_certificate_parm_s *parm = opaque;
279 const unsigned char *der;
282 ksba_sexp_t ski = NULL;
284 if (!strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]))
288 else if (!strncmp (line, "SENDCERT_SKI", 12) && (line[12]==' ' || !line[12]))
292 /* Send a certificate where a sourceKeyIdentifier is included. */
296 ski = make_simple_sexp_from_hexstr (line, &n);
301 else if (!strncmp (line, "SENDISSUERCERT", 14)
302 && (line[14] == ' ' || !line[14]))
309 log_error ("unsupported inquiry `%s'\n", line);
310 return gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
314 { /* Send the current certificate. */
315 der = ksba_cert_get_image (issuer_mode? parm->issuer_cert : parm->cert,
318 rc = gpg_error (GPG_ERR_INV_CERT_OBJ);
320 rc = assuan_send_data (parm->ctx, der, derlen);
322 else if (issuer_mode)
324 log_error ("sending specific issuer certificate back "
325 "is not yet implemented\n");
326 rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
329 { /* Send the given certificate. */
334 err = gpgsm_find_cert (line, ski, &cert);
337 log_error ("certificate not found: %s\n", gpg_strerror (err));
338 rc = gpg_error (GPG_ERR_NOT_FOUND);
342 der = ksba_cert_get_image (cert, &derlen);
344 rc = gpg_error (GPG_ERR_INV_CERT_OBJ);
346 rc = assuan_send_data (parm->ctx, der, derlen);
347 ksba_cert_release (cert);
356 /* Take a 20 byte hexencoded string and put it into the the provided
357 20 byte buffer FPR in binary format. */
359 unhexify_fpr (const char *hexstr, unsigned char *fpr)
364 for (s=hexstr, n=0; hexdigitp (s); s++, n++)
367 return 0; /* no fingerprint (invalid or wrong length). */
369 for (s=hexstr, n=0; *s; s += 2, n++)
375 static assuan_error_t
376 isvalid_status_cb (void *opaque, const char *line)
378 struct isvalid_status_parm_s *parm = opaque;
380 if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8]))
384 for (line += 8; *line == ' '; line++)
386 if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
387 return gpg_error (GPG_ERR_ASS_CANCELED);
390 else if (!strncmp (line, "ONLY_VALID_IF_CERT_VALID", 24)
391 && (line[24]==' ' || !line[24]))
394 if (!line[24] || !unhexify_fpr (line+25, parm->fpr))
395 parm->seen++; /* Bumb it to indicate an error. */
403 /* Call the directory manager to check whether the certificate is valid
404 Returns 0 for valid or usually one of the errors:
406 GPG_ERR_CERTIFICATE_REVOKED
412 1 = Do an OCSP check.
413 2 = Do an OCSP check using only the default responder.
416 gpgsm_dirmngr_isvalid (ctrl_t ctrl,
417 ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp)
419 static int did_options;
422 char line[ASSUAN_LINELENGTH];
423 struct inq_certificate_parm_s parm;
424 struct isvalid_status_parm_s stparm;
427 rc = start_dirmngr ();
433 certid = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
437 certid = gpgsm_get_certid (cert);
440 log_error ("error getting the certificate ID\n");
441 return gpg_error (GPG_ERR_GENERAL);
447 char *fpr = gpgsm_get_fingerprint_string (cert, GCRY_MD_SHA1);
448 log_info ("asking dirmngr about %s%s\n", fpr,
449 use_ocsp? " (using OCSP)":"");
453 parm.ctx = dirmngr_ctx;
455 parm.issuer_cert = issuer_cert;
459 memset (stparm.fpr, 0, 20);
461 /* FIXME: If --disable-crl-checks has been set, we should pass an
462 option to dirmngr, so that no fallback CRL check is done after an
463 ocsp check. It is not a problem right now as dirmngr does not
464 fallback to CRL checking. */
466 /* It is sufficient to send the options only once because we have
467 one connection per process only. */
470 if (opt.force_crl_refresh)
471 assuan_transact (dirmngr_ctx, "OPTION force-crl-refresh=1",
472 NULL, NULL, NULL, NULL, NULL, NULL);
475 snprintf (line, DIM(line)-1, "ISVALID%s %s",
476 use_ocsp == 2? " --only-ocsp --force-default-responder":"",
478 line[DIM(line)-1] = 0;
481 rc = assuan_transact (dirmngr_ctx, line, NULL, NULL,
482 inq_certificate, &parm,
483 isvalid_status_cb, &stparm);
485 log_info ("response of dirmngr: %s\n", rc? gpg_strerror (rc): "okay");
488 if (!rc && stparm.seen)
490 /* Need to also check the certificate validity. */
491 if (stparm.seen != 1)
493 log_error ("communication problem with dirmngr detected\n");
494 rc = gpg_error (GPG_ERR_INV_CRL);
499 ksba_cert_t rspcert = NULL;
501 /* Fixme: First try to get the certificate from the
502 dirmngr's cache - it should be there. */
505 rc = gpg_error (GPG_ERR_ENOMEM);
507 rc = keydb_search_fpr (kh, stparm.fpr);
509 rc = keydb_get_cert (kh, &rspcert);
512 log_error ("unable to find the certificate used "
513 "by the dirmngr: %s\n", gpg_strerror (rc));
514 rc = gpg_error (GPG_ERR_INV_CRL);
520 rc = gpgsm_cert_use_ocsp_p (rspcert);
522 rc = gpg_error (GPG_ERR_INV_CRL);
525 /* Note the no_dirmngr flag: This avoids checking
526 this certificate over and over again. */
527 rc = gpgsm_validate_chain (ctrl, rspcert, "", NULL, 0, NULL,
528 VALIDATE_FLAG_NO_DIRMNGR, NULL);
531 log_error ("invalid certificate used for CRL/OCSP: %s\n",
533 rc = gpg_error (GPG_ERR_INV_CRL);
537 ksba_cert_release (rspcert);
547 lookup_cb (void *opaque, const void *buffer, size_t length)
549 struct lookup_parm_s *parm = opaque;
560 put_membuf (&parm->data, buffer, length);
563 /* END encountered - process what we have */
564 buf = get_membuf (&parm->data, &len);
567 parm->error = gpg_error (GPG_ERR_ENOMEM);
571 rc = ksba_cert_new (&cert);
577 rc = ksba_cert_init_from_mem (cert, buf, len);
580 log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc));
584 parm->cb (parm->cb_value, cert);
587 ksba_cert_release (cert);
588 init_membuf (&parm->data, 4096);
592 /* Return a properly escaped pattern from NAMES. The only error
593 return is NULL to indicate a malloc failure. */
595 pattern_from_strlist (strlist_t names)
602 for (n=0, sl=names; sl; sl = sl->next)
604 for (s=sl->d; *s; s++, n++)
606 if (*s == '%' || *s == ' ' || *s == '+')
612 p = pattern = xtrymalloc (n+1);
616 for (n=0, sl=names; sl; sl = sl->next)
618 for (s=sl->d; *s; s++)
645 *pattern = 0; /* is empty */
647 p[-1] = '\0'; /* remove trailing blank */
653 lookup_status_cb (void *opaque, const char *line)
655 struct lookup_parm_s *parm = opaque;
657 if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8]))
661 for (line += 8; *line == ' '; line++)
663 if (gpgsm_status (parm->ctrl, STATUS_PROGRESS, line))
664 return gpg_error (GPG_ERR_ASS_CANCELED);
667 else if (!strncmp (line, "TRUNCATED", 9) && (line[9]==' ' || !line[9]))
671 for (line +=9; *line == ' '; line++)
673 gpgsm_status (parm->ctrl, STATUS_TRUNCATED, line);
680 /* Run the Directroy Managers lookup command using the pattern
681 compiled from the strings given in NAMES. The caller must provide
682 the callback CB which will be passed cert by cert. Note that CTRL
685 gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names,
686 void (*cb)(void*, ksba_cert_t), void *cb_value)
690 char line[ASSUAN_LINELENGTH];
691 struct lookup_parm_s parm;
694 rc = start_dirmngr ();
698 pattern = pattern_from_strlist (names);
700 return out_of_core ();
701 snprintf (line, DIM(line)-1, "LOOKUP %s", pattern);
702 line[DIM(line)-1] = 0;
706 parm.ctx = dirmngr_ctx;
708 parm.cb_value = cb_value;
710 init_membuf (&parm.data, 4096);
712 rc = assuan_transact (dirmngr_ctx, line, lookup_cb, &parm,
713 NULL, NULL, lookup_status_cb, &parm);
714 xfree (get_membuf (&parm.data, &len));
722 /* Run Command helpers*/
724 /* Fairly simple callback to write all output of dirmngr to stdout. */
726 run_command_cb (void *opaque, const void *buffer, size_t length)
730 if ( fwrite (buffer, length, 1, stdout) != 1 )
731 log_error ("error writing to stdout: %s\n", strerror (errno));
736 /* Handle inquiries from the dirmngr COMMAND. */
738 run_command_inq_cb (void *opaque, const char *line)
740 struct run_command_parm_s *parm = opaque;
743 if ( !strncmp (line, "SENDCERT", 8) && (line[8] == ' ' || !line[8]) )
744 { /* send the given certificate */
747 const unsigned char *der;
752 return gpg_error (GPG_ERR_ASS_PARAMETER);
754 err = gpgsm_find_cert (line, NULL, &cert);
757 log_error ("certificate not found: %s\n", gpg_strerror (err));
758 rc = gpg_error (GPG_ERR_NOT_FOUND);
762 der = ksba_cert_get_image (cert, &derlen);
764 rc = gpg_error (GPG_ERR_INV_CERT_OBJ);
766 rc = assuan_send_data (parm->ctx, der, derlen);
767 ksba_cert_release (cert);
770 else if ( !strncmp (line, "PRINTINFO", 9) && (line[9] == ' ' || !line[9]) )
771 { /* Simply show the message given in the argument. */
773 log_info ("dirmngr: %s\n", line);
777 log_error ("unsupported inquiry `%s'\n", line);
778 rc = gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE);
785 run_command_status_cb (void *opaque, const char *line)
787 ctrl_t ctrl = opaque;
791 log_info ("dirmngr status: %s\n", line);
793 if (!strncmp (line, "PROGRESS", 8) && (line[8]==' ' || !line[8]))
797 for (line += 8; *line == ' '; line++)
799 if (gpgsm_status (ctrl, STATUS_PROGRESS, line))
800 return gpg_error (GPG_ERR_ASS_CANCELED);
808 /* Pass COMMAND to dirmngr and print all output generated by Dirmngr
809 to stdout. A couple of inquiries are defined (see above). ARGC
810 arguments in ARGV are given to the Dirmngr. Spaces, plus and
811 percent characters within the argument strings are percent escaped
812 so that blanks can act as delimiters. */
814 gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
815 int argc, char **argv)
822 struct run_command_parm_s parm;
824 rc = start_dirmngr ();
828 parm.ctx = dirmngr_ctx;
830 len = strlen (command) + 1;
831 for (i=0; i < argc; i++)
832 len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
833 line = xtrymalloc (len);
835 return out_of_core ();
837 p = stpcpy (line, command);
838 for (i=0; i < argc; i++)
841 for (s=argv[i]; *s; s++)
847 else if (!isprint (*s) || *s == '+')
849 sprintf (p, "%%%02X", *(const unsigned char *)s);
858 rc = assuan_transact (dirmngr_ctx, line,
859 run_command_cb, NULL,
860 run_command_inq_cb, &parm,
861 run_command_status_cb, ctrl);
863 log_info ("response of dirmngr: %s\n", rc? gpg_strerror (rc): "okay");