From 3e40ccb87581b0f6180fbd9c1eef9c50f270c806 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Fri, 10 Apr 2026 15:50:17 +0200 Subject: [PATCH] getinfo: repair CURLINFO_TLS_SESSION This should return a SSL_CTX pointer but it was accidentally broken. Verify with test 1587 Follow-up to 2db8ae480fdcae7f005 Spotted by Codex Security Closes #21290 --- lib/cfilters.c | 6 ++- lib/cfilters.h | 7 +-- lib/getinfo.c | 6 ++- tests/data/Makefile.am | 2 +- tests/data/test1587 | 51 ++++++++++++++++++ tests/libtest/Makefile.inc | 3 +- tests/libtest/lib1587.c | 103 +++++++++++++++++++++++++++++++++++++ 7 files changed, 168 insertions(+), 10 deletions(-) create mode 100644 tests/data/test1587 create mode 100644 tests/libtest/lib1587.c diff --git a/lib/cfilters.c b/lib/cfilters.c index 2f8fd4a6b0..c3e79bb78c 100644 --- a/lib/cfilters.c +++ b/lib/cfilters.c @@ -676,14 +676,16 @@ bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex) bool Curl_conn_get_ssl_info(struct Curl_easy *data, struct connectdata *conn, int sockindex, + int query, struct curl_tlssessioninfo *info) { if(!CONN_SOCK_IDX_VALID(sockindex)) return FALSE; if(Curl_conn_is_ssl(conn, sockindex)) { struct Curl_cfilter *cf = conn->cfilter[sockindex]; - CURLcode result = cf ? cf->cft->query(cf, data, CF_QUERY_SSL_INFO, - NULL, (void *)info) : CURLE_UNKNOWN_OPTION; + CURLcode result = cf ? + cf->cft->query(cf, data, query, NULL, (void *)info) : + CURLE_UNKNOWN_OPTION; return !result; } return FALSE; diff --git a/lib/cfilters.h b/lib/cfilters.h index 38311b24b8..fc77e61dfe 100644 --- a/lib/cfilters.h +++ b/lib/cfilters.h @@ -394,12 +394,13 @@ bool Curl_conn_is_ip_connected(struct Curl_easy *data, int sockindex); bool Curl_conn_is_ssl(struct connectdata *conn, int sockindex); /* - * Fill `info` with information about the TLS instance securing - * the connection when available, otherwise e.g. when - * Curl_conn_is_ssl() is FALSE, return FALSE. + * Fill `info` with information about the TLS instance securing the connection + * when available, otherwise e.g. when Curl_conn_is_ssl() is FALSE, return + * FALSE. 'query' should be CF_QUERY_SSL_INFO or CF_QUERY_SSL_CTX_INFO. */ bool Curl_conn_get_ssl_info(struct Curl_easy *data, struct connectdata *conn, int sockindex, + int query, struct curl_tlssessioninfo *info); CURLcode Curl_conn_get_ip_info(struct Curl_easy *data, diff --git a/lib/getinfo.c b/lib/getinfo.c index 106c476d49..fab63e669a 100644 --- a/lib/getinfo.c +++ b/lib/getinfo.c @@ -586,14 +586,16 @@ static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info, break; case CURLINFO_TLS_SESSION: case CURLINFO_TLS_SSL_PTR: { + int query = (info == CURLINFO_TLS_SSL_PTR) ? + CF_QUERY_SSL_INFO : CF_QUERY_SSL_CTX_INFO; struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **) - param_slistp; + param_slistp; struct curl_tlssessioninfo *tsi = &data->tsi; /* we are exposing a pointer to internal memory with unknown * lifetime here. */ *tsip = tsi; - if(!Curl_conn_get_ssl_info(data, data->conn, FIRSTSOCKET, tsi)) { + if(!Curl_conn_get_ssl_info(data, data->conn, FIRSTSOCKET, query, tsi)) { tsi->backend = Curl_ssl_backend(); tsi->internals = NULL; } diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 05c9aad580..6c3ad8e34c 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -208,7 +208,7 @@ test1548 test1549 test1550 test1551 test1552 test1553 test1554 test1555 \ test1556 test1557 test1558 test1559 test1560 test1561 test1562 test1563 \ test1564 test1565 test1566 test1567 test1568 test1569 test1570 test1571 \ test1572 test1573 test1574 test1575 test1576 test1577 test1578 test1579 \ -test1580 test1581 test1582 test1583 test1584 test1585 test1586 \ +test1580 test1581 test1582 test1583 test1584 test1585 test1586 test1587 \ \ test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 \ test1598 test1599 test1600 test1601 test1602 test1603 test1604 test1605 \ diff --git a/tests/data/test1587 b/tests/data/test1587 new file mode 100644 index 0000000000..8806527935 --- /dev/null +++ b/tests/data/test1587 @@ -0,0 +1,51 @@ + + + + +HTTPS +CURLINFO_TLS_SESSION + + + +# Server-side + + +HTTP/1.1 401 OK +Date: Tue, 09 Nov 2030 14:49:00 GMT +Server: test-server/fake +Content-Length: 7 +WWW-Authenticate: curl2000 + +nomnom + + + +# Client-side + + +SSL +OpenSSL + + +http +https + + +CURLINFO_TLS_SESSION and CURLINFO_TLS_SSL_PTR with OpenSSL + + +lib%TESTNUMBER + + +https://%HOSTIP:%HTTPSPORT/ + + + + + +CURLINFO_TLS_SESSION: OK +CURLINFO_TLS_SSL_PTR: OK + + + + diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc index d42bdcd07e..713197962c 100644 --- a/tests/libtest/Makefile.inc +++ b/tests/libtest/Makefile.inc @@ -96,8 +96,7 @@ TESTS_C = \ lib1552.c lib1553.c lib1554.c lib1555.c lib1556.c lib1557.c lib1558.c \ lib1559.c lib1560.c lib1564.c lib1565.c \ lib1567.c lib1568.c lib1569.c lib1571.c \ - lib1576.c \ - lib1582.c \ + lib1576.c lib1582.c lib1587.c \ lib1591.c lib1592.c lib1593.c lib1594.c lib1597.c \ lib1598.c lib1599.c \ lib1662.c \ diff --git a/tests/libtest/lib1587.c b/tests/libtest/lib1587.c new file mode 100644 index 0000000000..ad66c003f0 --- /dev/null +++ b/tests/libtest/lib1587.c @@ -0,0 +1,103 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#include "first.h" + +#ifdef USE_OPENSSL + +#include +#include +#include +#include + +#ifdef HAVE_BORINGSSL_LIKE +/* BoringSSL and AWS-LC */ +typedef uint32_t opt1587; +#else +typedef uint64_t opt1587; +#endif + +static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *stream) +{ + const struct curl_tlssessioninfo *info; + CURLcode result; + static int once; + CURL *curl = stream; + (void)ptr; + + if(!once++) { + result = curl_easy_getinfo(curl, CURLINFO_TLS_SESSION, &info); + + if(result == CURLE_OK) { + /* set and read stuff using the SSL_CTX to verify it */ + opt1587 opts = SSL_CTX_get_options(info->internals); + SSL_CTX_set_options(info->internals, opts); + curl_mprintf("CURLINFO_TLS_SESSION: OK\n"); + } + + result = curl_easy_getinfo(curl, CURLINFO_TLS_SSL_PTR, &info); + + if(result == CURLE_OK) { + /* set and read stuff using the SSL pointer to verify it */ + opt1587 opts = SSL_get_options(info->internals); + SSL_set_options(info->internals, opts); + curl_mprintf("CURLINFO_TLS_SSL_PTR: OK\n"); + } + } + + return size * nmemb; +} + +static CURLcode test_lib1587(const char *URL) +{ + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + CURL *curl; + if(result) + return result; + + curl = curl_easy_init(); + if(curl) { + curl_easy_setopt(curl, CURLOPT_URL, URL); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + + result = curl_easy_perform(curl); + curl_easy_cleanup(curl); + } + + curl_global_cleanup(); + + return result; +} +#else +/* without OpenSSL this does nothing */ +static CURLcode test_lib1587(const char *URL) +{ + (void)URL; + return CURLE_OK; +} +#endif