diff options
author | Werner Koch <[email protected]> | 2017-02-17 15:39:48 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2017-02-17 15:41:02 +0000 |
commit | 070211eb990f5ea41271eba432b6a6b485cef7c7 (patch) | |
tree | df547fb8197e445666906f4a0ee5f37fda512e9d /dirmngr/server.c | |
parent | dirmngr: Remove use of hardcoded numbers in validate. (diff) | |
download | gnupg-070211eb990f5ea41271eba432b6a6b485cef7c7.tar.gz gnupg-070211eb990f5ea41271eba432b6a6b485cef7c7.zip |
dirmngr: Add options --tls and --systrust to the VALIDATE cmd.
* dirmngr/certcache.h (certlist_s, certlist_t): New.
* dirmngr/certcache.c (read_certlist_from_stream): New.
(release_certlist): New.
* dirmngr/server.c (MAX_CERTLIST_LENGTH): New.
(cmd_validate): Add options --tls and --systrust. Implement them
using a kludge for now.
* dirmngr/validate.c (validate_cert_chain): Support systrust
checking. Add kludge to disable the CRL checking for tls mode.
--
This can now be used to test a list of certificates as returned by
TLS. Put the certs PEM encoded into a a file certlist.pem with the
target certificate being the first. Then run
gpg-connect-agent --dirmngr \
'/definqfile CERTLIST wiki-gnupg-chain.pem' \
'validate --systrust --tls' /bye
CRLS check has been disabled becuase we can't yet pass the systrust
flag to the CRL checking code.
Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'dirmngr/server.c')
-rw-r--r-- | dirmngr/server.c | 104 |
1 files changed, 84 insertions, 20 deletions
diff --git a/dirmngr/server.c b/dirmngr/server.c index bc373f5b0..05ef439a1 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -60,6 +60,10 @@ Dirmngr was a system service and not a user service. */ #define MAX_CERT_LENGTH (16*1024) +/* The limit for the CERTLIST inquiry. We allow for up to 20 + * certificates but also take PEM encoding into account. */ +#define MAX_CERTLIST_LENGTH ((MAX_CERT_LENGTH * 20 * 4)/3) + /* The same goes for OpenPGP keyblocks, but here we need to allow for much longer blocks; a 200k keyblock is not too unusual for keys with a lot of signatures (e.g. 0x5b0358a2). 9C31503C6D866396 even @@ -1729,7 +1733,7 @@ cmd_cachecert (assuan_context_t ctx, char *line) static const char hlp_validate[] = - "VALIDATE\n" + "VALIDATE [--systrust] [--tls]\n" "\n" "Validate a certificate using the certificate validation function\n" "used internally by dirmngr. This command is only useful for\n" @@ -1739,20 +1743,38 @@ static const char hlp_validate[] = " INQUIRE TARGETCERT\n" "\n" "and the caller is expected to return the certificate for the\n" - "request as a binary blob."; + "request as a binary blob. The option --tls modifies this by asking\n" + "for list of certificates with\n" + "\n" + " INQUIRE CERTLIST\n" + "\n" + "Here the first certificate is the target certificate, the remaining\n" + "certificates are suggested intermediary certificates. All certifciates\n" + "need to be PEM encoded.\n" + "\n" + "The option --systrust changes the behaviour to include the system\n" + "provided root certificates as trust anchors."; static gpg_error_t cmd_validate (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); gpg_error_t err; ksba_cert_t cert = NULL; + certlist_t certlist = NULL; unsigned char *value = NULL; size_t valuelen; + int systrust_mode, tls_mode; - (void)line; + systrust_mode = has_option (line, "--systrust"); + tls_mode = has_option (line, "--tls"); + line = skip_options (line); - err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT", - &value, &valuelen, MAX_CERT_LENGTH); + if (tls_mode) + err = assuan_inquire (ctrl->server_local->assuan_ctx, "CERTLIST", + &value, &valuelen, MAX_CERTLIST_LENGTH); + else + err = assuan_inquire (ctrl->server_local->assuan_ctx, "TARGETCERT", + &value, &valuelen, MAX_CERT_LENGTH); if (err) { log_error (_("assuan_inquire failed: %s\n"), gpg_strerror (err)); @@ -1761,6 +1783,27 @@ cmd_validate (assuan_context_t ctx, char *line) if (!valuelen) /* No data returned; return a comprehensible error. */ err = gpg_error (GPG_ERR_MISSING_CERT); + else if (tls_mode) + { + estream_t fp; + + fp = es_fopenmem_init (0, "rb", value, valuelen); + if (!fp) + err = gpg_error_from_syserror (); + else + { + err = read_certlist_from_stream (&certlist, fp); + es_fclose (fp); + if (!err && !certlist) + err = gpg_error (GPG_ERR_MISSING_CERT); + if (!err) + { + /* Extraxt the first certificate from the list. */ + cert = certlist->cert; + ksba_cert_ref (cert); + } + } + } else { err = ksba_cert_new (&cert); @@ -1771,26 +1814,47 @@ cmd_validate (assuan_context_t ctx, char *line) if(err) goto leave; - /* If we have this certificate already in our cache, use the cached - * version for validation because this will take care of any cached - * results. */ - { - unsigned char fpr[20]; - ksba_cert_t tmpcert; + if (!tls_mode) + { + /* If we have this certificate already in our cache, use the + * cached version for validation because this will take care of + * any cached results. We don't need to do this in tls mode + * because this has already been done for certificate in a + * certlist_t. */ + unsigned char fpr[20]; + ksba_cert_t tmpcert; + + cert_compute_fpr (cert, fpr); + tmpcert = get_cert_byfpr (fpr); + if (tmpcert) + { + ksba_cert_release (cert); + cert = tmpcert; + } + } + + /* Quick hack to make verification work by inserting the supplied + * certs into the cache. */ + if (tls_mode && certlist) + { + certlist_t cl; + + for (cl = certlist->next; cl; cl = cl->next) + cache_cert (cl->cert); + } - cert_compute_fpr (cert, fpr); - tmpcert = get_cert_byfpr (fpr); - if (tmpcert) - { - ksba_cert_release (cert); - cert = tmpcert; - } - } - err = validate_cert_chain (ctrl, cert, NULL, VALIDATE_MODE_CERT, NULL); + err = validate_cert_chain + (ctrl, cert, NULL, + tls_mode && systrust_mode ? VALIDATE_MODE_TLS_SYSTRUST : + tls_mode ? VALIDATE_MODE_TLS : + /**/ systrust_mode ? VALIDATE_MODE_CERT_SYSTRUST : + /**/ VALIDATE_MODE_CERT, + NULL); leave: ksba_cert_release (cert); + release_certlist (certlist); return leave_cmd (ctx, err); } |