gtls: fix OCSP stapling management

Reported-by: Hiroki Kurosawa
Closes #14642
This commit is contained in:
Daniel Stenberg 2024-08-20 16:14:39 +02:00
parent c730c8549b
commit aeb1a281ca
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2

View file

@ -850,6 +850,13 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf,
init_flags |= GNUTLS_NO_TICKETS; init_flags |= GNUTLS_NO_TICKETS;
#endif #endif
#if defined(GNUTLS_NO_STATUS_REQUEST)
if(!config->verifystatus)
/* Disable the "status_request" TLS extension, enabled by default since
GnuTLS 3.8.0. */
init_flags |= GNUTLS_NO_STATUS_REQUEST;
#endif
rc = gnutls_init(&gtls->session, init_flags); rc = gnutls_init(&gtls->session, init_flags);
if(rc != GNUTLS_E_SUCCESS) { if(rc != GNUTLS_E_SUCCESS) {
failf(data, "gnutls_init() failed: %d", rc); failf(data, "gnutls_init() failed: %d", rc);
@ -1321,104 +1328,97 @@ Curl_gtls_verifyserver(struct Curl_easy *data,
infof(data, " server certificate verification SKIPPED"); infof(data, " server certificate verification SKIPPED");
if(config->verifystatus) { if(config->verifystatus) {
if(gnutls_ocsp_status_request_is_checked(session, 0) == 0) { gnutls_datum_t status_request;
gnutls_datum_t status_request; gnutls_ocsp_resp_t ocsp_resp;
gnutls_ocsp_resp_t ocsp_resp; gnutls_ocsp_cert_status_t status;
gnutls_x509_crl_reason_t reason;
gnutls_ocsp_cert_status_t status; rc = gnutls_ocsp_status_request_get(session, &status_request);
gnutls_x509_crl_reason_t reason;
rc = gnutls_ocsp_status_request_get(session, &status_request);
infof(data, " server certificate status verification FAILED");
if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
failf(data, "No OCSP response received");
return CURLE_SSL_INVALIDCERTSTATUS;
}
if(rc < 0) {
failf(data, "Invalid OCSP response received");
return CURLE_SSL_INVALIDCERTSTATUS;
}
gnutls_ocsp_resp_init(&ocsp_resp);
rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
if(rc < 0) {
failf(data, "Invalid OCSP response received");
return CURLE_SSL_INVALIDCERTSTATUS;
}
(void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
&status, NULL, NULL, NULL, &reason);
switch(status) {
case GNUTLS_OCSP_CERT_GOOD:
break;
case GNUTLS_OCSP_CERT_REVOKED: {
const char *crl_reason;
switch(reason) {
default:
case GNUTLS_X509_CRLREASON_UNSPECIFIED:
crl_reason = "unspecified reason";
break;
case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
crl_reason = "private key compromised";
break;
case GNUTLS_X509_CRLREASON_CACOMPROMISE:
crl_reason = "CA compromised";
break;
case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
crl_reason = "affiliation has changed";
break;
case GNUTLS_X509_CRLREASON_SUPERSEDED:
crl_reason = "certificate superseded";
break;
case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
crl_reason = "operation has ceased";
break;
case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
crl_reason = "certificate is on hold";
break;
case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
crl_reason = "will be removed from delta CRL";
break;
case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
crl_reason = "privilege withdrawn";
break;
case GNUTLS_X509_CRLREASON_AACOMPROMISE:
crl_reason = "AA compromised";
break;
}
failf(data, "Server certificate was revoked: %s", crl_reason);
break;
}
default:
case GNUTLS_OCSP_CERT_UNKNOWN:
failf(data, "Server certificate status is unknown");
break;
}
gnutls_ocsp_resp_deinit(ocsp_resp);
if(rc == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
failf(data, "No OCSP response received");
return CURLE_SSL_INVALIDCERTSTATUS; return CURLE_SSL_INVALIDCERTSTATUS;
} }
else
infof(data, " server certificate status verification OK"); if(rc < 0) {
failf(data, "Invalid OCSP response received");
return CURLE_SSL_INVALIDCERTSTATUS;
}
gnutls_ocsp_resp_init(&ocsp_resp);
rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request);
if(rc < 0) {
failf(data, "Invalid OCSP response received");
return CURLE_SSL_INVALIDCERTSTATUS;
}
(void)gnutls_ocsp_resp_get_single(ocsp_resp, 0, NULL, NULL, NULL, NULL,
&status, NULL, NULL, NULL, &reason);
switch(status) {
case GNUTLS_OCSP_CERT_GOOD:
break;
case GNUTLS_OCSP_CERT_REVOKED: {
const char *crl_reason;
switch(reason) {
default:
case GNUTLS_X509_CRLREASON_UNSPECIFIED:
crl_reason = "unspecified reason";
break;
case GNUTLS_X509_CRLREASON_KEYCOMPROMISE:
crl_reason = "private key compromised";
break;
case GNUTLS_X509_CRLREASON_CACOMPROMISE:
crl_reason = "CA compromised";
break;
case GNUTLS_X509_CRLREASON_AFFILIATIONCHANGED:
crl_reason = "affiliation has changed";
break;
case GNUTLS_X509_CRLREASON_SUPERSEDED:
crl_reason = "certificate superseded";
break;
case GNUTLS_X509_CRLREASON_CESSATIONOFOPERATION:
crl_reason = "operation has ceased";
break;
case GNUTLS_X509_CRLREASON_CERTIFICATEHOLD:
crl_reason = "certificate is on hold";
break;
case GNUTLS_X509_CRLREASON_REMOVEFROMCRL:
crl_reason = "will be removed from delta CRL";
break;
case GNUTLS_X509_CRLREASON_PRIVILEGEWITHDRAWN:
crl_reason = "privilege withdrawn";
break;
case GNUTLS_X509_CRLREASON_AACOMPROMISE:
crl_reason = "AA compromised";
break;
}
failf(data, "Server certificate was revoked: %s", crl_reason);
break;
}
default:
case GNUTLS_OCSP_CERT_UNKNOWN:
failf(data, "Server certificate status is unknown");
break;
}
gnutls_ocsp_resp_deinit(ocsp_resp);
if(status != GNUTLS_OCSP_CERT_GOOD)
return CURLE_SSL_INVALIDCERTSTATUS;
} }
else else
infof(data, " server certificate status verification SKIPPED"); infof(data, " server certificate status verification SKIPPED");