Skip to content

libcurl with Secure Transport and --enable-optimize crashes when settings CURLOPT_SSLCERT to an inexistant cert #9194

Description

@guillaumealgis

I did this

  • Compiled libcurl with Secure Transport on Darwin platform (tested on macOS and iOS).
  • Used --enable-optimize during configuration (this bellow for the full options list).
  • Tried to make a request while using a non-existent client SSL certificate (eg. curl_easy_setopt(handle, CURLOPT_SSLCERT, "thisdoesnotexistinkeychain");).

I expected the following

  • The request fails and curl_easy_perform returns an error.

What I got

  • curl_easy_perform crashes on a CFRelease call.

curl/libcurl version

curl 7.84.0 (arm-apple-darwin) libcurl/7.84.0 SecureTransport zlib/1.2.11 nghttp2/1.47.0
Release-Date: 2022-06-27
Protocols: http https mqtt 
Features: alt-svc AsynchDNS HSTS HTTP2 IPv6 Largefile libz SSL threadsafe UnixSockets

Operating system

macOS Monterey 12.4 (21F79)
Xcode 13.4.1 (13F100)

Darwin 21.5.0 Darwin Kernel Version 21.5.0: Tue Apr 26 21:08:37 PDT 2022; root:xnu-8020.121.3~4/RELEASE_ARM64_T6000 arm64

Details

libcurl ./configure options

./configure \
    --disable-dependency-tracking \
    --disable-shared \
    --enable-static \
    \
    --disable-debug \
    --disable-curldebug \
    --enable-optimize \
    --enable-warnings \
    --enable-symbol-hiding \
    \
    --disable-ares \
    \
    --enable-http \
    --disable-ftp \
    --disable-file \
    --disable-ldap \
    --disable-ldaps \
    --disable-rtsp \
    --disable-proxy \
    --disable-dict \
    --disable-telnet \
    --disable-tftp \
    --disable-pop3 \
    --disable-imap \
    --disable-smb \
    --disable-smtp \
    --disable-gopher \
    --disable-manual \
    --disable-libcurl-option \
    --enable-ipv6 \
    \
    --enable-threaded-resolver \
    --disable-sspi \
    --disable-crypto-auth \
    --disable-tls-srp \
    \
    --without-schannel \
    --with-secure-transport \
    \
    --without-libidn2 \
    \
    --host="arm-apple-darwin" --prefix="dist"

Minimal sample reproducing the issue

#include <stdlib.h>
#include <printf.h>

#include "curl-7.84.0/dist/include/curl/curl.h"

int main() {
    CURL *handle = curl_easy_init();

    if (!handle) {
        exit(1);
    }

    char errbuf[CURL_ERROR_SIZE];
    curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, errbuf);
    errbuf[0] = 0;

    curl_easy_setopt(handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);

    curl_easy_setopt(handle, CURLOPT_SSLCERTTYPE, "P12");
    curl_easy_setopt(handle, CURLOPT_SSLCERT, "thisdoesnotexistinkeychain");
    curl_easy_setopt(handle, CURLOPT_KEYPASSWD, "foobar");

    curl_easy_setopt(handle, CURLOPT_ACCEPT_ENCODING, "gzip,deflate");
    curl_easy_setopt(handle, CURLOPT_URL, "https://example.com");

    CURLcode res = curl_easy_perform(handle);

    long http_code = 0;
    curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_code);

    if (res != CURLE_OK) {
        size_t len = strlen(errbuf);
        printf("\nlibcurl: (%d) ", res);
        if(len)
            printf("%s%s", errbuf, ((errbuf[len - 1] != '\n') ? "\n" : ""));
        else
            printf("%s\n", curl_easy_strerror(res));
    } else {
        printf("OK");
    }
}
xcrun clang -g test.c -I curl-7.84.0/dist/include -L curl-7.84.0/dist/lib -lcurl -lnghttp2 -lz -framework Security -framework CoreFoundation -framework SystemConfiguration

The program will crash on :

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x1b925544c)
  * frame #0: 0x00000001b925544c CoreFoundation`CFRelease.cold.1 + 16
    frame #1: 0x00000001b908838c CoreFoundation`CFRelease + 268
    frame #2: 0x0000000100060574 a.out`CopyIdentityWithLabel(label="thisdoesnotexistinkeychain", out_cert_and_key=0x000000016fdfea00) at sectransp.c:1185:11
    frame #3: 0x000000010005de80 a.out`sectransp_connect_step1(data=0x0000000101808208, conn=0x000000010180ec08, sockindex=0) at sectransp.c:1890:13
    frame #4: 0x000000010005d440 a.out`sectransp_connect_common(data=0x0000000101808208, conn=0x000000010180ec08, sockindex=0, nonblocking=true, done=0x000000016fdfef15) at sectransp.c:3068:14
    frame #5: 0x000000010005d114 a.out`sectransp_connect_nonblocking(data=0x0000000101808208, conn=0x000000010180ec08, sockindex=0, done=0x000000016fdfef15) at sectransp.c:3157:10
    frame #6: 0x0000000100063a94 a.out`Curl_ssl_connect_nonblocking(data=0x0000000101808208, conn=0x000000010180ec08, isproxy=false, sockindex=0, done=0x000000016fdfef15) at vtls.c:371:12
    frame #7: 0x00000001000200d0 a.out`https_connecting(data=0x0000000101808208, done=0x000000016fdfef15) at http.c:1597:12
    frame #8: 0x000000010001ffbc a.out`Curl_http_connect(data=0x0000000101808208, done=0x000000016fdfef15) at http.c:1523:14
    frame #9: 0x000000010003e49c a.out`protocol_connect(data=0x0000000101808208, protocol_done=0x000000016fdfef15) at multi.c:1731:16
    frame #10: 0x000000010003b274 a.out`multi_runsingle(multi=0x0000000100504088, nowp=0x000000016fdfef70, data=0x0000000101808208) at multi.c:2047:16
    frame #11: 0x000000010003aa8c a.out`curl_multi_perform(multi=0x0000000100504088, running_handles=0x000000016fdfefd8) at multi.c:2640:14
    frame #12: 0x0000000100014c04 a.out`easy_transfer(multi=0x0000000100504088) at easy.c:662:15
    frame #13: 0x0000000100013b10 a.out`easy_perform(data=0x0000000101808208, events=false) at easy.c:752:42
    frame #14: 0x0000000100013970 a.out`curl_easy_perform(data=0x0000000101808208) at easy.c:771:10
    frame #15: 0x0000000100000e84 a.out`main at test.c:27:20
    frame #16: 0x00000001000e108c dyld`start + 520

Apparently curl is releasing the keys_list pointer even if nothing has been found by SecItemCopyMatching, which causes the crash. I spent a good few hours on this trying to figure out why keys_list was not NULL, but apparently my C is too rusty to solve this :(

Any help would be greatly appreciated !

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions