]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
mbedtls: no longer use MBEDTLS_SSL_VERIFY_OPTIONAL
authorJan Venekamp <1422460+jan2000@users.noreply.github.com>
Mon, 19 Aug 2024 01:59:08 +0000 (03:59 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 20 Aug 2024 10:45:06 +0000 (12:45 +0200)
With mbedTLS if the minimum version of TLS is set to 1.3,
MBEDTLS_SSL_VERIFY_OPTIONAL is not available in client mode. See:
https://github.com/Mbed-TLS/mbedtls/blob/2ca6c285/library/ssl_tls.c#L1357
Also, there might be plans to remove it completely in future mbedTLS
versions.

Switch to always use MBEDTLS_SSL_VERIFY_REQUIRED. If verifypeer or
verifyhost are disabled the corresponding error flags are cleared in the
verify callback function. That is also where verification errors are
logged.

Closes #14591

lib/vtls/mbedtls.c

index 217fd0dcb8bdc5e87eec9d0f5662b243dae9620c..1cf7c0469760a570d9e81556abc9d123ef25abfe 100644 (file)
@@ -115,11 +115,6 @@ struct mbed_ssl_backend_data {
   BIT(sent_shutdown);
 };
 
-struct verify_cb_data {
-  struct Curl_easy *data;
-  struct Curl_cfilter *cf;
-};
-
 /* apply threading? */
 #if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \
     defined(_WIN32)
@@ -490,28 +485,22 @@ add_ciphers:
   return CURLE_OK;
 }
 
-static void dump_cert_info(struct Curl_easy *data,
-                           const mbedtls_x509_crt *peercert)
+static void
+mbed_dump_cert_info(struct Curl_easy *data, const mbedtls_x509_crt *crt)
 {
-#if !defined(CURL_DISABLE_VERBOSE_STRINGS) && \
-    !defined(MBEDTLS_X509_REMOVE_INFO)
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS) || \
+    (MBEDTLS_VERSION_NUMBER >= 0x03000000 && defined(MBEDTLS_X509_REMOVE_INFO))
+  (void) data, (void) crt;
+#else
   const size_t bufsize = 16384;
-  char *buffer = malloc(bufsize);
+  char *p, *buffer = malloc(bufsize);
 
