ssls: fix potential memory leak on import
No binary (build failed)
—
(log yok)
| @@ -534,6 +534,7 @@ Features testable here are: | |
| - `SPNEGO` | |
| - `SSL` | |
| - `SSLpinning` | |
| + | - `SSLS-EXPORT` |
| - `SSPI` | |
| - `threaded-resolver` | |
| - `TLS-SRP` | |
| @@ -380,9 +380,9 @@ static void cf_ssl_scache_session_ldestroy(void *udata, void *obj) | |
| { | |
| struct Curl_ssl_session *s = obj; | |
| (void)udata; | |
| - | curlx_free(CURL_UNCONST(s->sdata)); |
| - | curlx_free(CURL_UNCONST(s->quic_tp)); |
| - | curlx_free((void *)s->alpn); |
| + | curlx_free(s->sdata); |
| + | curlx_free(s->quic_tp); |
| + | curlx_free(s->alpn); |
| curlx_free(s); | |
| } | |
| @@ -122,13 +122,13 @@ CURLcode Curl_ssl_scache_add_obj(struct Curl_cfilter *cf, | |
| /* All about an SSL session ticket */ | |
| struct Curl_ssl_session { | |
| - | const void *sdata; /* session ticket data, plain bytes */ |
| + | uint8_t *sdata; /* session ticket data, plain bytes */ |
| size_t sdata_len; /* number of bytes in sdata */ | |
| curl_off_t valid_until; /* seconds since EPOCH until ticket expires */ | |
| int ietf_tls_id; /* TLS protocol identifier negotiated */ | |
| char *alpn; /* APLN TLS negotiated protocol string */ | |
| size_t earlydata_max; /* max 0-RTT data supported by peer */ | |
| - | const unsigned char *quic_tp; /* Optional QUIC transport param bytes */ |
| + | uint8_t *quic_tp; /* Optional QUIC transport param bytes */ |
| size_t quic_tp_len; /* number of bytes in quic_tp */ | |
| struct Curl_llist_node list; /* internal storage handling */ | |
| BIT(sectrust_verified); /* session comes from sectrust verified TLS */ | |
| @@ -244,6 +244,7 @@ CURLcode Curl_ssl_session_unpack(struct Curl_easy *data, | |
| uint16_t val16; | |
| uint32_t val32; | |
| uint64_t val64; | |
| + | size_t dlen; |
| CURLcode result; | |
| DEBUGASSERT(buf); | |
| @@ -271,6 +272,7 @@ CURLcode Curl_ssl_session_unpack(struct Curl_easy *data, | |
| switch(val8) { | |
| case CURL_SPACK_ALPN: | |
| + | curlx_free(s->alpn); |
| result = spack_decstr16(&s->alpn, &buf, end); | |
| if(result) | |
| goto out; | |
| @@ -288,17 +290,21 @@ CURLcode Curl_ssl_session_unpack(struct Curl_easy *data, | |
| s->ietf_tls_id = val16; | |
| break; | |
| case CURL_SPACK_QUICTP: { | |
| - | result = spack_decdata16(&pval8, &s->quic_tp_len, &buf, end); |
| + | result = spack_decdata16(&pval8, &dlen, &buf, end); |
| if(result) | |
| goto out; | |
| + | curlx_free(s->quic_tp); |
| s->quic_tp = pval8; | |
| + | s->quic_tp_len = dlen; |
| break; | |
| } | |
| case CURL_SPACK_TICKET: { | |
| - | result = spack_decdata16(&pval8, &s->sdata_len, &buf, end); |
| + | result = spack_decdata16(&pval8, &dlen, &buf, end); |
| if(result) | |
| goto out; | |
| + | curlx_free(s->sdata); |
| s->sdata = pval8; | |
| + | s->sdata_len = dlen; |
| break; | |
| } | |
| case CURL_SPACK_VALID_UNTIL: | |
| @@ -220,7 +220,7 @@ test1645 test1646 test1647 test1648 test1649 test1650 test1651 test1652 \ | |
| test1653 test1654 test1655 test1656 test1657 test1658 test1659 test1660 \ | |
| test1661 test1662 test1663 test1664 test1665 test1666 test1667 test1668 \ | |
| test1669 test1670 test1671 test1672 test1673 test1674 test1675 test1676 \ | |
| - | test1677 test1680 test1681 test1682 test1683 test1684 \ |
| + | test1677 test1678 test1680 test1681 test1682 test1683 test1684 \ |
| test1685 test1686 \ | |
| \ | |
| test1700 test1702 test1703 test1704 test1705 test1706 test1707 \ | |
| @@ -0,0 +1,21 @@ | |
| + | <?xml version="1.0" encoding="US-ASCII"?> |
| + | <testcase> |
| + | <info> |
| + | <keywords> |
| + | ssls-import |
| + | </keywords> |
| + | </info> |
| + | |
| + | # Client-side |
| + | <client> |
| + | <features> |
| + | SSLS-EXPORT |
| + | </features> |
| + | <tool> |
| + | lib%TESTNUMBER |
| + | </tool> |
| + | <name> |
| + | SSL session import tests |
| + | </name> |
| + | </client> |
| + | </testcase> |
| @@ -103,7 +103,7 @@ TESTS_C = \ | |
| lib1591.c lib1592.c lib1593.c lib1594.c lib1597.c \ | |
| lib1598.c lib1599.c \ | |
| lib1647.c lib1648.c lib1649.c \ | |
| - | lib1662.c \ |
| + | lib1662.c lib1678.c \ |
| lib1686.c \ | |
| lib1900.c lib1901.c lib1902.c lib1903.c lib1905.c lib1906.c lib1907.c \ | |
| lib1908.c lib1910.c lib1911.c lib1912.c lib1913.c \ | |
| @@ -0,0 +1,163 @@ | |
| + | /*************************************************************************** |
| + | * _ _ ____ _ |
| + | * Project ___| | | | _ \| | |
| + | * / __| | | | |_) | | |
| + | * | (__| |_| | _ <| |___ |
| + | * \___|\___/|_| \_\_____| |
| + | * |
| + | * Copyright (C) Daniel Stenberg, <[email protected]>, 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" |
| + | |
| + | #if defined(USE_SSL) && defined(USE_SSLS_EXPORT) |
| + | |
| + | #define T1678_IMPORT_COUNT 64 |
| + | #define T1678_FIRST_TICKET_SIZE 4096 |
| + | #define T1678_FIRST_QUICTP_SIZE 127 |
| + | #define T1678_FIRST_ALPN_SIZE 10 |
| + | |
| + | static uint8_t *t1678_make_packet(size_t *packet_len) |
| + | { |
| + | const size_t t1678_total = |
| + | 1 + /* format version */ |
| + | 1 + 2 + T1678_FIRST_TICKET_SIZE + /* first ticket */ |
| + | 1 + 2 + T1678_FIRST_QUICTP_SIZE + /* first QUIC traffic params */ |
| + | 1 + 2 + T1678_FIRST_ALPN_SIZE + /* first ALPN params */ |
| + | 1 + 2 + 1 + /* second ticket */ |
| + | 1 + 2 + 1 + /* second ALPN */ |
| + | 1 + 2 + 1; /* second QUIC traffic params */ |
| + | |
| + | uint8_t *packet = curlx_malloc(t1678_total); |
| + | uint8_t *p; |
| + | |
| + | if(!packet) |
| + | return NULL; |
| + | |
| + | p = packet; |
| + | |
| + | /* CURL_SPACK_VERSION */ |
| + | *p++ = 0x01; |
| + | |
| + | /* First CURL_SPACK_TICKET */ |
| + | *p++ = 0x04; |
| + | *p++ = (uint8_t)(T1678_FIRST_TICKET_SIZE >> 8); |
| + | *p++ = (uint8_t)(T1678_FIRST_TICKET_SIZE & 0x0ff); |
| + | memset(p, 'A', T1678_FIRST_TICKET_SIZE); |
| + | p += T1678_FIRST_TICKET_SIZE; |
| + | |
| + | /* First CURL_SPACK_QUICTP */ |
| + | *p++ = 0x07; |
| + | *p++ = (uint8_t)(T1678_FIRST_QUICTP_SIZE >> 8); |
| + | *p++ = (uint8_t)(T1678_FIRST_QUICTP_SIZE & 0x0ff); |
| + | memset(p, 'Q', T1678_FIRST_QUICTP_SIZE); |
| + | p += T1678_FIRST_QUICTP_SIZE; |
| + | |
| + | /* First CURL_SPACK_ALPN */ |
| + | *p++ = 0x05; |
| + | *p++ = (uint8_t)(T1678_FIRST_ALPN_SIZE >> 8); |
| + | *p++ = (uint8_t)(T1678_FIRST_ALPN_SIZE & 0x0ff); |
| + | memset(p, 'a', T1678_FIRST_ALPN_SIZE); |
| + | p += T1678_FIRST_ALPN_SIZE; |
| + | |
| + | /* Second CURL_SPACK_TICKET: one byte. */ |
| + | *p++ = 0x04; |
| + | *p++ = 0x00; |
| + | *p++ = 0x01; |
| + | *p++ = 'B'; |
| + | |
| + | /* Second CURL_SPACK_ALPN: one byte. */ |
| + | *p++ = 0x05; |
| + | *p++ = 0x00; |
| + | *p++ = 0x01; |
| + | *p++ = 'b'; |
| + | |
| + | /* Second CURL_SPACK_QUICTP: one byte. */ |
| + | *p++ = 0x07; |
| + | *p++ = 0x00; |
| + | *p++ = 0x01; |
| + | *p++ = 'R'; |
| + | |
| + | *packet_len = t1678_total; |
| + | return packet; |
| + | } |
| + | |
| + | static CURLcode test_lib1678(const char *URL) |
| + | { |
| + | uint8_t *packet; |
| + | size_t packet_len; |
| + | CURLSH *share = NULL; |
| + | CURL *easy = NULL; |
| + | CURLSHcode shrc; |
| + | CURLcode result = CURLE_FAILED_INIT; |
| + | int i; |
| + | |
| + | (void)URL; |
| + | packet = t1678_make_packet(&packet_len); |
| + | if(!packet) |
| + | goto test_cleanup; |
| + | |
| + | result = curl_global_init(CURL_GLOBAL_DEFAULT); |
| + | if(result != CURLE_OK) |
| + | goto test_cleanup; |
| + | |
| + | share = curl_share_init(); |
| + | easy = curl_easy_init(); |
| + | |
| + | if(!share || !easy) |
| + | goto test_cleanup; |
| + | |
| + | shrc = curl_share_setopt(share, |
| + | CURLSHOPT_SHARE, |
| + | CURL_LOCK_DATA_SSL_SESSION); |
| + | if(shrc != CURLSHE_OK) |
| + | goto test_cleanup; |
| + | |
| + | result = curl_easy_setopt(easy, CURLOPT_SHARE, share); |
| + | if(result) |
| + | goto test_cleanup; |
| + | |
| + | for(i = 0; i < T1678_IMPORT_COUNT; ++i) { |
| + | result = curl_easy_ssls_import(easy, |
| + | "example.test:443", |
| + | NULL, |
| + | 0, |
| + | packet, |
| + | packet_len); |
| + | if(result) { |
| + | curl_mfprintf(stderr, |
| + | "import %d failed: %d (%s)\n", |
| + | i, (int)result, |
| + | curl_easy_strerror(result)); |
| + | break; |
| + | } |
| + | } |
| + | |
| + | test_cleanup: |
| + | curlx_free(packet); |
| + | curl_easy_cleanup(easy); |
| + | curl_share_cleanup(share); |
| + | curl_global_cleanup(); |
| + | |
| + | return result; |
| + | } |
| + | #else |
| + | static CURLcode test_lib1678(const char *URL) |
| + | { |
| + | (void)URL; |
| + | return CURLE_OK; |
| + | } |
| + | #endif /* USE_SSL && USE_SSLS_EXPORT */ |
| @@ -733,6 +733,7 @@ sub checksystemfeatures { | |
| # 'https-proxy' is used as "server" so consider it a protocol | |
| push @protocols, 'https-proxy'; | |
| } | |
| + | $feature{"SSLS-EXPORT"} = $feat =~ /SSLS-EXPORT/; |
| # Unicode support | |
| $feature{"Unicode"} = $feat =~ /Unicode/i; | |
| # Thread-safe init | |