Skip to content

Commit

Permalink
curl: make --libcurl output better CURLOPT_*SSLVERSION
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bagder committed Mar 14, 2024
1 parent 09f3679 commit 4094818
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 5 deletions.
8 changes: 4 additions & 4 deletions src/tool_operate.c
Expand Up @@ -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 =
Expand Down
54 changes: 54 additions & 0 deletions src/tool_setopt.c
Expand Up @@ -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),
Expand Down Expand Up @@ -296,6 +306,50 @@ CURLcode tool_setopt_enum(CURL *curl, struct GlobalConfig *config,
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,
Expand Down
10 changes: 10 additions & 0 deletions src/tool_setopt.h
Expand Up @@ -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[];
Expand Down Expand Up @@ -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);
Expand All @@ -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)

Expand All @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion tests/data/Makefile.inc
Expand Up @@ -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 \
Expand Down
118 changes: 118 additions & 0 deletions tests/data/test1481
@@ -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
Host: moo
User-Agent: curl/%VERSION
Accept: */*
Proxy-Connection: Keep-Alive

</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>

0 comments on commit 4094818

Please sign in to comment.