dirmngr: Add support for hkps keyservers.

* dirmngr/dirmngr.c: Include gnutls.h.
(opts): Add --gnutls-debug and --hkp-cacert.
(opt_gnutls_debug, my_gnutls_log): New.
(set_debug): Set gnutls log level.
(parse_rereadable_options): Register a CA file.
(main): Init GNUTLS.
* dirmngr/ks-engine-hkp.c (ks_hkp_help): Support hkps.
(send_request): Ditto.
This commit is contained in:
Werner Koch 2014-05-05 16:09:45 +02:00
parent ea0f5481f0
commit 60e2fc7d38
5 changed files with 194 additions and 70 deletions

View File

@ -40,6 +40,9 @@
# include <signal.h> # include <signal.h>
#endif #endif
#include <npth.h> #include <npth.h>
#ifdef HTTP_USE_GNUTLS
# include <gnutls/gnutls.h>
#endif /*HTTP_USE_GNUTLS*/
#define JNLIB_NEED_LOG_LOGV #define JNLIB_NEED_LOG_LOGV
@ -92,6 +95,7 @@ enum cmd_and_opt_values {
oDebugAll, oDebugAll,
oDebugWait, oDebugWait,
oDebugLevel, oDebugLevel,
oGnutlsDebug,
oNoGreeting, oNoGreeting,
oNoOptions, oNoOptions,
oHomedir, oHomedir,
@ -116,6 +120,7 @@ enum cmd_and_opt_values {
oOCSPMaxPeriod, oOCSPMaxPeriod,
oOCSPCurrentPeriod, oOCSPCurrentPeriod,
oMaxReplies, oMaxReplies,
oHkpCaCert,
oFakedSystemTime, oFakedSystemTime,
oForce, oForce,
oAllowOCSP, oAllowOCSP,
@ -195,11 +200,16 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_s_i (oMaxReplies, "max-replies", ARGPARSE_s_i (oMaxReplies, "max-replies",
N_("|N|do not return more than N items in one query")), N_("|N|do not return more than N items in one query")),
ARGPARSE_s_s (oHkpCaCert, "hkp-cacert",
N_("|FILE|use the CA certifciates in FILE for HKP over TLS")),
ARGPARSE_s_s (oSocketName, "socket-name", "@"), /* Only for debugging. */ ARGPARSE_s_s (oSocketName, "socket-name", "@"), /* Only for debugging. */
ARGPARSE_s_u (oFakedSystemTime, "faked-system-time", "@"), /*(epoch time)*/ ARGPARSE_s_u (oFakedSystemTime, "faked-system-time", "@"), /*(epoch time)*/
ARGPARSE_p_u (oDebug, "debug", "@"), ARGPARSE_p_u (oDebug, "debug", "@"),
ARGPARSE_s_n (oDebugAll, "debug-all", "@"), ARGPARSE_s_n (oDebugAll, "debug-all", "@"),
ARGPARSE_s_i (oGnutlsDebug, "gnutls-debug", "@"),
ARGPARSE_s_i (oDebugWait, "debug-wait", "@"), ARGPARSE_s_i (oDebugWait, "debug-wait", "@"),
ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"), ARGPARSE_s_n (oNoGreeting, "no-greeting", "@"),
ARGPARSE_s_s (oHomedir, "homedir", "@"), ARGPARSE_s_s (oHomedir, "homedir", "@"),
@ -234,6 +244,9 @@ static char *current_logfile;
/* Helper to implement --debug-level. */ /* Helper to implement --debug-level. */
static const char *debug_level; static const char *debug_level;
/* Helper to set the GNUTLS log level. */
static int opt_gnutls_debug = -1;
/* Flag indicating that a shutdown has been requested. */ /* Flag indicating that a shutdown has been requested. */
static volatile int shutdown_pending; static volatile int shutdown_pending;
@ -331,6 +344,20 @@ my_ksba_hash_buffer (void *arg, const char *oid,
} }
/* GNUTLS log function callback. */
static void
my_gnutls_log (int level, const char *text)
{
int n;
n = strlen (text);
while (n && text[n-1] == '\n')
n--;
log_debug ("gnutls:L%d: %.*s\n", level, n, text);
}
/* Setup the debugging. With a LEVEL of NULL only the active debug /* Setup the debugging. With a LEVEL of NULL only the active debug
flags are propagated to the subsystems. With LEVEL set, a specific flags are propagated to the subsystems. With LEVEL set, a specific
set of debug flags is set; thus overriding all flags already set of debug flags is set; thus overriding all flags already
@ -382,6 +409,14 @@ set_debug (void)
if (opt.debug & DBG_CRYPTO_VALUE ) if (opt.debug & DBG_CRYPTO_VALUE )
gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1); gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1);
#ifdef HTTP_USE_GNUTLS
if (opt_gnutls_debug >= 0)
{
gnutls_global_set_log_function (my_gnutls_log);
gnutls_global_set_log_level (opt_gnutls_debug);
}
#endif /*HTTP_USE_GNUTLS*/
} }
@ -439,6 +474,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
opt.ocsp_signer = tmp; opt.ocsp_signer = tmp;
} }
FREE_STRLIST (opt.ignored_cert_extensions); FREE_STRLIST (opt.ignored_cert_extensions);
http_register_tls_ca (NULL);
return 1; return 1;
} }
@ -449,6 +485,7 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
case oDebug: opt.debug |= pargs->r.ret_ulong; break; case oDebug: opt.debug |= pargs->r.ret_ulong; break;
case oDebugAll: opt.debug = ~0; break; case oDebugAll: opt.debug = ~0; break;
case oDebugLevel: debug_level = pargs->r.ret_str; break; case oDebugLevel: debug_level = pargs->r.ret_str; break;
case oGnutlsDebug: opt_gnutls_debug = pargs->r.ret_int; break;
case oLogFile: case oLogFile:
if (!reread) if (!reread)
@ -490,6 +527,10 @@ parse_rereadable_options (ARGPARSE_ARGS *pargs, int reread)
case oMaxReplies: opt.max_replies = pargs->r.ret_int; break; case oMaxReplies: opt.max_replies = pargs->r.ret_int; break;
case oHkpCaCert:
http_register_tls_ca (pargs->r.ret_str);
break;
case oIgnoreCertExtension: case oIgnoreCertExtension:
add_to_strlist (&opt.ignored_cert_extensions, pargs->r.ret_str); add_to_strlist (&opt.ignored_cert_extensions, pargs->r.ret_str);
break; break;
@ -628,6 +669,12 @@ main (int argc, char **argv)
ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free ); ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );
ksba_set_hash_buffer_function (my_ksba_hash_buffer, NULL); ksba_set_hash_buffer_function (my_ksba_hash_buffer, NULL);
/* Init GNUTLS. */
#ifdef HTTP_USE_GNUTLS
rc = gnutls_global_init ();
if (rc)
log_fatal ("gnutls_global_init failed: %s\n", gnutls_strerror (rc));
#endif /*HTTP_USE_GNUTLS*/
/* Init Assuan. */ /* Init Assuan. */
malloc_hooks.malloc = gcry_malloc; malloc_hooks.malloc = gcry_malloc;

