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 <wk@gnupg.org>
This commit is contained in:
Werner Koch 2018-04-24 11:40:51 +02:00
parent d2ad715441
commit 460e3812be
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 59 additions and 47 deletions

View File

@ -1105,7 +1105,7 @@ cmd_ldapserver (assuan_context_t ctx, char *line)
static const char hlp_isvalid[] = static const char hlp_isvalid[] =
"ISVALID [--only-ocsp] [--force-default-responder]" "ISVALID [--only-ocsp] [--force-default-responder]"
" <certificate_id>|<certificate_fpr>\n" " <certificate_id> [<certificate_fpr>]\n"
"\n" "\n"
"This command checks whether the certificate identified by the\n" "This command checks whether the certificate identified by the\n"
"certificate_id is valid. This is done by consulting CRLs or\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" "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" "issuer name and the second part the serial number.\n"
"\n" "\n"
"Alternatively the certificate's fingerprint may be given in which\n" "If an OCSP check is desired CERTIFICATE_FPR with the hex encoded\n"
"case an OCSP request is done before consulting the CRL.\n" "fingerprint of the certificate is required. In this case an OCSP\n"
"request is done before consulting the CRL.\n"
"\n" "\n"
"If the option --only-ocsp is given, no fallback to a CRL check will\n" "If the option --only-ocsp is given, no fallback to a CRL check will\n"
"be used.\n" "be used.\n"
@ -1130,7 +1131,7 @@ static gpg_error_t
cmd_isvalid (assuan_context_t ctx, char *line) cmd_isvalid (assuan_context_t ctx, char *line)
{ {
ctrl_t ctrl = assuan_get_pointer (ctx); ctrl_t ctrl = assuan_get_pointer (ctx);
char *issuerhash, *serialno; char *issuerhash, *serialno, *fpr;
gpg_error_t err; gpg_error_t err;
int did_inquire = 0; int did_inquire = 0;
int ocsp_mode = 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"); force_default_responder = has_option (line, "--force-default-responder");
line = skip_options (line); line = skip_options (line);
issuerhash = xstrdup (line); /* We need to work on a copy of the /* We need to work on a copy of the line because that same Assuan
line because that same Assuan * context may be used for an inquiry. That is because Assuan
context may be used for an inquiry. * reuses its line buffer. */
That is because Assuan reuses its issuerhash = xstrdup (line);
line buffer.
*/
serialno = strchr (issuerhash, '.'); serialno = strchr (issuerhash, '.');
if (serialno) if (!serialno)
*serialno++ = 0;
else
{ {
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) if (endp)
*endp = 0; *endp = 0;
if (strlen (issuerhash) != 40) if (strlen (fpr) != 40)
{ {
xfree (issuerhash); 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; ocsp_mode = 1;
} }
@ -1168,17 +1180,24 @@ cmd_isvalid (assuan_context_t ctx, char *line)
again: again:
if (ocsp_mode) if (ocsp_mode)
{ {
/* Note, that we ignore the given issuer hash and instead rely /* Note, that we currently ignore the supplied fingerprint FPR;
on the current certificate semantics used with this * instead ocsp_isvalid does an inquire to ask for the cert.
command. */ * The fingerprint may eventually be used to lookup the
* certificate in a local cache. */
if (!opt.allow_ocsp) if (!opt.allow_ocsp)
err = gpg_error (GPG_ERR_NOT_SUPPORTED); err = gpg_error (GPG_ERR_NOT_SUPPORTED);
else else
err = ocsp_isvalid (ctrl, NULL, NULL, force_default_responder); 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 if (gpg_err_code (err) == GPG_ERR_CONFIGURATION
OCSP_MODE, get the issuerhash and the serialno from the && gpg_err_source (err) == GPG_ERR_SOURCE_DIRMNGR)
current certificate and jump to again. */ {
/* 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) else if (only_ocsp)
err = gpg_error (GPG_ERR_NO_CRL_KNOWN); err = gpg_error (GPG_ERR_NO_CRL_KNOWN);

View File

@ -491,8 +491,8 @@ isvalid_status_cb (void *opaque, const char *line)
Values for USE_OCSP: Values for USE_OCSP:
0 = Do CRL check. 0 = Do CRL check.
1 = Do an OCSP check. 1 = Do an OCSP check but fallback to CRL unless CRLS are disabled.
2 = Do an OCSP check using only the default responder. 2 = Do only an OCSP check using only the default responder.
*/ */
int int
gpgsm_dirmngr_isvalid (ctrl_t ctrl, gpgsm_dirmngr_isvalid (ctrl_t ctrl,
@ -500,7 +500,7 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
{ {
static int did_options; static int did_options;
int rc; int rc;
char *certid; char *certid, *certfpr;
char line[ASSUAN_LINELENGTH]; char line[ASSUAN_LINELENGTH];
struct inq_certificate_parm_s parm; struct inq_certificate_parm_s parm;
struct isvalid_status_parm_s stparm; struct isvalid_status_parm_s stparm;
@ -509,19 +509,13 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
if (rc) if (rc)
return 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); log_error ("error getting the certificate ID\n");
} release_dirmngr (ctrl);
else return gpg_error (GPG_ERR_GENERAL);
{
certid = gpgsm_get_certid (cert);
if (!certid)
{
log_error ("error getting the certificate ID\n");
release_dirmngr (ctrl);
return gpg_error (GPG_ERR_GENERAL);
}
} }
if (opt.verbose > 1) if (opt.verbose > 1)
@ -541,13 +535,8 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
stparm.seen = 0; stparm.seen = 0;
memset (stparm.fpr, 0, 20); 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 /* 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 (!did_options)
{ {
if (opt.force_crl_refresh) if (opt.force_crl_refresh)
@ -555,10 +544,14 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl,
NULL, NULL, NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL, NULL, NULL);
did_options = 1; did_options = 1;
} }
snprintf (line, DIM(line), "ISVALID%s %s", snprintf (line, DIM(line), "ISVALID%s%s %s%s%s",
use_ocsp == 2? " --only-ocsp --force-default-responder":"", use_ocsp == 2 || opt.no_crl_check ? " --only-ocsp":"",
certid); use_ocsp == 2? " --force-default-responder":"",
certid,
use_ocsp? " ":"",
use_ocsp? certfpr:"");
xfree (certid); xfree (certid);
xfree (certfpr);
rc = assuan_transact (dirmngr_ctx, line, NULL, NULL, rc = assuan_transact (dirmngr_ctx, line, NULL, NULL,
inq_certificate, &parm, inq_certificate, &parm,