From 7fa1d3cc821dca1ea8e1c80a0bdd527177c185ee Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Mon, 5 Dec 2022 14:25:04 +0100 Subject: [PATCH] gpgsm: Always use the chain model if the root-CA requests this. * sm/call-dirmngr.c (gpgsm_dirmngr_isvalid): Do not use option --force-default-responder. * sm/certchain.c (is_cert_still_valid): Rename arg for clarity. (gpgsm_validate_chain): Always switch to chain model. -- The trustlist.txt may indicate that a root CA issues certificates which shall be validated using the chain model. This is for example the case for qualified signatures. Before this change we did this only if the default shell model indicated that a certificate has expired. This optimization is technically okay but has one problem: The chain model requires the use of OCSP but we switch to this only when running the chain model validation. To catch revoked certificates using OCSP we need to always switch to the chain model unless OCSP has been enabled anyway. Note that the old --force-default-responder option is not anymore used. Test cases are certificates issued by # CN=TeleSec qualified Root CA 1 # O=Deutsche Telekom AG # C=DE # 2.5.4.97=USt-IdNr. DE 123475223 90:C6:13:6C:7D:EF:EF:E9:7C:C7:64:F9:D2:67:8E:AD:03:E5:52:96 \ S cm qual relax A sample revoked certificate is -----BEGIN CERTIFICATE----- MIIDTzCCAvSgAwIBAgIQIXfquQjq32B03CdaflIbiDAMBggqhkjOPQQDAgUAMHEx CzAJBgNVBAYTAkRFMRwwGgYDVQQKDBNEZXV0c2NoZSBUZWxla29tIEFHMSMwIQYD VQQDDBpUZWxlU2VjIFBLUyBlSURBUyBRRVMgQ0EgMTEfMB0GA1UEYQwWVVN0LUlk TnIuIERFIDEyMzQ3NTIyMzAeFw0yMDA2MjIxMDQ1NDJaFw0yMzA2MjUyMzU5MDBa MDAxCzAJBgNVBAYTAkRFMRUwEwYDVQQDDAxLb2NoLCBXZXJuZXIxCjAIBgNVBAUT ATMwWjAUBgcqhkjOPQIBBgkrJAMDAggBAQcDQgAEbkEXUuXTriWOwqQhjlh11oCc 6Z8lQdQDz3zY/OEh8fMJS7AKBNo8zkpPKDJ2olPph18b1goEbLiqHQsPRPahDaOC AaowggGmMB8GA1UdIwQYMBaAFP/0iep1rMXT0iQ0+WUqBvLM6bqBMB0GA1UdDgQW BBQEI3xsIUDnoOx+gLYbG63v5/f9kjAOBgNVHQ8BAf8EBAMCBkAwDAYDVR0TAQH/ BAIwADAgBgNVHREEGTAXgRV3ZXJuZXIua29jaEBnbnVwZy5jb20wPQYDVR0gBDYw NDAyBgcEAIvsQAECMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly9wa3MudGVsZXNlYy5k ZS9jcHMwgYQGCCsGAQUFBwEBBHgwdjBLBggrBgEFBQcwAoY/aHR0cDovL3RxcmNh MS5wa2kudGVsZXNlYy5kZS9jcnQvVGVsZVNlY19QS1NfZUlEQVNfUUVTX0NBXzEu Y3J0MCcGCCsGAQUFBzABhhtodHRwOi8vcGtzLnRlbGVzZWMuZGUvb2NzcHIwXgYI KwYBBQUHAQMEUjBQMAgGBgQAjkYBATAIBgYEAI5GAQQwOgYGBACORgEFMDAwLhYo aHR0cHM6Ly93d3cudGVsZXNlYy5kZS9zaWduYXR1cmthcnRlL2FnYhMCZW4wDAYI KoZIzj0EAwIFAANHADBEAiAqgB8gyZyj05CRdHD5KJcpG68DzQECYnYP6ZPasUYK AQIgI1GtRMJWvFTIKsZpgY+ty0pRb5/K09fbmvaSAKFpv/I= -----END CERTIFICATE----- --- doc/gpg.texi | 2 +- sm/call-dirmngr.c | 11 +++++------ sm/certchain.c | 14 ++++++++------ sm/gpgsm.h | 6 +++--- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/doc/gpg.texi b/doc/gpg.texi index 1a3cb9e25..466baf3bf 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -1341,7 +1341,7 @@ Assume "no" on most questions. Should not be used in an option file. @item --list-filter @{select=@var{expr}@} @opindex list-filter A list filter can be used to output only certain keys during key -listsin command. For the availbale property names, see the description +listing commands. For the available property names, see the description of @option{--import-filter}. diff --git a/sm/call-dirmngr.c b/sm/call-dirmngr.c index 5dd8a3938..a15ff240d 100644 --- a/sm/call-dirmngr.c +++ b/sm/call-dirmngr.c @@ -510,10 +510,10 @@ isvalid_status_cb (void *opaque, const char *line) Values for USE_OCSP: 0 = Do CRL check. - 1 = Do an OCSP check but fallback to CRL unless CRLS are disabled. - 2 = Do only 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 (used for the chain model). */ -int +gpg_error_t gpgsm_dirmngr_isvalid (ctrl_t ctrl, ksba_cert_t cert, ksba_cert_t issuer_cert, int use_ocsp) { @@ -563,9 +563,8 @@ gpgsm_dirmngr_isvalid (ctrl_t ctrl, NULL, NULL, NULL, NULL, NULL, NULL); did_options = 1; } - 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":"", + snprintf (line, DIM(line), "ISVALID%s %s%s%s", + (use_ocsp == 2 || opt.no_crl_check) ? " --only-ocsp":"", certid, use_ocsp? " ":"", use_ocsp? certfpr:""); diff --git a/sm/certchain.c b/sm/certchain.c index 4050680e8..ca03a766f 100644 --- a/sm/certchain.c +++ b/sm/certchain.c @@ -1187,7 +1187,7 @@ gpgsm_is_root_cert (ksba_cert_t cert) /* This is a helper for gpgsm_validate_chain. */ static gpg_error_t -is_cert_still_valid (ctrl_t ctrl, int force_ocsp, int lm, estream_t fp, +is_cert_still_valid (ctrl_t ctrl, int chain_model, int lm, estream_t fp, ksba_cert_t subject_cert, ksba_cert_t issuer_cert, int *any_revoked, int *any_no_crl, int *any_crl_too_old) { @@ -1201,7 +1201,7 @@ is_cert_still_valid (ctrl_t ctrl, int force_ocsp, int lm, estream_t fp, } - if (!(force_ocsp || ctrl->use_ocsp) + if (!(chain_model || ctrl->use_ocsp) && !opt.enable_issuer_based_crl_check) { err = ksba_cert_get_crl_dist_point (subject_cert, 0, NULL, NULL, NULL); @@ -1220,7 +1220,7 @@ is_cert_still_valid (ctrl_t ctrl, int force_ocsp, int lm, estream_t fp, err = gpgsm_dirmngr_isvalid (ctrl, subject_cert, issuer_cert, - force_ocsp? 2 : !!ctrl->use_ocsp); + chain_model? 2 : !!ctrl->use_ocsp); audit_log_ok (ctrl->audit, AUDIT_CRL_CHECK, err); if (err) @@ -2158,10 +2158,12 @@ gpgsm_validate_chain (ctrl_t ctrl, ksba_cert_t cert, ksba_isotime_t checktime, { *retflags |= VALIDATE_FLAG_STEED; } - else if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED - && !(flags & VALIDATE_FLAG_CHAIN_MODEL) - && (rootca_flags.valid && rootca_flags.chain_model)) + else if (!(flags & VALIDATE_FLAG_CHAIN_MODEL) + && (rootca_flags.valid && rootca_flags.chain_model)) { + /* The root CA indicated that the chain model is to be used but + * we have not yet used it. Thus do the validation again using + * the chain model. */ do_list (0, listmode, listfp, _("switching to chain model")); rc = do_validate_chain (ctrl, cert, checktime, r_exptime, listmode, listfp, diff --git a/sm/gpgsm.h b/sm/gpgsm.h index 9fbb53a29..b0ed8891c 100644 --- a/sm/gpgsm.h +++ b/sm/gpgsm.h @@ -494,9 +494,9 @@ gpg_error_t gpgsm_agent_export_key (ctrl_t ctrl, const char *keygrip, size_t *r_resultlen); /*-- call-dirmngr.c --*/ -int gpgsm_dirmngr_isvalid (ctrl_t ctrl, - ksba_cert_t cert, ksba_cert_t issuer_cert, - int use_ocsp); +gpg_error_t gpgsm_dirmngr_isvalid (ctrl_t ctrl, + ksba_cert_t cert, ksba_cert_t issuer_cert, + int use_ocsp); int gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, const char *uri, int cache_only, void (*cb)(void*, ksba_cert_t), void *cb_value);