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/>.
47 /* fixme: We need a context for each thread or serialize the access to
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
{
61 ksba_cert_t issuer_cert
;
64 struct isvalid_status_parm_s
{
67 unsigned char fpr
[20];
71 struct lookup_parm_s
{
74 void (*cb
)(void *, ksba_cert_t
);
80 struct run_command_parm_s
{
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. */
92 init_membuf (struct membuf
*mb
, int initiallen
)
95 mb
->size
= initiallen
;
97 mb
->buf
= xtrymalloc (initiallen
);
103 put_membuf (struct membuf
*mb
, const void *buf
, size_t len
)
108 if (mb
->len
+ len
>= mb
->size
)
112 mb
->size
+= len
+ 1024;
113 p
= xtryrealloc (mb
->buf
, mb
->size
);
121 memcpy (mb
->buf
+ mb
->len
, buf
, len
);
126 get_membuf (struct membuf
*mb
, size_t *len
)
140 mb
->out_of_core
= 1; /* don't allow a reuse */
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. */
149 prepare_dirmngr (ctrl_t ctrl
, assuan_context_t ctx
, gpg_error_t err
)
151 struct keyserver_spec
*server
;
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
);
165 server
= opt
.keyserver
;
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 */
190 start_dirmngr_ext (ctrl_t ctrl
, assuan_context_t
*ctx_r
)
194 assuan_context_t ctx
= NULL
;
197 if (opt
.disable_dirmngr
)
198 return gpg_error (GPG_ERR_NO_DIRMNGR
);
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
208 opt
.prefer_system_dirmngr
= 1;
210 infostr
= force_pipe_server
? NULL
: getenv ("DIRMNGR_INFO");
211 #endif /*HAVE_W32_SYSTEM*/
212 if (infostr
&& !*infostr
)
215 infostr
= xstrdup (infostr
);
217 if (opt
.prefer_system_dirmngr
&& !force_pipe_server
&& !infostr
)
219 infostr
= xstrdup (dirmngr_socket_name ());
223 rc
= assuan_new (&ctx
);
226 log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc
));
234 int no_close_list
[3];
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
;
245 log_info (_("no running dirmngr - starting `%s'\n"),
246 opt
.dirmngr_program
);
250 gpg_error_t tmperr
= gpg_error (gpg_err_code_from_errno (errno
));
251 log_error ("error flushing pending output: %s\n", strerror (errno
));
256 argv
[1] = "--server";
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
,
276 if ( !(p
= strchr (infostr
, PATHSEP_C
)) || p
== infostr
)
278 log_error (_("malformed DIRMNGR_INFO environment variable\n"));
280 force_pipe_server
= 1;
281 return start_dirmngr_ext (ctrl
, ctx_r
);
285 while (*p
&& *p
!= PATHSEP_C
)
287 prot
= *p
? atoi (p
+1) : 0;
290 log_error (_("dirmngr protocol version %d is not supported\n"),
293 force_pipe_server
= 1;
294 return start_dirmngr_ext (ctrl
, ctx_r
);
300 rc
= assuan_socket_connect (ctx
, infostr
, pid
);
301 #ifdef HAVE_W32_SYSTEM
303 log_debug ("connecting dirmngr at `%s' failed\n", 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
);
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
);
328 log_debug ("connection to dirmngr established\n");
334 start_dirmngr (ctrl_t ctrl
)
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? */
347 dirmngr_ctx_locked
= 0;
353 release_dirmngr (ctrl_t ctrl
)
357 if (!dirmngr_ctx_locked
)
358 log_error ("WARNING: trying to release a non-locked dirmngr ctx\n");
359 dirmngr_ctx_locked
= 0;
364 start_dirmngr2 (ctrl_t ctrl
)
368 assert (! dirmngr2_ctx_locked
);
369 dirmngr2_ctx_locked
= 1;
371 err
= start_dirmngr_ext (ctrl
, &dirmngr2_ctx
);
373 dirmngr2_ctx_locked
= 0;
379 release_dirmngr2 (ctrl_t 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. */
392 inq_certificate (void *opaque
, const char *line
)
394 struct inq_certificate_parm_s
*parm
= opaque
;
396 const unsigned char *der
;
399 ksba_sexp_t ski
= NULL
;
401 if (!strncmp (line
, "SENDCERT", 8) && (line
[8] == ' ' || !line
[8]))
405 else if (!strncmp (line
, "SENDCERT_SKI", 12) && (line
[12]==' ' || !line
[12]))
409 /* Send a certificate where a sourceKeyIdentifier is included. */
413 ski
= make_simple_sexp_from_hexstr (line
, &n
);
418 else if (!strncmp (line
, "SENDISSUERCERT", 14)
419 && (line
[14] == ' ' || !line
[14]))
424 else if (!strncmp (line
, "ISTRUSTED", 9) && (line
[9]==' ' || !line
[9]))
426 /* The server is asking us whether the certificate is a trusted
431 struct rootca_flags_s rootca_flags
;
437 for (s
=line
,n
=0; hexdigitp (s
); s
++, n
++)
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
;
445 if (!gpgsm_agent_istrusted (parm
->ctrl
, NULL
, fpr
, &rootca_flags
))
446 rc
= assuan_send_data (parm
->ctx
, "1", 1);
453 log_error ("unsupported inquiry `%s'\n", line
);
454 return gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE
);
458 { /* Send the current certificate. */
459 der
= ksba_cert_get_image (issuer_mode
? parm
->issuer_cert
: parm
->cert
,
462 rc
= gpg_error (GPG_ERR_INV_CERT_OBJ
);
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
);
473 { /* Send the given certificate. */
478 err
= gpgsm_find_cert (line
, ski
, &cert
);
481 log_error ("certificate not found: %s\n", gpg_strerror (err
));
482 rc
= gpg_error (GPG_ERR_NOT_FOUND
);
486 der
= ksba_cert_get_image (cert
, &derlen
);
488 rc
= gpg_error (GPG_ERR_INV_CERT_OBJ
);
490 rc
= assuan_send_data (parm
->ctx
, der
, derlen
);
491 ksba_cert_release (cert
);
500 /* Take a 20 byte hexencoded string and put it into the the provided
501 20 byte buffer FPR in binary format. */
503 unhexify_fpr (const char *hexstr
, unsigned char *fpr
)
508 for (s
=hexstr
, n
=0; hexdigitp (s
); s
++, n
++)
511 return 0; /* no fingerprint (invalid or wrong length). */
513 for (s
=hexstr
, n
=0; *s
; s
+= 2, n
++)
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]))
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]))
538 if (!line
[24] || !unhexify_fpr (line
+25, parm
->fpr
))
539 parm
->seen
++; /* Bumb it to indicate an error. */
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
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
;
566 char line
[ASSUAN_LINELENGTH
];
567 struct inq_certificate_parm_s parm
;
568 struct isvalid_status_parm_s stparm
;
570 rc
= start_dirmngr (ctrl
);
576 certid
= gpgsm_get_fingerprint_hexstring (cert
, GCRY_MD_SHA1
);
580 certid
= gpgsm_get_certid (cert
);
583 log_error ("error getting the certificate ID\n");
584 release_dirmngr (ctrl
);
585 return gpg_error (GPG_ERR_GENERAL
);
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)":"");
597 parm
.ctx
= dirmngr_ctx
;
600 parm
.issuer_cert
= issuer_cert
;
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. */
615 if (opt
.force_crl_refresh
)
616 assuan_transact (dirmngr_ctx
, "OPTION force-crl-refresh=1",
617 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
620 snprintf (line
, DIM(line
)-1, "ISVALID%s %s",
621 use_ocsp
== 2? " --only-ocsp --force-default-responder":"",
623 line
[DIM(line
)-1] = 0;
626 rc
= assuan_transact (dirmngr_ctx
, line
, NULL
, NULL
,
627 inq_certificate
, &parm
,
628 isvalid_status_cb
, &stparm
);
630 log_info ("response of dirmngr: %s\n", rc
? gpg_strerror (rc
): "okay");
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
);
644 ksba_cert_t rspcert
= NULL
;
646 /* Fixme: First try to get the certificate from the
647 dirmngr's cache - it should be there. */
650 rc
= gpg_error (GPG_ERR_ENOMEM
);
652 rc
= keydb_search_fpr (kh
, stparm
.fpr
);
654 rc
= keydb_get_cert (kh
, &rspcert
);
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
);
665 rc
= gpgsm_cert_use_ocsp_p (rspcert
);
667 rc
= gpg_error (GPG_ERR_INV_CRL
);
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
);
676 log_error ("invalid certificate used for CRL/OCSP: %s\n",
678 rc
= gpg_error (GPG_ERR_INV_CRL
);
682 ksba_cert_release (rspcert
);
685 release_dirmngr (ctrl
);
693 lookup_cb (void *opaque
, const void *buffer
, size_t length
)
695 struct lookup_parm_s
*parm
= opaque
;
706 put_membuf (&parm
->data
, buffer
, length
);
709 /* END encountered - process what we have */
710 buf
= get_membuf (&parm
->data
, &len
);
713 parm
->error
= gpg_error (GPG_ERR_ENOMEM
);
717 rc
= ksba_cert_new (&cert
);
723 rc
= ksba_cert_init_from_mem (cert
, buf
, len
);
726 log_error ("failed to parse a certificate: %s\n", gpg_strerror (rc
));
730 parm
->cb (parm
->cb_value
, cert
);
733 ksba_cert_release (cert
);
734 init_membuf (&parm
->data
, 4096);
738 /* Return a properly escaped pattern from NAMES. The only error
739 return is NULL to indicate a malloc failure. */
741 pattern_from_strlist (strlist_t names
)
748 for (n
=0, sl
=names
; sl
; sl
= sl
->next
)
750 for (s
=sl
->d
; *s
; s
++, n
++)
752 if (*s
== '%' || *s
== ' ' || *s
== '+')
758 p
= pattern
= xtrymalloc (n
+1);
762 for (sl
=names
; sl
; sl
= sl
->next
)
764 for (s
=sl
->d
; *s
; s
++)
791 *pattern
= 0; /* is empty */
793 p
[-1] = '\0'; /* remove trailing blank */
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]))
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]))
817 for (line
+=9; *line
== ' '; line
++)
819 gpgsm_status (parm
->ctrl
, STATUS_TRUNCATED
, line
);
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
832 gpgsm_dirmngr_lookup (ctrl_t ctrl
, strlist_t names
, int cache_only
,
833 void (*cb
)(void*, ksba_cert_t
), void *cb_value
)
837 char line
[ASSUAN_LINELENGTH
];
838 struct lookup_parm_s parm
;
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
);
851 else if (!dirmngr2_ctx_locked
)
853 rc
= start_dirmngr2 (ctrl
);
860 log_fatal ("both dirmngr contexts are in use\n");
863 pattern
= pattern_from_strlist (names
);
866 if (ctx
== dirmngr_ctx
)
867 release_dirmngr (ctrl
);
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;
881 parm
.cb_value
= cb_value
;
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
);
892 release_dirmngr2 (ctrl
);
901 /* Run Command helpers*/
903 /* Fairly simple callback to write all output of dirmngr to stdout. */
905 run_command_cb (void *opaque
, const void *buffer
, size_t length
)
911 if ( fwrite (buffer
, length
, 1, stdout
) != 1 )
912 log_error ("error writing to stdout: %s\n", strerror (errno
));
917 /* Handle inquiries from the dirmngr COMMAND. */
919 run_command_inq_cb (void *opaque
, const char *line
)
921 struct run_command_parm_s
*parm
= opaque
;
924 if ( !strncmp (line
, "SENDCERT", 8) && (line
[8] == ' ' || !line
[8]) )
925 { /* send the given certificate */
928 const unsigned char *der
;
933 return gpg_error (GPG_ERR_ASS_PARAMETER
);
935 err
= gpgsm_find_cert (line
, NULL
, &cert
);
938 log_error ("certificate not found: %s\n", gpg_strerror (err
));
939 rc
= gpg_error (GPG_ERR_NOT_FOUND
);
943 der
= ksba_cert_get_image (cert
, &derlen
);
945 rc
= gpg_error (GPG_ERR_INV_CERT_OBJ
);
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. */
954 log_info ("dirmngr: %s\n", line
);
958 log_error ("unsupported inquiry `%s'\n", line
);
959 rc
= gpg_error (GPG_ERR_ASS_UNKNOWN_INQUIRE
);
966 run_command_status_cb (void *opaque
, const char *line
)
968 ctrl_t ctrl
= opaque
;
972 log_info ("dirmngr status: %s\n", line
);
974 if (!strncmp (line
, "PROGRESS", 8) && (line
[8]==' ' || !line
[8]))
978 for (line
+= 8; *line
== ' '; line
++)
980 if (gpgsm_status (ctrl
, STATUS_PROGRESS
, line
))
981 return gpg_error (GPG_ERR_ASS_CANCELED
);
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
)
1003 struct run_command_parm_s parm
;
1005 rc
= start_dirmngr (ctrl
);
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
);
1017 release_dirmngr (ctrl
);
1018 return out_of_core ();
1021 p
= stpcpy (line
, command
);
1022 for (i
=0; i
< argc
; i
++)
1025 for (s
=argv
[i
]; *s
; s
++)
1031 else if (!isprint (*s
) || *s
== '+')
1033 sprintf (p
, "%%%02X", *(const unsigned char *)s
);
1042 rc
= assuan_transact (dirmngr_ctx
, line
,
1043 run_command_cb
, NULL
,
1044 run_command_inq_cb
, &parm
,
1045 run_command_status_cb
, ctrl
);
1047 log_info ("response of dirmngr: %s\n", rc
? gpg_strerror (rc
): "okay");
1048 release_dirmngr (ctrl
);