-  if(!buffer)
-    return;
-
-  if(mbedtls_x509_crt_info(buffer, bufsize, " ", peercert) > 0) {
-    char *p = buffer;
+  if(buffer && mbedtls_x509_crt_info(buffer, bufsize, " ", crt) > 0) {
     infof(data, "Server certificate:");
-    while(*p) {
-      char *nl = strchr(p, '\n');
-      if(nl)
-        *nl = '\0';
-      infof(data, "%s", p);
-      if(!nl)
-        break;
-      p = nl + 1;
+    for(p = buffer; *p; *p && p++) {
+      size_t s = strcspn(p, "\n");
+      infof(data, "%.*s", (int) s, p);
+      p += s;
     }
   }
   else
@@ -521,63 +510,52 @@ static void dump_cert_info(struct Curl_easy *data,
 #endif
 }
 
-static int count_server_cert(const mbedtls_x509_crt *peercert)
+static void
+mbed_extract_certinfo(struct Curl_easy *data, const mbedtls_x509_crt *crt)
 {
-  int count = 1;
+  CURLcode result;
+  const mbedtls_x509_crt *cur;
+  int i;
 
-  DEBUGASSERT(peercert);
+  for(i = 0, cur = crt; cur; ++i, cur = cur->next);
+  result = Curl_ssl_init_certinfo(data, i);
 
-  while(peercert->next) {
-    ++count;
-    peercert = peercert->next;
+  for(i = 0, cur = crt; result == CURLE_OK && cur; ++i, cur = cur->next) {
+    const char *beg = (const char *) cur->raw.p;
+    const char *end = beg + cur->raw.len;
+    result = Curl_extract_certinfo(data, i, beg, end);
   }
-  return count;
-}
-
-static CURLcode collect_server_cert_single(struct Curl_easy *data,
-                                           const mbedtls_x509_crt *server_cert,
-                                           int idx)
-{
-  const char *beg, *end;
-
-  DEBUGASSERT(server_cert);
-
-  beg = (const char *)server_cert->raw.p;
-  end = beg + server_cert->raw.len;
-  return Curl_extract_certinfo(data, idx, beg, end);
 }
 
-static int mbed_verify(void *udata, mbedtls_x509_crt *crt,
-                       int depth, uint32_t *flags)
+static int mbed_verify_cb(void *ptr, mbedtls_x509_crt *crt,
+                          int depth, uint32_t *flags)
 {
-  struct verify_cb_data *cb_data = udata;
-  struct Curl_easy *data = cb_data->data;
-  struct Curl_cfilter *cf = cb_data->cf;
+  struct Curl_cfilter *cf = (struct Curl_cfilter *) ptr;
   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
+  struct Curl_easy *data = CF_DATA_CURRENT(cf);
 
   if(depth == 0) {
     if(data->set.verbose)
-      dump_cert_info(data, crt);
-
-    if(data->set.ssl.certinfo) {
-      mbedtls_x509_crt *peercert = crt;
-      int count = count_server_cert(peercert);
-      CURLcode result = Curl_ssl_init_certinfo(data, count);
-      int i;
-      for(i = 0; result == CURLE_OK && peercert; i++) {
-        result = collect_server_cert_single(data, peercert, i);
-        peercert = peercert->next;
-      }
-    }
+      mbed_dump_cert_info(data, crt);
+    if(data->set.ssl.certinfo)
+      mbed_extract_certinfo(data, crt);
   }
 
-  /* we clear any faults the mbedtls' own verification found if needed.
-   * See <https://github.com/Mbed-TLS/mbedtls/issues/9210> */
   if(!conn_config->verifypeer)
     *flags = 0;
   else if(!conn_config->verifyhost)
     *flags &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH;
 
+  if(*flags) {
+#if MBEDTLS_VERSION_NUMBER < 0x03000000 || !defined(MBEDTLS_X509_REMOVE_INFO)
+    char buf[128];
+    mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", *flags);
+    failf(data, "mbedTLS: %s", buf);
+#else
+    failf(data, "mbedTLS: cerificate verification error 0x%08x", *flags);
+#endif
+  }
+
   return 0;
 }
 
@@ -838,6 +816,12 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
     return CURLE_SSL_CONNECT_ERROR;
   }
 
+  /* Always let mbedTLS verify certificates, if verifypeer or verifyhost are
+   * disabled we clear the corresponding error flags in the verify callback
+   * function. That is also where we log verification errors. */
+  mbedtls_ssl_conf_verify(&backend->config, mbed_verify_cb, cf);
+  mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_REQUIRED);
+
   mbedtls_ssl_init(&backend->ssl);
   backend->initialized = TRUE;
 
@@ -849,15 +833,6 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data)
   if(ret != CURLE_OK)
     return ret;
 
-#ifdef TLS13_SUPPORT
-  if(conn_config->version == CURL_SSLVERSION_TLSv1_3)
-    mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_REQUIRED);
-  else
-    mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
-#else
-  mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
-#endif
-
   mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random,
                        &backend->ctr_drbg);
 
@@ -999,7 +974,6 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
   struct ssl_connect_data *connssl = cf->ctx;
   struct mbed_ssl_backend_data *backend =
     (struct mbed_ssl_backend_data *)connssl->backend;
-  struct verify_cb_data cb_data = { data, cf };
 #ifndef CURL_DISABLE_PROXY
   const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)?
     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]:
@@ -1010,8 +984,6 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
 
   DEBUGASSERT(backend);
 
-  mbedtls_ssl_conf_verify(&backend->config, mbed_verify, &cb_data);
-
   ret = mbedtls_ssl_handshake(&backend->ssl);
 
   if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
@@ -1023,8 +995,8 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
     return CURLE_OK;
   }
   else if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
-    infof(data, "peer certificate could not be verified");
-    /* fall through to flag checking below for better error messages */
+    failf(data, "peer certificate could not be verified");
+    return CURLE_PEER_FAILED_VERIFICATION;
   }
   else if(ret) {
     char errorbuf[128];
@@ -1052,29 +1024,6 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data)
   infof(data, "mbedTLS: %s Handshake complete",
         mbedtls_ssl_get_version(&backend->ssl));
 #endif
-  ret = mbedtls_ssl_get_verify_result(&backend->ssl);
-
-  if(ret) {
-    if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
-      failf(data, "Cert verify failed: BADCERT_EXPIRED");
-
-    else if(ret & MBEDTLS_X509_BADCERT_REVOKED)
-      failf(data, "Cert verify failed: BADCERT_REVOKED");
-
-    else if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH)
-      failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
-
-    else if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
-      failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
-
-    else if(ret & MBEDTLS_X509_BADCERT_FUTURE)
-      failf(data, "Cert verify failed: BADCERT_FUTURE");
-
-    else
-      failf(data, "peer certificate could not be verified");
-
-    return CURLE_PEER_FAILED_VERIFICATION;
-  }
 
   if(pinnedpubkey) {
     int size;