Blame SOURCES/0027-curl-7.61.1-CVE-2020-8286.patch

1a95c1
From 2470bc91f62cc9b0ab1deac60a67f87b7cc95f6e Mon Sep 17 00:00:00 2001
1a95c1
From: Daniel Stenberg <daniel@haxx.se>
1a95c1
Date: Wed, 2 Dec 2020 23:01:11 +0100
1a95c1
Subject: [PATCH] openssl: make the OCSP verification verify the certificate id
1a95c1
1a95c1
CVE-2020-8286
1a95c1
1a95c1
Reported by anonymous
1a95c1
1a95c1
Bug: https://curl.se/docs/CVE-2020-8286.html
1a95c1
1a95c1
Upstream-commit: d9d01672785b8ac04aab1abb6de95fe3072ae199
1a95c1
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
1a95c1
---
1a95c1
 lib/vtls/openssl.c | 83 ++++++++++++++++++++++++++++++----------------
1a95c1
 1 file changed, 54 insertions(+), 29 deletions(-)
1a95c1
1a95c1
diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c
1a95c1
index 9476773..35cd652 100644
1a95c1
--- a/lib/vtls/openssl.c
1a95c1
+++ b/lib/vtls/openssl.c
1a95c1
@@ -1659,6 +1659,11 @@ static CURLcode verifystatus(struct connectdata *conn,
1a95c1
   OCSP_BASICRESP *br = NULL;
1a95c1
   X509_STORE     *st = NULL;
1a95c1
   STACK_OF(X509) *ch = NULL;
1a95c1
+  X509 *cert;
1a95c1
+  OCSP_CERTID *id = NULL;
1a95c1
+  int cert_status, crl_reason;
1a95c1
+  ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
1a95c1
+  int ret;
1a95c1
 
1a95c1
   long len = SSL_get_tlsext_status_ocsp_resp(BACKEND->handle, &p);
1a95c1
 
1a95c1
@@ -1727,43 +1732,63 @@ static CURLcode verifystatus(struct connectdata *conn,
1a95c1
     goto end;
1a95c1
   }
1a95c1
 
1a95c1
-  for(i = 0; i < OCSP_resp_count(br); i++) {
1a95c1
-    int cert_status, crl_reason;
1a95c1
-    OCSP_SINGLERESP *single = NULL;
1a95c1
-
1a95c1
-    ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
1a95c1
+  /* Compute the certificate's ID */
1a95c1
+  cert = SSL_get_peer_certificate(BACKEND->handle);
1a95c1
+  if(!cert) {
1a95c1
+    failf(data, "Error getting peer certficate");
1a95c1
+    result = CURLE_SSL_INVALIDCERTSTATUS;
1a95c1
+    goto end;
1a95c1
+  }
1a95c1
 
1a95c1
-    single = OCSP_resp_get0(br, i);
1a95c1
-    if(!single)
1a95c1
-      continue;
1a95c1
+  for(i = 0; i < sk_X509_num(ch); i++) {
1a95c1
+    X509 *issuer = sk_X509_value(ch, i);
1a95c1
+    if(X509_check_issued(issuer, cert) == X509_V_OK) {
1a95c1
+      id = OCSP_cert_to_id(EVP_sha1(), cert, issuer);
1a95c1
+      break;
1a95c1
+    }
1a95c1
+  }
1a95c1
+  X509_free(cert);
1a95c1
 
1a95c1
-    cert_status = OCSP_single_get0_status(single, &crl_reason, &rev,
1a95c1
-                                          &thisupd, &nextupd);
1a95c1
+  if(!id) {
1a95c1
+    failf(data, "Error computing OCSP ID");
1a95c1
+    result = CURLE_SSL_INVALIDCERTSTATUS;
1a95c1
+    goto end;
1a95c1
+  }
1a95c1
 
1a95c1
-    if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
1a95c1
-      failf(data, "OCSP response has expired");
1a95c1
-      result = CURLE_SSL_INVALIDCERTSTATUS;
1a95c1
-      goto end;
1a95c1
-    }
1a95c1
+  /* Find the single OCSP response corresponding to the certificate ID */
1a95c1
+  ret = OCSP_resp_find_status(br, id, &cert_status, &crl_reason, &rev,
1a95c1
+                              &thisupd, &nextupd);
1a95c1
+  OCSP_CERTID_free(id);
1a95c1
+  if(ret != 1) {
1a95c1
+    failf(data, "Could not find certificate ID in OCSP response");
1a95c1
+    result = CURLE_SSL_INVALIDCERTSTATUS;
1a95c1
+    goto end;
1a95c1
+  }
1a95c1
 
1a95c1
-    infof(data, "SSL certificate status: %s (%d)\n",
1a95c1
-          OCSP_cert_status_str(cert_status), cert_status);
1a95c1
+  /* Validate the corresponding single OCSP response */
1a95c1
+  if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) {
1a95c1
+    failf(data, "OCSP response has expired");
1a95c1
+    result = CURLE_SSL_INVALIDCERTSTATUS;
1a95c1
+    goto end;
1a95c1
+  }
1a95c1
 
1a95c1
-    switch(cert_status) {
1a95c1
-      case V_OCSP_CERTSTATUS_GOOD:
1a95c1
-        break;
1a95c1
+  infof(data, "SSL certificate status: %s (%d)\n",
1a95c1
+        OCSP_cert_status_str(cert_status), cert_status);
1a95c1
 
1a95c1
-      case V_OCSP_CERTSTATUS_REVOKED:
1a95c1
-        result = CURLE_SSL_INVALIDCERTSTATUS;
1a95c1
+  switch(cert_status) {
1a95c1
+  case V_OCSP_CERTSTATUS_GOOD:
1a95c1
+    break;
1a95c1
 
1a95c1
-        failf(data, "SSL certificate revocation reason: %s (%d)",
1a95c1
-              OCSP_crl_reason_str(crl_reason), crl_reason);
1a95c1
-        goto end;
1a95c1
+  case V_OCSP_CERTSTATUS_REVOKED:
1a95c1
+    result = CURLE_SSL_INVALIDCERTSTATUS;
1a95c1
+    failf(data, "SSL certificate revocation reason: %s (%d)",
1a95c1
+          OCSP_crl_reason_str(crl_reason), crl_reason);
1a95c1
+    goto end;
1a95c1
 
1a95c1
-      case V_OCSP_CERTSTATUS_UNKNOWN:
1a95c1
-        result = CURLE_SSL_INVALIDCERTSTATUS;
1a95c1
-        goto end;
1a95c1
-    }
1a95c1
+  case V_OCSP_CERTSTATUS_UNKNOWN:
1a95c1
+  default:
1a95c1
+    result = CURLE_SSL_INVALIDCERTSTATUS;
1a95c1
+    goto end;
1a95c1
   }
1a95c1
 
1a95c1
 end:
1a95c1
-- 
1a95c1
2.26.2
1a95c1