mirror of
https://github.com/norandom/OpenUltraSAST.git
synced 2026-10-21 05:59:29 +00:00
feat(real-world-vfc-slice): add labeled OpenSSL/Firefox/Chromium/curl pair corpus
Harvest 176 isolated vuln-vs-fix functions (109 CVEs, 352 training rows) into benchmarks/pairs/vfc with provenance and a JSONL training manifest. Score the slice as an honesty dashboard (ousast pairs --slice vfc); keep the pair gate on the local fixtures only.
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
/* Provenance: curl/curl verifystatus (fixed).
|
||||
* repo: curl/curl
|
||||
* commit: d9d01672785b8ac04aab1abb6de95fe3072ae199
|
||||
* parent: 69a358f2186e04cf44698b5100332cbf1ee7f01d
|
||||
* commit_url: https://github.com/curl/curl/commit/d9d01672785b8ac04aab1abb6de95fe3072ae199
|
||||
* cve: CVE-2020-8286
|
||||
* license: curl
|
||||
* function: verifystatus
|
||||
* relpath: lib/vtls/openssl.c
|
||||
*/
|
||||
|
||||
!defined(OPENSSL_NO_OCSP)
|
||||
static CURLcode verifystatus(struct connectdata *conn,
|
||||
struct ssl_connect_data *connssl)
|
||||
{
|
||||
int i, ocsp_status;
|
||||
unsigned char *status;
|
||||
const unsigned char *p;
|
||||
CURLcode result = CURLE_OK;
|
||||
struct Curl_easy *data = conn->data;
|
||||
OCSP_RESPONSE *rsp = NULL;
|
||||
OCSP_BASICRESP *br = NULL;
|
||||
X509_STORE *st = NULL;
|
||||
STACK_OF(X509) *ch = NULL;
|
||||
struct ssl_backend_data *backend = connssl->backend;
|
||||
X509 *cert;
|
||||
OCSP_CERTID *id = NULL;
|
||||
int cert_status, crl_reason;
|
||||
ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
|
||||
int ret;
|
||||
|
||||
long len = SSL_get_tlsext_status_ocsp_resp(backend->handle, &status);
|
||||
|
||||
if(!status) {
|
||||
failf(data, "No OCSP response received");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
p = status;
|
||||
rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
|
||||
if(!rsp) {
|
||||
failf(data, "Invalid OCSP response");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ocsp_status = OCSP_response_status(rsp);
|
||||
if(ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
|
||||
failf(data, "Invalid OCSP response status: %s (%d)",
|
||||
OCSP_response_status_str(ocsp_status), ocsp_status);
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
br = OCSP_response_get1_basic(rsp);
|
||||
if(!br) {
|
||||
failf(data, "Invalid OCSP response");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ch = SSL_get_peer_cert_chain(backend->handle);
|
||||
st = SSL_CTX_get_cert_store(backend->ctx);
|
||||
|
||||
#if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && \
|
||||
LIBRESSL_VERSION_NUMBER <= 0x2040200fL))
|
||||
/* The authorized responder cert in the OCSP response MUST be signed by the
|
||||
peer cert's issuer (see RFC6960 section 4.2.2.2). If that's a root cert,
|
||||
no problem, but if it's an intermediate cert OpenSSL has a bug where it
|
||||
expects this issuer to be present in the chain embedded in the OCSP
|
||||
response. So we add it if necessary. */
|
||||
|
||||
/* First make sure the peer cert chain includes both a peer and an issuer,
|
||||
and the OCSP response contains a responder cert. */
|
||||
if(sk_X509_num(ch) >= 2 && sk_X509_num(br->certs) >= 1) {
|
||||
X509 *responder = sk_X509_value(br->certs, sk_X509_num(br->certs) - 1);
|
||||
|
||||
/* Find issuer of responder cert and add it to the OCSP response chain */
|
||||
for(i = 0; i < sk_X509_num(ch); i++) {
|
||||
X509 *issuer = sk_X509_value(ch, i);
|
||||
if(X509_check_issued(issuer, responder) == X509_V_OK) {
|
||||
if(!OCSP_basic_add1_cert(br, issuer)) {
|
||||
failf(data, "Could not add issuer cert to OCSP response");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(OCSP_basic_verify(br, ch, st, 0) <= 0) {
|
||||
failf(data, "OCSP response verification failed");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Compute the certificate's ID */
|
||||
cert = SSL_get_peer_certificate(backend->handle);
|
||||
if(!cert) {
|
||||
failf(data, "Error getting peer certficate");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
for(i = 0; i < sk_X509_num(ch); i++) {
|
||||
X509 *issuer = sk_X509_value(ch, i);
|
||||
if(X509_check_issued(issuer, cert) == X509_V_OK) {
|
||||
id = OCSP_cert_to_id(EVP_sha1(), cert, issuer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
X509_free(cert);
|
||||
|
||||
if(!id) {
|
||||
failf(data, "Error computing OCSP ID");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Find the single OCSP response corresponding to the certificate ID */
|
||||
ret = OCSP_resp_find_status(br, id, &cert_status, &crl_reason, &rev,
|
||||
&thisupd, &nextupd);
|
||||
OCSP_CERTID_free(id);
|
||||
if(ret != 1) {
|
||||
failf(data, "Could not find certificate ID in OCSP response");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Validate the corresponding single OCSP response */
|
||||
if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
|
||||
failf(data, "OCSP response has expired");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
infof(data, "SSL certificate status: %s (%d)\n",
|
||||
OCSP_cert_status_str(cert_status), cert_status);
|
||||
|
||||
switch(cert_status) {
|
||||
case V_OCSP_CERTSTATUS_GOOD:
|
||||
break;
|
||||
|
||||
case V_OCSP_CERTSTATUS_REVOKED:
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
failf(data, "SSL certificate revocation reason: %s (%d)",
|
||||
OCSP_crl_reason_str(crl_reason), crl_reason);
|
||||
goto end;
|
||||
|
||||
case V_OCSP_CERTSTATUS_UNKNOWN:
|
||||
default:
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
if(br)
|
||||
OCSP_BASICRESP_free(br);
|
||||
OCSP_RESPONSE_free(rsp);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/* Provenance: curl/curl verifystatus (vuln).
|
||||
* repo: curl/curl
|
||||
* commit: 69a358f2186e04cf44698b5100332cbf1ee7f01d
|
||||
* parent: 69a358f2186e04cf44698b5100332cbf1ee7f01d
|
||||
* commit_url: https://github.com/curl/curl/commit/d9d01672785b8ac04aab1abb6de95fe3072ae199
|
||||
* cve: CVE-2020-8286
|
||||
* license: curl
|
||||
* function: verifystatus
|
||||
* relpath: lib/vtls/openssl.c
|
||||
*/
|
||||
|
||||
!defined(OPENSSL_NO_OCSP)
|
||||
static CURLcode verifystatus(struct connectdata *conn,
|
||||
struct ssl_connect_data *connssl)
|
||||
{
|
||||
int i, ocsp_status;
|
||||
unsigned char *status;
|
||||
const unsigned char *p;
|
||||
CURLcode result = CURLE_OK;
|
||||
struct Curl_easy *data = conn->data;
|
||||
OCSP_RESPONSE *rsp = NULL;
|
||||
OCSP_BASICRESP *br = NULL;
|
||||
X509_STORE *st = NULL;
|
||||
STACK_OF(X509) *ch = NULL;
|
||||
struct ssl_backend_data *backend = connssl->backend;
|
||||
|
||||
long len = SSL_get_tlsext_status_ocsp_resp(backend->handle, &status);
|
||||
|
||||
if(!status) {
|
||||
failf(data, "No OCSP response received");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
p = status;
|
||||
rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
|
||||
if(!rsp) {
|
||||
failf(data, "Invalid OCSP response");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ocsp_status = OCSP_response_status(rsp);
|
||||
if(ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
|
||||
failf(data, "Invalid OCSP response status: %s (%d)",
|
||||
OCSP_response_status_str(ocsp_status), ocsp_status);
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
br = OCSP_response_get1_basic(rsp);
|
||||
if(!br) {
|
||||
failf(data, "Invalid OCSP response");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ch = SSL_get_peer_cert_chain(backend->handle);
|
||||
st = SSL_CTX_get_cert_store(backend->ctx);
|
||||
|
||||
#if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && \
|
||||
LIBRESSL_VERSION_NUMBER <= 0x2040200fL))
|
||||
/* The authorized responder cert in the OCSP response MUST be signed by the
|
||||
peer cert's issuer (see RFC6960 section 4.2.2.2). If that's a root cert,
|
||||
no problem, but if it's an intermediate cert OpenSSL has a bug where it
|
||||
expects this issuer to be present in the chain embedded in the OCSP
|
||||
response. So we add it if necessary. */
|
||||
|
||||
/* First make sure the peer cert chain includes both a peer and an issuer,
|
||||
and the OCSP response contains a responder cert. */
|
||||
if(sk_X509_num(ch) >= 2 && sk_X509_num(br->certs) >= 1) {
|
||||
X509 *responder = sk_X509_value(br->certs, sk_X509_num(br->certs) - 1);
|
||||
|
||||
/* Find issuer of responder cert and add it to the OCSP response chain */
|
||||
for(i = 0; i < sk_X509_num(ch); i++) {
|
||||
X509 *issuer = sk_X509_value(ch, i);
|
||||
if(X509_check_issued(issuer, responder) == X509_V_OK) {
|
||||
if(!OCSP_basic_add1_cert(br, issuer)) {
|
||||
failf(data, "Could not add issuer cert to OCSP response");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(OCSP_basic_verify(br, ch, st, 0) <= 0) {
|
||||
failf(data, "OCSP response verification failed");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
for(i = 0; i < OCSP_resp_count(br); i++) {
|
||||
int cert_status, crl_reason;
|
||||
OCSP_SINGLERESP *single = NULL;
|
||||
|
||||
ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
|
||||
|
||||
single = OCSP_resp_get0(br, i);
|
||||
if(!single)
|
||||
continue;
|
||||
|
||||
cert_status = OCSP_single_get0_status(single, &crl_reason, &rev,
|
||||
&thisupd, &nextupd);
|
||||
|
||||
if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
|
||||
failf(data, "OCSP response has expired");
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
|
||||
infof(data, "SSL certificate status: %s (%d)\n",
|
||||
OCSP_cert_status_str(cert_status), cert_status);
|
||||
|
||||
switch(cert_status) {
|
||||
case V_OCSP_CERTSTATUS_GOOD:
|
||||
break;
|
||||
|
||||
case V_OCSP_CERTSTATUS_REVOKED:
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
|
||||
failf(data, "SSL certificate revocation reason: %s (%d)",
|
||||
OCSP_crl_reason_str(crl_reason), crl_reason);
|
||||
goto end;
|
||||
|
||||
case V_OCSP_CERTSTATUS_UNKNOWN:
|
||||
result = CURLE_SSL_INVALIDCERTSTATUS;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if(br)
|
||||
OCSP_BASICRESP_free(br);
|
||||
OCSP_RESPONSE_free(rsp);
|
||||
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user