]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
curl: make --libcurl output better CURLOPT_*SSLVERSION
authorDaniel Stenberg <daniel@haxx.se>
Thu, 14 Mar 2024 12:58:45 +0000 (13:58 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 14 Mar 2024 16:59:22 +0000 (17:59 +0100)
The option is really two enums ORed together, so it needs special
attention to make the code output nice.

Added test 1481 to verify. Both the server and the proxy versions.

Reported-by: Boris Verkhovskiy
Fixes #13127
Closes #13129

src/tool_operate.c
src/tool_setopt.c
src/tool_setopt.h
tests/data/Makefile.inc
tests/data/test1481 [new file with mode: 0644]

index 5a5fc8745ed14ba4e240c8cc1bf1518d6a30b28d..7e2c1eefe02b92305999108c5e71c2adee35f103 100644 (file)
@@ -1763,11 +1763,11 @@ static CURLcode single_transfer(struct GlobalConfig *global,
           if(config->falsestart)
             my_setopt(curl, CURLOPT_SSL_FALSESTART, 1L);
 
-          my_setopt_enum(curl, CURLOPT_SSLVERSION,
-                         config->ssl_version | config->ssl_version_max);
+          my_setopt_SSLVERSION(curl, CURLOPT_SSLVERSION,
+                               config->ssl_version | config->ssl_version_max);
           if(config->proxy)
-            my_setopt_enum(curl, CURLOPT_PROXY_SSLVERSION,
-                           config->proxy_ssl_version);
+            my_setopt_SSLVERSION(curl, CURLOPT_PROXY_SSLVERSION,
+                                 config->proxy_ssl_version);
 
           {
             long mask =
index b41b6d1d263c484177781358ac7ccc48aeaa31a5..656adbda8a287d1be0e02eaa70ce93263fa36e91 100644 (file)
@@ -107,6 +107,16 @@ const struct NameValue setopt_nv_CURL_SSLVERSION[] = {
   NVEND,
 };
 
+const struct NameValue setopt_nv_CURL_SSLVERSION_MAX[] = {
+  NV(CURL_SSLVERSION_MAX_NONE),
+  NV(CURL_SSLVERSION_MAX_DEFAULT),
+  NV(CURL_SSLVERSION_MAX_TLSv1_0),
+  NV(CURL_SSLVERSION_MAX_TLSv1_1),
+  NV(CURL_SSLVERSION_MAX_TLSv1_2),
+  NV(CURL_SSLVERSION_MAX_TLSv1_3),
+  NVEND,
+};
+
 const struct NameValue setopt_nv_CURL_TIMECOND[] = {
   NV(CURL_TIMECOND_IFMODSINCE),
   NV(CURL_TIMECOND_IFUNMODSINCE),
@@ -296,6 +306,50 @@ nomem:
   return ret;
 }
 
+/* setopt wrapper for CURLOPT_SSLVERSION */
+CURLcode tool_setopt_SSLVERSION(CURL *curl, struct GlobalConfig *config,
+                                const char *name, CURLoption tag,
+                                long lval)
+{
+  CURLcode ret = CURLE_OK;
+  bool skip = FALSE;
+
+  ret = curl_easy_setopt(curl, tag, lval);
+  if(!lval)
+    skip = TRUE;
+
+  if(config->libcurl && !skip && !ret) {
+    /* we only use this for real if --libcurl was used */
+    const struct NameValue *nv = NULL;
+    const struct NameValue *nv2 = NULL;
+    for(nv = setopt_nv_CURL_SSLVERSION; nv->name; nv++) {
+      if(nv->value == (lval & 0xffff))
+        break; /* found it */
+    }
+    for(nv2 = setopt_nv_CURL_SSLVERSION_MAX; nv2->name; nv2++) {
+      if(nv2->value == (lval & ~0xffff))
+        break; /* found it */
+    }
+    if(!nv->name) {
+      /* If no definition was found, output an explicit value.
+       * This could happen if new values are defined and used
+       * but the NameValue list is not updated. */
+      CODE2("curl_easy_setopt(hnd, %s, %ldL);", name, lval);
+    }
+    else {
+      CODE3("curl_easy_setopt(hnd, %s, (long)(%s | %s));",
+            name, nv->name, nv2->name);
+    }
+  }
+
+#ifdef DEBUGBUILD
+  if(ret)
+    warnf(config, "option %s returned error (%d)", name, (int)ret);
+#endif
+nomem:
+  return ret;
+}
+
 /* setopt wrapper for bitmasks */
 CURLcode tool_setopt_bitmask(CURL *curl, struct GlobalConfig *config,
                              const char *name, CURLoption tag,
index cd59a74cd8b9ec460f6420d86c070e0a4f9d75eb..6588da9ced06a734dab730830b3cae4f99c8116e 100644 (file)
@@ -52,6 +52,7 @@ extern const struct NameValue setopt_nv_CURLPROXY[];
 extern const struct NameValue setopt_nv_CURL_SOCKS_PROXY[];
 extern const struct NameValue setopt_nv_CURL_HTTP_VERSION[];
 extern const struct NameValue setopt_nv_CURL_SSLVERSION[];
+extern const struct NameValue setopt_nv_CURL_SSLVERSION_MAX[];
 extern const struct NameValue setopt_nv_CURL_TIMECOND[];
 extern const struct NameValue setopt_nv_CURLFTPSSL_CCC[];
 extern const struct NameValue setopt_nv_CURLUSESSL[];
@@ -81,6 +82,9 @@ extern const struct NameValueUnsigned setopt_nv_CURLHSTS[];
 CURLcode tool_setopt_enum(CURL *curl, struct GlobalConfig *config,
                           const char *name, CURLoption tag,
                           const struct NameValue *nv, long lval);
+CURLcode tool_setopt_SSLVERSION(CURL *curl, struct GlobalConfig *config,
+                                const char *name, CURLoption tag,
+                                long lval);
 CURLcode tool_setopt_flags(CURL *curl, struct GlobalConfig *config,
                            const char *name, CURLoption tag,
                            const struct NameValue *nv, long lval);
@@ -106,6 +110,9 @@ CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *global,
 #define my_setopt_enum(x,y,z) \
   SETOPT_CHECK(tool_setopt_enum(x, global, #y, y, setopt_nv_ ## y, z), y)
 
+#define my_setopt_SSLVERSION(x,y,z) \
+  SETOPT_CHECK(tool_setopt_SSLVERSION(x, global, #y, y, z), y)
+
 #define my_setopt_bitmask(x,y,z) \
   SETOPT_CHECK(tool_setopt_bitmask(x, global, #y, y, setopt_nv_ ## y, z), y)
 
@@ -132,6 +139,9 @@ CURLcode tool_setopt(CURL *curl, bool str, struct GlobalConfig *global,
 #define my_setopt_enum(x,y,z) \
   SETOPT_CHECK(curl_easy_setopt(x, y, z), y)
 
+#define my_setopt_SSLVERSION(x,y,z) \
+  SETOPT_CHECK(curl_easy_setopt(x, y, z), y)
+
 #define my_setopt_bitmask(x,y,z) \
   SETOPT_CHECK(curl_easy_setopt(x, y, z), y)
 
index 06bc5c54f9647553ed9353f329d350baec540492..50b404b468bd0458aee0ed66203947bc1dea61bd 100644 (file)
@@ -188,7 +188,7 @@ test1447 test1448 test1449 test1450 test1451 test1452 test1453 test1454 \
 test1455 test1456 test1457 test1458 test1459 test1460 test1461 test1462 \
 test1463 test1464 test1465 test1466 test1467 test1468 test1469 test1470 \
 test1471 test1472 test1473 test1474 test1475 test1476 test1477 test1478 \
-test1479 test1480 \
+test1479 test1480 test1481 \
 \
 test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
 test1508 test1509 test1510 test1511 test1512 test1513 test1514 test1515 \
diff --git a/tests/data/test1481 b/tests/data/test1481
new file mode 100644 (file)
index 0000000..ca638f5
--- /dev/null
@@ -0,0 +1,118 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+--libcurl
+</keywords>
+</info>
+
+# Server-side
+<reply>
+<data>
+HTTP/1.1 200 OK
+Date: Thu, 29 Jul 2008 14:49:00 GMT
+Server: test-server/fake
+Content-Length: 0
+Connection: close
+
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+<features>
+proxy
+ssl
+</features>
+<name>
+--libcurl with TLS version options
+</name>
+<setenv>
+SSL_CERT_FILE=
+</setenv>
+<command>
+http://moo/ --libcurl %LOGDIR/test%TESTNUMBER.c --tls-max 1.3 --proxy-tlsv1 -x http://%HOSTIP:%HTTPPORT
+</command>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET http://moo/ HTTP/1.1\r
+Host: moo\r
+User-Agent: curl/%VERSION\r
+Accept: */*\r
+Proxy-Connection: Keep-Alive\r
+\r
+</protocol>
+<stripfile>
+s/(USERAGENT, \")[^\"]+/${1}stripped/
+# CURLOPT_SSL_VERIFYPEER, SSH_KNOWNHOSTS and HTTP_VERSION vary with
+# CURLOPT_INTERLEAVEDATA requires RTSP protocol
+# configurations - just ignore them
+$_ = '' if /CURLOPT_SSL_VERIFYPEER/
+$_ = '' if /CURLOPT_SSH_KNOWNHOSTS/
+$_ = '' if /CURLOPT_HTTP_VERSION/
+$_ = '' if /CURLOPT_HTTP09_ALLOWED/
+$_ = '' if /CURLOPT_INTERLEAVEDATA/
+</stripfile>
+<file name="%LOGDIR/test%TESTNUMBER.c" mode="text">
+/********* Sample code generated by the curl command line tool **********
+ * All curl_easy_setopt() options are documented at:
+ * https://curl.se/libcurl/c/curl_easy_setopt.html
+ ************************************************************************/
+#include <curl/curl.h>
+
+int main(int argc, char *argv[])
+{
+  CURLcode ret;
+  CURL *hnd;
+
+  hnd = curl_easy_init();
+  curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L);
+  curl_easy_setopt(hnd, CURLOPT_URL, "http://moo/");
+  curl_easy_setopt(hnd, CURLOPT_PROXY, "http://%HOSTIP:%HTTPPORT");
+  curl_easy_setopt(hnd, CURLOPT_USERAGENT, "stripped");
+  curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L);
+  curl_easy_setopt(hnd, CURLOPT_SSLVERSION, (long)(CURL_SSLVERSION_DEFAULT | CURL_SSLVERSION_MAX_TLSv1_3));
+  curl_easy_setopt(hnd, CURLOPT_PROXY_SSLVERSION, (long)(CURL_SSLVERSION_TLSv1 | CURL_SSLVERSION_MAX_NONE));
+  curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L);
+%if ftp
+  curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L);
+%endif
+  curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L);
+
+  /* Here is a list of options the curl code used that cannot get generated
+     as source easily. You may choose to either not use them or implement
+     them yourself.
+
+  CURLOPT_WRITEDATA was set to an object pointer
+  CURLOPT_WRITEFUNCTION was set to a function pointer
+  CURLOPT_READDATA was set to an object pointer
+  CURLOPT_READFUNCTION was set to a function pointer
+  CURLOPT_SEEKDATA was set to an object pointer
+  CURLOPT_SEEKFUNCTION was set to a function pointer
+  CURLOPT_ERRORBUFFER was set to an object pointer
+  CURLOPT_STDERR was set to an object pointer
+  CURLOPT_DEBUGFUNCTION was set to a function pointer
+  CURLOPT_DEBUGDATA was set to an object pointer
+  CURLOPT_HEADERFUNCTION was set to a function pointer
+  CURLOPT_HEADERDATA was set to an object pointer
+
+  */
+
+  ret = curl_easy_perform(hnd);
+
+  curl_easy_cleanup(hnd);
+  hnd = NULL;
+
+  return (int)ret;
+}
+/**** End of sample code ****/
+</file>
+</verify>
+</testcase>