]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
gtls: simplify Curl_gtls_verifyserver
authorDaniel Stenberg <daniel@haxx.se>
Mon, 4 May 2026 07:55:26 +0000 (09:55 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 4 May 2026 08:35:40 +0000 (10:35 +0200)
Move peer certificate verification logic into gtls_verify_cert()

Closes #21488

lib/vtls/gtls.c

index 9b6a4fab2e3935a41f734df932e5271943b90f01..e0a689eecb48cb7f1372066d4e6c2704e5bbd7c6 100644 (file)
@@ -1555,21 +1555,75 @@ static CURLcode gtls_chain_get_der(struct Curl_cfilter *cf,
   *pder_len = (size_t)chain->certs[i].size;
   return CURLE_OK;
 }
+#endif /* USE_APPLE_SECTRUST */
 
-static CURLcode glts_apple_verify(struct Curl_cfilter *cf,
-                                  struct Curl_easy *data,
-                                  struct ssl_peer *peer,
-                                  struct gtls_cert_chain *chain,
-                                  bool *pverified)
+/* This function verifies the peer's certificate and returns CURLE_OK on
+   success or an appropriate CURLcode on error. The certificate verification
+   status bitmask (trusted, invalid etc.) is stored in
+   ssl_config->certverifyresult as one or more gnutls_certificate_status_t
+   enumerated elements bitwise or'd. */
+static CURLcode gtls_verify_cert(struct Curl_easy *data,
+                                 struct ssl_primary_config *config,
+                                 struct ssl_config_data *ssl_config,
+                                 gnutls_session_t session,
+                                 struct Curl_cfilter *cf,
+                                 struct ssl_peer *peer,
+                                 struct gtls_cert_chain *chain)
 {
-  CURLcode result;
+  bool verified = FALSE;
+  unsigned int verify_status = 0;
+  long * const certverifyresult = &ssl_config->certverifyresult;
+  int rc = gnutls_certificate_verify_peers2(session, &verify_status);
+  if(rc < 0) {
+    failf(data, "server cert verify failed: %d", rc);
+    *certverifyresult = rc;
+    return CURLE_SSL_CONNECT_ERROR;
+  }
+  *certverifyresult = verify_status;
+  verified = !(verify_status & GNUTLS_CERT_INVALID);
+  if(verified)
+    infof(data, "  SSL certificate verified by GnuTLS");
 
-  result = Curl_vtls_apple_verify(cf, data, peer, chain->num_certs,
-                                  gtls_chain_get_der, chain, NULL, 0);
-  *pverified = !result;
-  return result;
+#ifdef USE_APPLE_SECTRUST
+  if(!verified && ssl_config->native_ca_store) {
+    CURLcode result =
+      Curl_vtls_apple_verify(cf, data, peer, chain->num_certs,
+                             gtls_chain_get_der, chain, NULL, 0);
+    if(result && (result != CURLE_PEER_FAILED_VERIFICATION))
+      return result; /* unexpected error */
+    verified = !result;
+    if(verified) {
+      infof(data, "SSL certificate verified via Apple SecTrust.");
+      *certverifyresult = 0;
+    }
+  }
+#else
+  (void)cf;
+  (void)peer;
+  (void)chain;
+#endif
+
+  if(!verified) {
+    /* verify_status is a bitmask of gnutls_certificate_status bits */
+    const char *cause = "certificate error, no details available";
+    if(verify_status & GNUTLS_CERT_EXPIRED)
+      cause = "certificate has expired";
+    else if(verify_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
+      cause = "certificate signer not trusted";
+    else if(verify_status & GNUTLS_CERT_INSECURE_ALGORITHM)
+      cause = "certificate uses insecure algorithm";
+    else if(verify_status & GNUTLS_CERT_INVALID_OCSP_STATUS)
+      cause = "attached OCSP status response is invalid";
+    failf(data, "SSL certificate verification failed: %s. (CAfile: %s "
+          "CRLfile: %s)", cause,
+          config->CAfile ? config->CAfile : "none",
+          ssl_config->primary.CRLfile ?
+          ssl_config->primary.CRLfile : "none");
+
+    return CURLE_PEER_FAILED_VERIFICATION;
+  }
+  return CURLE_OK;
 }
-#endif /* USE_APPLE_SECTRUST */
 
 CURLcode Curl_gtls_verifyserver(struct Curl_cfilter *cf,
                                 struct Curl_easy *data,
@@ -1643,58 +1697,10 @@ CURLcode Curl_gtls_verifyserver(struct Curl_cfilter *cf,
   }
 
   if(config->verifypeer) {
-    bool verified = FALSE;
-    unsigned int verify_status = 0;
-    /* This function tries to verify the peer's certificate and return
-       its status (trusted, invalid etc.). The value of status should be
-       one or more of the gnutls_certificate_status_t enumerated elements
-       bitwise or'd. To avoid denial of service attacks some default
-       upper limits regarding the certificate key size and chain size
-       are set. To override them use
-       gnutls_certificate_set_verify_limits(). */
-    rc = gnutls_certificate_verify_peers2(session, &verify_status);
-    if(rc < 0) {
-      failf(data, "server cert verify failed: %d", rc);
-      *certverifyresult = rc;
-      result = CURLE_SSL_CONNECT_ERROR;
-      goto out;
-    }
-    *certverifyresult = verify_status;
-    verified = !(verify_status & GNUTLS_CERT_INVALID);
-    if(verified)
-      infof(data, "  SSL certificate verified by GnuTLS");
-
-#ifdef USE_APPLE_SECTRUST
-    if(!verified && ssl_config->native_ca_store) {
-      result = glts_apple_verify(cf, data, peer, &chain, &verified);
-      if(result && (result != CURLE_PEER_FAILED_VERIFICATION))
-        goto out; /* unexpected error */
-      if(verified) {
-        infof(data, "SSL certificate verified via Apple SecTrust.");
-        *certverifyresult = 0;
-      }
-    }
-#endif
-
-    if(!verified) {
-      /* verify_status is a bitmask of gnutls_certificate_status bits */
-      const char *cause = "certificate error, no details available";
-      if(verify_status & GNUTLS_CERT_EXPIRED)
-        cause = "certificate has expired";
-      else if(verify_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
-        cause = "certificate signer not trusted";
-      else if(verify_status & GNUTLS_CERT_INSECURE_ALGORITHM)
-        cause = "certificate uses insecure algorithm";
-      else if(verify_status & GNUTLS_CERT_INVALID_OCSP_STATUS)
-        cause = "attached OCSP status response is invalid";
-      failf(data, "SSL certificate verification failed: %s. (CAfile: %s "
-            "CRLfile: %s)", cause,
-            config->CAfile ? config->CAfile : "none",
-            ssl_config->primary.CRLfile ?
-            ssl_config->primary.CRLfile : "none");
-      result = CURLE_PEER_FAILED_VERIFICATION;
+    result = gtls_verify_cert(data, config, ssl_config, session,
+                              cf, peer, &chain);
+    if(result)
       goto out;
-    }
   }
   else
     infof(data, "  SSL certificate verification SKIPPED");