View File

@ -628,12 +628,14 @@ ks_hkp_help (ctrl_t ctrl, parsed_uri_t uri)
const char const data[] = const char const data[] =
"Handler for HKP URLs:\n" "Handler for HKP URLs:\n"
" hkp://\n" " hkp://\n"
" hkps://\n"
"Supported methods: search, get, put\n"; "Supported methods: search, get, put\n";
gpg_error_t err; gpg_error_t err;
if (!uri) if (!uri)
err = ks_print_help (ctrl, " hkp"); err = ks_print_help (ctrl, " hkp\n hkps");
else if (uri->is_http && !strcmp (uri->scheme, "hkp")) else if (uri->is_http && (!strcmp (uri->scheme, "hkp")
|| !strcmp (uri->scheme, "hkps")))
err = ks_print_help (ctrl, data); err = ks_print_help (ctrl, data);
else else
err = 0; err = 0;
@ -747,6 +749,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
estream_t *r_fp) estream_t *r_fp)
{ {
gpg_error_t err; gpg_error_t err;
http_session_t session = NULL;
http_t http = NULL; http_t http = NULL;
int redirects_left = MAX_REDIRECTS; int redirects_left = MAX_REDIRECTS;
estream_t fp = NULL; estream_t fp = NULL;
@ -754,6 +757,10 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
*r_fp = NULL; *r_fp = NULL;
err = http_session_new (&session, NULL);
if (err)
goto leave;
once_more: once_more:
err = http_open (&http, err = http_open (&http,
post_cb? HTTP_REQ_POST : HTTP_REQ_GET, post_cb? HTTP_REQ_POST : HTTP_REQ_GET,
@ -761,7 +768,8 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
/* fixme: AUTH */ NULL, /* fixme: AUTH */ NULL,
httpflags, httpflags,
/* fixme: proxy*/ NULL, /* fixme: proxy*/ NULL,
NULL, NULL, session,
NULL,
/*FIXME curl->srvtag*/NULL); /*FIXME curl->srvtag*/NULL);
if (!err) if (!err)
{ {
@ -798,6 +806,13 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
goto leave; goto leave;
} }
if (http_get_tls_info (http, NULL))
{
/* Update the httpflags so that a redirect won't fallback to an
unencrypted connection. */
httpflags |= HTTP_FLAG_FORCE_TLS;
}
switch (http_get_status_code (http)) switch (http_get_status_code (http))
{ {
case 200: case 200:
@ -806,6 +821,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
case 301: case 301:
case 302: case 302:
case 307:
{ {
const char *s = http_get_header (http, "Location"); const char *s = http_get_header (http, "Location");
@ -837,6 +853,10 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
goto leave; goto leave;
} }
/* FIXME: We should register a permanent redirection and whether a
host has ever used TLS so that future calls will always use
TLS. */
fp = http_get_read_ptr (http); fp = http_get_read_ptr (http);
if (!fp) if (!fp)
{ {
@ -851,6 +871,7 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
leave: leave:
http_close (http, 0); http_close (http, 0);
http_session_release (session);
xfree (request_buffer); xfree (request_buffer);
return err; return err;
} }

View File

@ -0,0 +1,32 @@
-----BEGIN CERTIFICATE-----
MIIFizCCA3OgAwIBAgIJAK9zyLTPn4CPMA0GCSqGSIb3DQEBBQUAMFwxCzAJBgNV
BAYTAk5PMQ0wCwYDVQQIDARPc2xvMR4wHAYDVQQKDBVza3Mta2V5c2VydmVycy5u
ZXQgQ0ExHjAcBgNVBAMMFXNrcy1rZXlzZXJ2ZXJzLm5ldCBDQTAeFw0xMjEwMDkw
MDMzMzdaFw0yMjEwMDcwMDMzMzdaMFwxCzAJBgNVBAYTAk5PMQ0wCwYDVQQIDARP
c2xvMR4wHAYDVQQKDBVza3Mta2V5c2VydmVycy5uZXQgQ0ExHjAcBgNVBAMMFXNr
cy1rZXlzZXJ2ZXJzLm5ldCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
ggIBANdsWy4PXWNUCkS3L//nrd0GqN3dVwoBGZ6w94Tw2jPDPifegwxQozFXkG6I
6A4TK1CJLXPvfz0UP0aBYyPmTNadDinaB9T4jIwd4rnxl+59GiEmqkN3IfPsv5Jj
MkKUmJnvOT0DEVlEaO1UZIwx5WpfprB3mR81/qm4XkAgmYrmgnLXd/pJDAMk7y1F
45b5zWofiD5l677lplcIPRbFhpJ6kDTODXh/XEdtF71EAeaOdEGOvyGDmCO0GWqS
FDkMMPTlieLA/0rgFTcz4xwUYj/cD5e0ZBuSkYsYFAU3hd1cGfBue0cPZaQH2HYx
Qk4zXD8S3F4690fRhr+tki5gyG6JDR67aKp3BIGLqm7f45WkX1hYp+YXywmEziM4
aSbGYhx8hoFGfq9UcfPEvp2aoc8u5sdqjDslhyUzM1v3m3ZGbhwEOnVjljY6JJLx
MxagxnZZSAY424ZZ3t71E/Mn27dm2w+xFRuoy8JEjv1d+BT3eChM5KaNwrj0IO/y
u8kFIgWYA1vZ/15qMT+tyJTfyrNVV/7Df7TNeWyNqjJ5rBmt0M6NpHG7CrUSkBy9
p8JhimgjP5r0FlEkgg+lyD+V79H98gQfVgP3pbJICz0SpBQf2F/2tyS4rLm+49rP
fcOajiXEuyhpcmzgusAj/1FjrtlynH1r9mnNaX4e+rLWzvU5AgMBAAGjUDBOMB0G
A1UdDgQWBBTkwyoJFGfYTVISTpM8E+igjdq28zAfBgNVHSMEGDAWgBTkwyoJFGfY
TVISTpM8E+igjdq28zAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQAR
OXnYwu3g1ZjHyley3fZI5aLPsaE17cOImVTehC8DcIphm2HOMR/hYTTL+V0G4P+u
gH+6xeRLKSHMHZTtSBIa6GDL03434y9CBuwGvAFCMU2GV8w92/Z7apkAhdLToZA/
X/iWP2jeaVJhxgEcH8uPrnSlqoPBcKC9PrgUzQYfSZJkLmB+3jEa3HKruy1abJP5
gAdQvwvcPpvYRnIzUc9fZODsVmlHVFBCl2dlu/iHh2h4GmL4Da2rRkUMlbVTdioB
UYIvMycdOkpH5wJftzw7cpjsudGas0PARDXCFfGyKhwBRFY7Xp7lbjtU5Rz0Gc04
lPrhDf0pFE98Aw4jJRpFeWMjpXUEaG1cq7D641RpgcMfPFvOHY47rvDTS7XJOaUT
BwRjmDt896s6vMDcaG/uXJbQjuzmmx3W2Idyh3s5SI0GTHb0IwMKYb4eBUIpQOnB
cE77VnCYqKvN1NVYAqhWjXbY7XasZvszCRcOG+W3FqNaHOK/n/0ueb0uijdLan+U
f4p1bjbAox8eAOQS/8a3bzkJzdyBNUKGx1BIK2IBL9bn/HravSDOiNRSnZ/R3l9G
ZauX0tu7IIDlRCILXSyeazu0aj/vdT3YFQXPcvt5Fkf5wiNTo53f72/jYEJd6qph
WrpoKqrwGwTpRUCMhYIUt65hsTxCiJJ5nKe39h46sg==
-----END CERTIFICATE-----

View File

@ -18,7 +18,7 @@
@mansect synopsis @mansect synopsis
@ifset manverb @ifset manverb
.B dirmngr .B dirmngr
.RI [ options ] .RI [ options ]
.I command .I command
.RI [ args ] .RI [ args ]
@end ifset @end ifset
@ -32,7 +32,7 @@ system daemon through the @command{dirmngr-client} tool.
If @command{dirmngr} is started in system daemon mode, it uses a If @command{dirmngr} is started in system daemon mode, it uses a
directory layout as common for system daemons and does not make use of directory layout as common for system daemons and does not make use of
the default @file{~/.gnupg} directory. the default @file{~/.gnupg} directory.
@manpause @manpause
@ -175,7 +175,7 @@ numeric value or by a keyword:
@item none @item none
No debugging at all. A value of less than 1 may be used instead of No debugging at all. A value of less than 1 may be used instead of
the keyword. the keyword.
@item basic @item basic
Some basic debug messages. A value between 1 and 2 may be used Some basic debug messages. A value between 1 and 2 may be used
instead of the keyword. instead of the keyword.
@item advanced @item advanced
@ -204,6 +204,10 @@ usual C-Syntax.
@opindex debug-all @opindex debug-all
Same as @code{--debug=0xffffffff} Same as @code{--debug=0xffffffff}
@item --gnutls-debug @var{level}
@opindex gnutls-debug
Enable debugging of GNUTLS at @var{level}.
@item --debug-wait @var{n} @item --debug-wait @var{n}
@opindex debug-wait @opindex debug-wait
When running in server mode, wait @var{n} seconds before entering the When running in server mode, wait @var{n} seconds before entering the
@ -247,12 +251,12 @@ scheme are ignored when looking for a suitable DP.
@item --ignore-ldap-dp @item --ignore-ldap-dp
@opindex ignore-ldap-dp @opindex ignore-ldap-dp
This is similar to @option{--ignore-http-dp} but ignores entries using This is similar to @option{--ignore-http-dp} but ignores entries using
the @acronym{LDAP} scheme. Both options may be combined resulting in the @acronym{LDAP} scheme. Both options may be combined resulting in
ignoring DPs entirely. ignoring DPs entirely.
@item --ignore-ocsp-service-url @item --ignore-ocsp-service-url
@opindex ignore-ocsp-service-url @opindex ignore-ocsp-service-url
Ignore all OCSP URLs contained in the certificate. The effect is to Ignore all OCSP URLs contained in the certificate. The effect is to
force the use of the default responder. force the use of the default responder.
@item --honor-http-proxy @item --honor-http-proxy
@ -284,7 +288,7 @@ configured LDAP server if the connection using the "proxy" failed.
@item --ldapserverlist-file @var{file} @item --ldapserverlist-file @var{file}
@opindex ldapserverlist-file @opindex ldapserverlist-file
Read the list of LDAP servers to consult for CRLs and certificates from Read the list of LDAP servers to consult for CRLs and certificates from
file instead of the default per-user ldap server list file. The default file instead of the default per-user ldap server list file. The default
value for @var{file} is @file{dirmngr_ldapservers.conf} or value for @var{file} is @file{dirmngr_ldapservers.conf} or
@file{ldapservers.conf} when running in @option{--daemon} mode. @file{ldapservers.conf} when running in @option{--daemon} mode.
@ -328,7 +332,7 @@ Note: The current version of dirmngr has this option disabled by default.
@item --allow-ocsp @item --allow-ocsp
@opindex allow-ocsp @opindex allow-ocsp
This option enables OCSP support if requested by the client. This option enables OCSP support if requested by the client.
OCSP requests are rejected by default because they may violate the OCSP requests are rejected by default because they may violate the
privacy of the user; for example it is possible to track the time when privacy of the user; for example it is possible to track the time when
@ -395,10 +399,17 @@ won't be rejected due to an unknown critical extension. Use this
option with care because extensions are usually flagged as critical option with care because extensions are usually flagged as critical
for a reason. for a reason.
@item --hkp-cacert @var{file}
Use the root certificates in @var{file} for verification of the TLS
certificates used with @code{hkps} (keyserver access over TLS). If
the file is in PEM format a suffix of @code{.pem} is expected for
@var{file}. This option may be given multiple times to add more
root certificates.
@end table @end table
@c @c
@c Dirmngr Configuration @c Dirmngr Configuration
@c @c
@mansect files @mansect files
@ -472,7 +483,7 @@ Please ignore the output; it is not needed anymore. Check the log file
to see whether all trusted root certificates have been loaded correctly. to see whether all trusted root certificates have been loaded correctly.
@c @c
@c Dirmngr Signals @c Dirmngr Signals
@c @c
@mansect signals @mansect signals
@ -480,7 +491,7 @@ to see whether all trusted root certificates have been loaded correctly.
@section Use of signals. @section Use of signals.
A running @command{dirmngr} may be controlled by signals, i.e. using A running @command{dirmngr} may be controlled by signals, i.e. using
the @command{kill} command to send a signal to the process. the @command{kill} command to send a signal to the process.
Here is a list of supported signals: Here is a list of supported signals:
@ -522,7 +533,7 @@ This prints some caching statistics to the log file.
Dirmngr is supposed to be used as a system wide daemon, it should be Dirmngr is supposed to be used as a system wide daemon, it should be
started like: started like:
@example @example
dirmngr --daemon dirmngr --daemon
@end example @end example
@ -613,7 +624,7 @@ local lookup will be done in this case.
Check whether the certificate described by the @var{certid} has been Check whether the certificate described by the @var{certid} has been
revoked. Due to caching, the Dirmngr is able to answer immediately in revoked. Due to caching, the Dirmngr is able to answer immediately in
most cases. most cases.
The @var{certid} is a hex encoded string consisting of two parts, The @var{certid} is a hex encoded string consisting of two parts,
delimited by a single dot. The first part is the SHA-1 hash of the delimited by a single dot. The first part is the SHA-1 hash of the
@ -642,7 +653,7 @@ us that it has been revoked.
@item GPG_ERR_NO_CRL_KNOWN @item GPG_ERR_NO_CRL_KNOWN
No CRL is known for this certificate or the CRL is not valid or out of No CRL is known for this certificate or the CRL is not valid or out of
date. date.
@item GPG_ERR_NO_DATA @item GPG_ERR_NO_DATA
The OCSP responder returned an ``unknown'' status. This means that it The OCSP responder returned an ``unknown'' status. This means that it
@ -690,7 +701,7 @@ given or the certificate is not know, the function inquires the
certificate using: certificate using:
@example @example
S: INQUIRE TARGETCERT S: INQUIRE TARGETCERT
C: D <DER encoded certificate> C: D <DER encoded certificate>
C: END C: END
@end example @end example
@ -720,7 +731,7 @@ certificate is not known by Dirmngr, the function inquires the
certificate using: certificate using:
@example @example
S: INQUIRE TARGETCERT S: INQUIRE TARGETCERT
C: D <DER encoded certificate> C: D <DER encoded certificate>
C: END C: END
@end example @end example
@ -751,13 +762,13 @@ helpful for debugging. To get the actual certificate, this command
immediately inquires it using immediately inquires it using
@example @example
S: INQUIRE TARGETCERT S: INQUIRE TARGETCERT
C: D <DER encoded certificate> C: D <DER encoded certificate>
C: END C: END
@end example @end example
Thus the caller is expected to return the certificate for the request Thus the caller is expected to return the certificate for the request
as a binary blob. as a binary blob.
@noindent @noindent
The return code is 0 for success; i.e. the certificate has not been The return code is 0 for success; i.e. the certificate has not been
@ -771,45 +782,45 @@ internally by dirmngr. This command is only useful for debugging. To
get the actual certificate, this command immediately inquires it using get the actual certificate, this command immediately inquires it using
@example @example
S: INQUIRE TARGETCERT S: INQUIRE TARGETCERT
C: D <DER encoded certificate> C: D <DER encoded certificate>
C: END C: END
@end example @end example
Thus the caller is expected to return the certificate for the request Thus the caller is expected to return the certificate for the request
as a binary blob. as a binary blob.
@mansect see also @mansect see also
@ifset isman @ifset isman
@command{gpgsm}(1), @command{gpgsm}(1),
@command{dirmngr-client}(1) @command{dirmngr-client}(1)
@end ifset @end ifset
@include see-also-note.texi @include see-also-note.texi
@c @c
@c !!! UNDER CONSTRUCTION !!! @c !!! UNDER CONSTRUCTION !!!
@c @c
@c @c
@c @section Verifying a Certificate @c @section Verifying a Certificate
@c @c
@c There are several ways to request services from Dirmngr. Almost all of @c There are several ways to request services from Dirmngr. Almost all of
@c them are done using the Assuan protocol. What we describe here is the @c them are done using the Assuan protocol. What we describe here is the
@c Assuan command CHECKCRL as used for example by the dirmnr-client tool if @c Assuan command CHECKCRL as used for example by the dirmnr-client tool if
@c invoked as @c invoked as
@c @c
@c @example @c @example
@c dirmngr-client foo.crt @c dirmngr-client foo.crt
@c @end example @c @end example
@c @c
@c This command will send an Assuan request to an already running Dirmngr @c This command will send an Assuan request to an already running Dirmngr
@c instance. foo.crt is expected to be a standard X.509 certificate and @c instance. foo.crt is expected to be a standard X.509 certificate and
@c dirmngr will receive the Assuan command @c dirmngr will receive the Assuan command
@c @c
@c @example @c @example
@c CHECKCRL @var [{fingerprint}] @c CHECKCRL @var [{fingerprint}]
@c @end example @c @end example
@c @c
@c @var{fingerprint} is optional and expected to be the SHA-1 has of the @c @var{fingerprint} is optional and expected to be the SHA-1 has of the
@c DER encoding of the certificate under question. It is to be HEX @c DER encoding of the certificate under question. It is to be HEX
@c encoded. The rationale for sending the fingerprint is that it allows @c encoded. The rationale for sending the fingerprint is that it allows
@ -817,15 +828,15 @@ as a binary blob.
@c this is not the case and no certificate has been found in dirmngr's @c this is not the case and no certificate has been found in dirmngr's
@c internal certificate storage, dirmngr will request the certificate using @c internal certificate storage, dirmngr will request the certificate using
@c the Assuan inquiry @c the Assuan inquiry
@c @c
@c @example @c @example
@c INQUIRE TARGETCERT @c INQUIRE TARGETCERT
@c @end example @c @end example
@c @c
@c The caller (in our example dirmngr-client) is then expected to return @c The caller (in our example dirmngr-client) is then expected to return
@c the certificate for the request (which should match @var{fingerprint}) @c the certificate for the request (which should match @var{fingerprint})
@c as a binary blob. @c as a binary blob.
@c @c
@c Dirmngr now passes control to @code{crl_cache_cert_isvalid}. This @c Dirmngr now passes control to @code{crl_cache_cert_isvalid}. This
@c function checks whether a CRL item exists for target certificate. These @c function checks whether a CRL item exists for target certificate. These
@c CRL items are kept in a database of already loaded and verified CRLs. @c CRL items are kept in a database of already loaded and verified CRLs.
@ -837,25 +848,25 @@ as a binary blob.
@c listed in the CRL or @code{GPG_ERR_NO_CRL_KNOWN} in cases where no CRL or no @c listed in the CRL or @code{GPG_ERR_NO_CRL_KNOWN} in cases where no CRL or no
@c information is available. The first two codes are immediatly returned to @c information is available. The first two codes are immediatly returned to
@c the caller and the processing of this request has been done. @c the caller and the processing of this request has been done.
@c @c
@c Only the @code{GPG_ERR_NO_CRL_KNOWN} needs more attention: Dirmngr now @c Only the @code{GPG_ERR_NO_CRL_KNOWN} needs more attention: Dirmngr now
@c calls @code{clr_cache_reload_crl} and if this succeeds calls @c calls @code{clr_cache_reload_crl} and if this succeeds calls
@c @code{crl_cache_cert_isvald) once more. All further errors are @c @code{crl_cache_cert_isvald) once more. All further errors are
@c immediately returned to the caller. @c immediately returned to the caller.
@c @c
@c @code{crl_cache_reload_crl} is the actual heart of the CRL management. @c @code{crl_cache_reload_crl} is the actual heart of the CRL management.
@c It locates the corresponding CRL for the target certificate, reads and @c It locates the corresponding CRL for the target certificate, reads and
@c verifies this CRL and stores it in the CRL cache. It works like this: @c verifies this CRL and stores it in the CRL cache. It works like this:
@c @c
@c * Loop over all crlDPs in the target certificate. @c * Loop over all crlDPs in the target certificate.
@c * If the crlDP is invalid immediately terminate the loop. @c * If the crlDP is invalid immediately terminate the loop.
@c * Loop over all names in the current crlDP. @c * Loop over all names in the current crlDP.
@c * If the URL scheme is unknown or not enabled @c * If the URL scheme is unknown or not enabled
@c (--ignore-http-dp, --ignore-ldap-dp) continues with @c (--ignore-http-dp, --ignore-ldap-dp) continues with
@c the next name. @c the next name.
@c * @code{crl_fetch} is called to actually retrieve the CRL. @c * @code{crl_fetch} is called to actually retrieve the CRL.
@c In case of problems this name is ignore and we continue with @c In case of problems this name is ignore and we continue with
@c the next name. Note that @code{crl_fetch} does only return @c the next name. Note that @code{crl_fetch} does only return
@c a descriptor for the CRL for further reading so does the CRL @c a descriptor for the CRL for further reading so does the CRL
@c does not yet end up in memory. @c does not yet end up in memory.
@c * @code{crl_cache_insert} is called with that descriptor to @c * @code{crl_cache_insert} is called with that descriptor to
@ -873,16 +884,16 @@ as a binary blob.
@c * @code(crl_cache_insert) is then used to actually insert the CRL @c * @code(crl_cache_insert) is then used to actually insert the CRL
@c into the cache. If this failed we give up immediatley without @c into the cache. If this failed we give up immediatley without
@c checking the rest of the servers from the first step. @c checking the rest of the servers from the first step.
@c * Ready. @c * Ready.
@c @c
@c @c
@c The @code{crl_cache_insert} function takes care of reading the bulk of @c The @code{crl_cache_insert} function takes care of reading the bulk of
@c the CRL, parsing it and checking the signature. It works like this: A @c the CRL, parsing it and checking the signature. It works like this: A
@c new database file is created using a temporary file name. The CRL @c new database file is created using a temporary file name. The CRL
@c parsing machinery is started and all items of the CRL are put into @c parsing machinery is started and all items of the CRL are put into
@c this database file. At the end the issuer certificate of the CRL @c this database file. At the end the issuer certificate of the CRL
@c needs to be retrieved. Three cases are to be distinguished: @c needs to be retrieved. Three cases are to be distinguished:
@c @c
@c a) An authorityKeyIdentifier with an issuer and serialno exits: The @c a) An authorityKeyIdentifier with an issuer and serialno exits: The
@c certificate is retrieved using @code{find_cert_bysn}. If @c certificate is retrieved using @code{find_cert_bysn}. If
@c the certificate is in the certificate cache, it is directly @c the certificate is in the certificate cache, it is directly
@ -899,7 +910,7 @@ as a binary blob.
@c certificate to match the requested issuer and seriano (This is @c certificate to match the requested issuer and seriano (This is
@c needed because the LDAP layer may return several certificates as @c needed because the LDAP layer may return several certificates as
@c LDAP as no standard way to retrieve by serial number). @c LDAP as no standard way to retrieve by serial number).
@c @c
@c b) An authorityKeyIdentifier with a key ID exists: The certificate is @c b) An authorityKeyIdentifier with a key ID exists: The certificate is
@c retrieved using @code{find_cert_bysubject}. If the certificate is @c retrieved using @code{find_cert_bysubject}. If the certificate is
@c in the certificate cache, it is directly returned. Then the @c in the certificate cache, it is directly returned. Then the
@ -913,7 +924,7 @@ as a binary blob.
@c external resources. This is done using the @code{ca_cert_fetch} @c external resources. This is done using the @code{ca_cert_fetch}
@c and @code{fetch_next_ksba_cert} and comparing the returned @c and @code{fetch_next_ksba_cert} and comparing the returned
@c certificate to match the requested subject and key ID. @c certificate to match the requested subject and key ID.
@c @c
@c c) No authorityKeyIdentifier exits: The certificate is retrieved @c c) No authorityKeyIdentifier exits: The certificate is retrieved
@c using @code{find_cert_bysubject} without the key ID argument. If @c using @code{find_cert_bysubject} without the key ID argument. If
@c the certificate is in the certificate cache the first one with a @c the certificate is in the certificate cache the first one with a
@ -930,12 +941,12 @@ as a binary blob.
@c and @code{fetch_next_ksba_cert} and comparing the returned @c and @code{fetch_next_ksba_cert} and comparing the returned
@c certificate to match the requested subject; the first certificate @c certificate to match the requested subject; the first certificate
@c with a matching subject is then returned. @c with a matching subject is then returned.
@c @c
@c If no certificate was found, the function returns with the error @c If no certificate was found, the function returns with the error
@c GPG_ERR_MISSING_CERT. Now the signature is verified. If this fails, @c GPG_ERR_MISSING_CERT. Now the signature is verified. If this fails,
@c the erro is returned. On success the @code{validate_cert_chain} is @c the erro is returned. On success the @code{validate_cert_chain} is
@c used to verify that the certificate is actually valid. @c used to verify that the certificate is actually valid.
@c @c
@c Here we may encounter a recursive situation: @c Here we may encounter a recursive situation:
@c @code{validate_cert_chain} needs to look at other certificates and @c @code{validate_cert_chain} needs to look at other certificates and
@c also at CRLs to check whether tehse other certificates and well, the @c also at CRLs to check whether tehse other certificates and well, the
@ -944,7 +955,7 @@ as a binary blob.
@c are currently processing. This would be a catch-22 and may indicate a @c are currently processing. This would be a catch-22 and may indicate a
@c broken PKI. However, due to overlapping expiring times and imprecise @c broken PKI. However, due to overlapping expiring times and imprecise
@c clocks thsi may actually happen. @c clocks thsi may actually happen.
@c @c
@c For historical reasons the Assuan command ISVALID is a bit different @c For historical reasons the Assuan command ISVALID is a bit different
@c to CHECKCRL but this is mainly due to different calling conventions. @c to CHECKCRL but this is mainly due to different calling conventions.
@c In the end the same fucntionality is used, albeit hidden by a couple @c In the end the same fucntionality is used, albeit hidden by a couple
@ -952,44 +963,44 @@ as a binary blob.
@c ingetrages OCSP checking depending on options are the way it is @c ingetrages OCSP checking depending on options are the way it is
@c called. GPGSM still uses this command but might eventuall switch over @c called. GPGSM still uses this command but might eventuall switch over
@c to CHECKCRL and CHECKOCSP so that ISVALID can be retired. @c to CHECKCRL and CHECKOCSP so that ISVALID can be retired.
@c @c
@c @c
@c @section Validating a certificate @c @section Validating a certificate
@c @c
@c We describe here how the internal function @code{validate_cert_chain} @c We describe here how the internal function @code{validate_cert_chain}
@c works. Note that mainly testing purposes this functionality may be @c works. Note that mainly testing purposes this functionality may be
@c called directly using @cmd{dirmngr-client --validate @file{foo.crt}}. @c called directly using @cmd{dirmngr-client --validate @file{foo.crt}}.
@c @c
@c For backward compatibility this function returns success if Dirmngr is @c For backward compatibility this function returns success if Dirmngr is
@c not used as a system daemon. Thus not validating the certicates at @c not used as a system daemon. Thus not validating the certicates at
@c all. FIXME: This is definitely not correct and should be fixed ASAP. @c all. FIXME: This is definitely not correct and should be fixed ASAP.
@c @c
@c The function takes the target certificate and a mode argument as @c The function takes the target certificate and a mode argument as
@c parameters and returns an error code and optionally the closes @c parameters and returns an error code and optionally the closes
@c expiration time of all certificates in the chain. @c expiration time of all certificates in the chain.
@c @c
@c We first check that the certificate may be used for the requested @c We first check that the certificate may be used for the requested
@c purpose (i.e. OCSP or CRL signing). If this is not the case @c purpose (i.e. OCSP or CRL signing). If this is not the case
@c GPG_ERR_WRONG_KEY_USAGE is returned. @c GPG_ERR_WRONG_KEY_USAGE is returned.
@c @c
@c The next step is to find the trust anchor (root certificate) and to @c The next step is to find the trust anchor (root certificate) and to
@c assemble the chain in memory: Starting with the target certificate, @c assemble the chain in memory: Starting with the target certificate,
@c the expiration time is checked against the current date, unknown @c the expiration time is checked against the current date, unknown
@c critical extensions are detected and certificate policies are matched @c critical extensions are detected and certificate policies are matched
@c (We only allow 2.289.9.9 but I have no clue about that OID and from @c (We only allow 2.289.9.9 but I have no clue about that OID and from
@c where I got it - it does not even seem to be assigned - debug cruft?). @c where I got it - it does not even seem to be assigned - debug cruft?).
@c @c
@c Now if this certificate is a self-signed one, we have reached the @c Now if this certificate is a self-signed one, we have reached the
@c trust anchor. In this case we check that the signature is good, the @c trust anchor. In this case we check that the signature is good, the
@c certificate is allowed to act as a CA, that it is a trusted one (by @c certificate is allowed to act as a CA, that it is a trusted one (by
@c checking whether it is has been put into the trusted-certs @c checking whether it is has been put into the trusted-certs
@c configuration directory) and finally prepend into to our list @c configuration directory) and finally prepend into to our list
@c representing the certificate chain. This steps ends then. @c representing the certificate chain. This steps ends then.
@c @c
@c If it is not a self-signed certificate, we check that the chain won't @c If it is not a self-signed certificate, we check that the chain won't
@c get too long (current limit is 100), if this is the case we terminate @c get too long (current limit is 100), if this is the case we terminate
@c with the error GPG_ERR_BAD_CERT_CHAIN. @c with the error GPG_ERR_BAD_CERT_CHAIN.
@c @c
@c Now the issuer's certificate is looked up: If an @c Now the issuer's certificate is looked up: If an
@c authorityKeyIdentifier is available, this one is used to locate the @c authorityKeyIdentifier is available, this one is used to locate the
@c certificate either using issuer and serialnumber or subject DN @c certificate either using issuer and serialnumber or subject DN
@ -1002,7 +1013,7 @@ as a binary blob.
@c that a matching certificate has explicitly been put into the @c that a matching certificate has explicitly been put into the
@c certificate cache. If the issuer's certificate could not be found, @c certificate cache. If the issuer's certificate could not be found,
@c the validation terminates with the error code @code{GPG_ERR_MISSING_CERT}. @c the validation terminates with the error code @code{GPG_ERR_MISSING_CERT}.
@c @c
@c If the issuer's certificate has been found, the signature of the @c If the issuer's certificate has been found, the signature of the
@c actual certificate is checked and in case this fails the error @c actual certificate is checked and in case this fails the error
@c #code{GPG_ERR_BAD_CERT_CHAIN} is returned. If the signature checks out, the @c #code{GPG_ERR_BAD_CERT_CHAIN} is returned. If the signature checks out, the
@ -1011,13 +1022,13 @@ as a binary blob.
@c certificate signing). Then the certificate is prepended to our list @c certificate signing). Then the certificate is prepended to our list
@c representing the certificate chain. Finally the loop is continued now @c representing the certificate chain. Finally the loop is continued now
@c with the issuer's certificate as the current certificate. @c with the issuer's certificate as the current certificate.
@c @c
@c After the end of the loop and if no error as been encountered @c After the end of the loop and if no error as been encountered
@c (i.e. the certificate chain has been assempled correctly), a check is @c (i.e. the certificate chain has been assempled correctly), a check is
@c done whether any certificate expired or a critical policy has not been @c done whether any certificate expired or a critical policy has not been
@c met. In any of these cases the validation terminates with an @c met. In any of these cases the validation terminates with an
@c appropriate error. @c appropriate error.
@c @c
@c Finally the function @code{check_revocations} is called to verify no @c Finally the function @code{check_revocations} is called to verify no
@c certificate in the assempled chain has been revoked: This is an @c certificate in the assempled chain has been revoked: This is an
@c recursive process because a CRL has to be checked for each certificate @c recursive process because a CRL has to be checked for each certificate
@ -1025,16 +1036,16 @@ as a binary blob.
@c that it is trusted and we avoid checking a CRL here due to common @c that it is trusted and we avoid checking a CRL here due to common
@c setup problems and the assumption that a revoked root certifcate has @c setup problems and the assumption that a revoked root certifcate has
@c been removed from the list of trusted certificates. @c been removed from the list of trusted certificates.
@c @c
@c @c
@c @c
@c @c
@c @section Looking up certificates through LDAP. @c @section Looking up certificates through LDAP.
@c @c
@c This describes the LDAP layer to retrieve certificates. @c This describes the LDAP layer to retrieve certificates.
@c the functions @code{ca_cert_fetch} and @code{fetch_next_ksba_cert} are @c the functions @code{ca_cert_fetch} and @code{fetch_next_ksba_cert} are
@c used for this. The first one starts a search and the second one is @c used for this. The first one starts a search and the second one is
@c used to retrieve certificate after certificate. @c used to retrieve certificate after certificate.
@c @c

