From 460e3812be711bd18195053d74aa736215f21eee Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Tue, 24 Apr 2018 11:40:51 +0200 Subject: [PATCH] dirmngr: Fallback to CRL if no default OCSP responder is configured. * dirmngr/server.c (cmd_isvalid): Use option second arg to trigger OCSP checkibng. Fallback to CRL if no default OCSP responder has been configured. * sm/call-dirmngr.c (gpgsm_dirmngr_isvalid): Adjust accordingly. Signed-off-by: Werner Koch --- dirmngr/server.c | 65 ++++++++++++++++++++++++++++++----------------- sm/call-dirmngr.c | 41 +++++++++++++----------------- 2 files changed, 59 insertions(+), 47 deletions(-) diff --git a/dirmngr/server.c b/dirmngr/server.c index 4315c4133..48244d4af 100644 --- a/dirmngr/server.c +++ b/dirmngr/server.c @@ -1105,7 +1105,7 @@ cmd_ldapserver (assuan_context_t ctx, char *line) static const char hlp_isvalid[] = "ISVALID [--only-ocsp] [--force-default-responder]" - " |\n" + " []\n" "\n" "This command checks whether the certificate identified by the\n" "certificate_id is valid. This is done by consulting CRLs or\n" @@ -1117,8 +1117,9 @@ static const char hlp_isvalid[] = "delimited by a single dot. The first part is the SHA-1 hash of the\n" "issuer name and the second part the serial number.\n" "\n" - "Alternatively the certificate's fingerprint may be given in which\n" - "case an OCSP request is done before consulting the CRL.\n" + "If an OCSP check is desired CERTIFICATE_FPR with the hex encoded\n" + "fingerprint of the certificate is required. In this case an OCSP\n" + "request is done before consulting the CRL.\n" "\n" "If the option --only-ocsp is given, no fallback to a CRL check will\n" "be used.\n" @@ -1130,7 +1131,7 @@ static gpg_error_t cmd_isvalid (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); - char *issuerhash, *serialno; + char *issuerhash, *serialno, *fpr; gpg_error_t err; int did_inquire = 0; int ocsp_mode = 0; @@ -1141,25 +1142,36 @@ cmd_isvalid (assuan_context_t ctx, char *line) force_default_responder = has_option (line, "--force-default-responder"); line = skip_options (line); - issuerhash = xstrdup (line); /* We need to work on a copy of the - line because that same Assuan - context may be used for an inquiry. - That is because Assuan reuses its - line buffer. - */ + /* We need to work on a copy of the line because that same Assuan + * context may be used for an inquiry. That is because Assuan + * reuses its line buffer. */ + issuerhash = xstrdup (line); serialno = strchr (issuerhash, '.'); - if (serialno) - *serialno++ = 0; - else + if (!serialno) { - char *endp = strchr (issuerhash, ' '); + xfree (issuerhash); + return leave_cmd (ctx, PARM_ERROR (_("serialno missing in cert ID"))); + } + *serialno++ = 0; + if (strlen (issuerhash) != 40) + { + xfree (issuerhash); + return leave_cmd (ctx, PARM_ERROR ("cert ID is too short")); + } + + fpr = strchr (serialno, ' '); + while (fpr && spacep (fpr)) + fpr++; + if (fpr && *fpr) + { + char *endp = strchr (fpr, ' '); if (endp) *endp = 0; - if (strlen (issuerhash) != 40) + if (strlen (fpr) != 40) { xfree (issuerhash); - return leave_cmd (ctx, PARM_ERROR (_("serialno missing in cert ID"))); + return leave_cmd (ctx, PARM_ERROR ("fingerprint too short")); } ocsp_mode = 1; } @@ -1168,17 +1180,24 @@ cmd_isvalid (assuan_context_t ctx, char *line) again: if (ocsp_mode) { - /* Note, that we ignore the given issuer hash and instead rely - on the current certificate semantics used with this - command. */ + /* Note, that we currently ignore the supplied fingerprint FPR; + * instead ocsp_isvalid does an inquire to ask for the cert. + * The fingerprint may eventually be used to lookup the + * certificate in a local cache. */ if (!opt.allow_ocsp) err = gpg_error (GPG_ERR_NOT_SUPPORTED); else err = ocsp_isvalid (ctrl, NULL, NULL, force_default_responder); - /* Fixme: If we got no ocsp response and --only-ocsp is not used - we should fall back to CRL mode. Thus we need to clear - OCSP_MODE, get the issuerhash and the serialno from the - current certificate and jump to again. */ + + if (gpg_err_code (err) == GPG_ERR_CONFIGURATION + && gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR) + { + /* No default responder configured - fallback to CRL. */ + if (!only_ocsp) + log_info ("falling back to CRL check\n"); + ocsp_mode = 0; + goto again; + } } else if (only_ocsp) err = gpg_error (GPG_ERR_NO_CRL_KNOWN); diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index e94311892..3a38bca50 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -491,8 +491,8 @@ isvalid_status_cb (void *opaque, const char *line) Values for USE_OCSP: 0 = Do CRL check. - 1 = Do an OCSP check. - 2 = Do an OCSP check using only the default responder. + 1 = Do an OCSP check but fallback to CRL unless CRLS are disabled. + 2 = Do only an OCSP check using only the default responder. */ int gpgsm_dirmngr_isvalid (ctrl_t ctrl, @@ -500,7 +500,7 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl, { static int did_options; int rc; - char *certid; + char *certid, *certfpr; char line[ASSUAN_LINELENGTH]; struct inq_certificate_parm_s parm; struct isvalid_status_parm_s stparm; @@ -509,19 +509,13 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl, if (rc) return rc; - if (use_ocsp) + certfpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); + certid = gpgsm_get_certid (cert); + if (!certid) { - certid = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); - } - else - { - certid = gpgsm_get_certid (cert); - if (!certid) - { - log_error ("error getting the certificate ID\n"); - release_dirmngr (ctrl); - return gpg_error (GPG_ERR_GENERAL); - } + log_error ("error getting the certificate ID\n"); + release_dirmngr (ctrl); + return gpg_error (GPG_ERR_GENERAL); } if (opt.verbose > 1) @@ -541,13 +535,8 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl, stparm.seen = 0; memset (stparm.fpr, 0, 20); - /* FIXME: If --disable-crl-checks has been set, we should pass an - option to dirmngr, so that no fallback CRL check is done after an - ocsp check. It is not a problem right now as dirmngr does not - fallback to CRL checking. */ - /* It is sufficient to send the options only once because we have - one connection per process only. */ + * one connection per process only. */ if (!did_options) { if (opt.force_crl_refresh) @@ -555,10 +544,14 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl, NULL, NULL, NULL, NULL, NULL, NULL); did_options = 1; } - snprintf (line, DIM(line), "ISVALID%s %s", - use_ocsp == 2? " --only-ocsp --force-default-responder":"", - certid); + snprintf (line, DIM(line), "ISVALID%s%s %s%s%s", + use_ocsp == 2 || opt.no_crl_check ? " --only-ocsp":"", + use_ocsp == 2? " --force-default-responder":"", + certid, + use_ocsp? " ":"", + use_ocsp? certfpr:""); xfree (certid); + xfree (certfpr); rc = assuan_transact (dirmngr_ctx, line, NULL, NULL, inq_certificate, &parm,