View File

@ -1630,16 +1630,29 @@ are available for all keyserver types, some common options are:
program uses internally (libcurl, openldap, etc). program uses internally (libcurl, openldap, etc).
@item check-cert @item check-cert
@ifset gpgtwoone
This option has no more function since GnuPG 2.1. Use the
@code{dirmngr} configuration options instead.
@end ifset
@ifclear gpgtwoone
Enable certificate checking if the keyserver presents one (for hkps or Enable certificate checking if the keyserver presents one (for hkps or
ldaps). Defaults to on. ldaps). Defaults to on.
@end ifclear
@item ca-cert-file @item ca-cert-file
@ifset gpgtwoone
This option has no more function since GnuPG 2.1. Use the
@code{dirmngr} configuration options instead.
@end ifset
@ifclear gpgtwoone
Provide a certificate store to override the system default. Only Provide a certificate store to override the system default. Only
necessary if check-cert is enabled, and the keyserver is using a necessary if check-cert is enabled, and the keyserver is using a
certificate that is not present in a system default certificate list. certificate that is not present in a system default certificate list.
Note that depending on the SSL library that the keyserver helper is Note that depending on the SSL library that the keyserver helper is
built with, this may actually be a directory or a file. built with, this may actually be a directory or a file.
@end ifclear
@end table @end table
@item --completes-needed @code{n} @item --completes-needed @code{n}