Buy commercial curl support from WolfSSL. We help you work
out your issues, debug your libcurl applications, use the API, port to new
platforms, add new features and more. With a team lead by the curl founder
himself.
curl with openssl not honoring MaxProtocol in openssl conf
- Contemporary messages sorted: [ by date ] [ by thread ] [ by subject ] [ by author ] [ by messages with attachments ]
From: Andreas Hasenack via curl-users <curl-users_at_lists.haxx.se>
Date: Tue, 3 Jan 2023 12:01:18 -0300
Hi,
I'm checking how to restrict crypto algorithms and suites in different
applications linked with openssl, by tweaking the openssl
configuration file. I understand that applications can still override
those settings, but at least I would expect them to follow the
defaults from the openssl config when nothing else is chosen.
Tl;DR: it looks like curl isn't respecting openssl's MaxProtocol[1]. I
tried all versions of Ubuntu from Bionic to Lunar, and it only worked
as expected in Bionic, where it failed to connect to the TLSv1.3-only
server when I had MaxProtocol=TLSv1.2.
Here are the versions:
curl | 7.58.0-2ubuntu3.21 | bionic-security | source
curl | 7.68.0-1ubuntu2.14 | focal-security | source
curl | 7.81.0-1ubuntu1.6 | jammy-security | source
curl | 7.85.0-1ubuntu0.1 | kinetic-security | source
curl | 7.86.0-2 | lunar | source
Build options used are at the end of the email.
In my test scenario, I setup a server (ubuntu Jammy in this case) in
one machine running:
openssl s_server -cert j-server.pem -key j-server.key -tls1_3
Then from another machine, I configure openssl with "MaxProtocol =
TLSv1.2" and attempt to connect to this server. I'm trying with
openssl's native s_client command, then curl, then wget. While
s_client and wget fail correctly, curl always succeeds.
In these tests, the openssl config is at /etc/ssl/openssl.cnf, and I
have the relevant parts like this on the *client* I'm testing:
openssl_conf = openssl_init
[openssl_init]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
CipherString = DEFAULT:@SECLEVEL=2
MaxProtocol = TLSv1.2
a) s_client
$ openssl s_client -connect j-server.lxd:4433;echo $?
CONNECTED(00000003)
40777708747F0000:error:0A00042E:SSL routines:ssl3_read_bytes:tlsv1
alert protocol version:../ssl/record/rec_layer_s3.c:1588:SSL alert
number 70
Date: Tue, 3 Jan 2023 12:01:18 -0300
Hi,
I'm checking how to restrict crypto algorithms and suites in different
applications linked with openssl, by tweaking the openssl
configuration file. I understand that applications can still override
those settings, but at least I would expect them to follow the
defaults from the openssl config when nothing else is chosen.
Tl;DR: it looks like curl isn't respecting openssl's MaxProtocol[1]. I
tried all versions of Ubuntu from Bionic to Lunar, and it only worked
as expected in Bionic, where it failed to connect to the TLSv1.3-only
server when I had MaxProtocol=TLSv1.2.
Here are the versions:
curl | 7.58.0-2ubuntu3.21 | bionic-security | source
curl | 7.68.0-1ubuntu2.14 | focal-security | source
curl | 7.81.0-1ubuntu1.6 | jammy-security | source
curl | 7.85.0-1ubuntu0.1 | kinetic-security | source
curl | 7.86.0-2 | lunar | source
Build options used are at the end of the email.
In my test scenario, I setup a server (ubuntu Jammy in this case) in
one machine running:
openssl s_server -cert j-server.pem -key j-server.key -tls1_3
Then from another machine, I configure openssl with "MaxProtocol =
TLSv1.2" and attempt to connect to this server. I'm trying with
openssl's native s_client command, then curl, then wget. While
s_client and wget fail correctly, curl always succeeds.
In these tests, the openssl config is at /etc/ssl/openssl.cnf, and I
have the relevant parts like this on the *client* I'm testing:
openssl_conf = openssl_init
[openssl_init]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
CipherString = DEFAULT:@SECLEVEL=2
MaxProtocol = TLSv1.2
a) s_client
$ openssl s_client -connect j-server.lxd:4433;echo $?
CONNECTED(00000003)
40777708747F0000:error:0A00042E:SSL routines:ssl3_read_bytes:tlsv1
alert protocol version:../ssl/record/rec_layer_s3.c:1588:SSL alert
number 70
--- no peer certificate available --- No client certificate CA names sent --- SSL handshake has read 7 bytes and written 209 bytes Verification: OK --- New, (NONE), Cipher is (NONE) Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : 0000 Session-ID: Session-ID-ctx: Master-Key: PSK identity: None PSK identity hint: None SRP username: None Start Time: 1672756788 Timeout : 7200 (sec) Verify return code: 0 (ok) Extended master secret: no --- 1 And on the server: 4037782EA77F0000:error:0A000102:SSL routines:tls_early_post_process_client_hello:unsupported protocol:../ssl/statem/statem_srvr.c:1657: b) wget $ wget -O /dev/null https://j-server.lxd:4433 --2023-01-03 14:42:18-- https://j-server.lxd:4433/ Resolving j-server.lxd (j-server.lxd)... 10.0.100.87 Connecting to j-server.lxd (j-server.lxd)|10.0.100.87|:4433... connected. OpenSSL: error:0A00042E:SSL routines::tlsv1 alert protocol version Unable to establish SSL connection. Server errors with the same message as when using s_client. c) curl $ curl -V curl 7.86.0 (x86_64-pc-linux-gnu) libcurl/7.86.0 OpenSSL/3.0.5 zlib/1.2.11 brotli/1.0.9 zstd/1.5.2 libidn2/2.3.3 libpsl/0.21.0 (+libidn2/2.3.2) libssh/0.10.4/openssl/zlib nghttp2/1.50.0 librtmp/2.3 Release-Date: 2022-10-26 Protocols: dict file ftp ftps gopher gophers http https imap imaps ldap ldaps mqtt pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL threadsafe TLS-SRP UnixSockets zstd $ curl -o /dev/null https://j-server.lxd:4433 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- 0:00:04 --:--:-- 0^C And the server logs that TLSv1.3 was used: $ openssl s_server -cert j-server.pem -key j-server.key -tls1_3 Using default temp DH parameters ACCEPT (...) CIPHER is TLS_AES_256_GCM_SHA384 Secure Renegotiation IS supported GET / HTTP/1.1 Host: j-server.lxd:4433 User-Agent: curl/7.86.0 Accept: */* That's a TLSv1.3 ciphersuite, but just to be sure, tshark (tcpdump) confirms tls v1.3 was used: 1 0.000000000 10.0.100.41 → 10.0.100.87 TCP 76 40102 → 4433 [SYN] Seq=0 Win=64240 Len=0 MSS=1460 SACK_PERM=1 TSval=1771368713 TSecr=0 WS=128 2 0.000009574 10.0.100.87 → 10.0.100.41 TCP 76 4433 → 40102 [SYN, ACK] Seq=0 Ack=1 Win=65160 Len=0 MSS=1460 SACK_PERM=1 TSval=2052315130 TSecr=1771368713 WS=128 3 0.000018983 10.0.100.41 → 10.0.100.87 TCP 68 40102 → 4433 [ACK] Seq=1 Ack=1 Win=64256 Len=0 TSval=1771368713 TSecr=2052315130 4 0.025030013 10.0.100.41 → 10.0.100.87 TLSv1 585 Client Hello 5 0.025043788 10.0.100.87 → 10.0.100.41 TCP 68 4433 → 40102 [ACK] Seq=1 Ack=518 Win=64768 Len=0 TSval=2052315155 TSecr=1771368738 6 0.027072337 10.0.100.87 → 10.0.100.41 TLSv1.3 3023 Server Hello, Change Cipher Spec, Application Data, Application Data, Application Data, Application Data 7 0.027098322 10.0.100.41 → 10.0.100.87 TCP 68 40102 → 4433 [ACK] Seq=518 Ack=2956 Win=63488 Len=0 TSval=1771368740 TSecr=2052315157 8 0.028267604 10.0.100.41 → 10.0.100.87 TLSv1.3 148 Change Cipher Spec, Application Data 9 0.028368488 10.0.100.41 → 10.0.100.87 TLSv1.3 171 Application Data 10 0.028473787 10.0.100.87 → 10.0.100.41 TLSv1.3 323 Application Data 11 0.028550592 10.0.100.87 → 10.0.100.41 TLSv1.3 323 Application Data 12 0.028630400 10.0.100.41 → 10.0.100.87 TCP 68 40102 → 4433 [ACK] Seq=701 Ack=3466 Win=64128 Len=0 TSval=1771368741 TSecr=2052315158 curl -v shows an odd mix of TLSv1.2 and TLSv1.3 that I don't understand, but eventually settles on "* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384": $ curl -o /dev/null https://j-server.lxd:4433 -s -v * Trying 10.0.100.87:4433... * Connected to j-server.lxd (10.0.100.87) port 4433 (#0) * ALPN: offers h2 * ALPN: offers http/1.1 * CAfile: /etc/ssl/certs/ca-certificates.crt * CApath: /etc/ssl/certs * TLSv1.0 (OUT), TLS header, Certificate Status (22): } [5 bytes data] * TLSv1.3 (OUT), TLS handshake, Client hello (1): } [512 bytes data] * TLSv1.2 (IN), TLS header, Certificate Status (22): { [5 bytes data] * TLSv1.3 (IN), TLS handshake, Server hello (2): { [122 bytes data] * TLSv1.2 (IN), TLS header, Finished (20): { [5 bytes data] * TLSv1.2 (IN), TLS header, Supplemental data (23): { [5 bytes data] * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): { [6 bytes data] * TLSv1.2 (IN), TLS header, Supplemental data (23): { [5 bytes data] * TLSv1.3 (IN), TLS handshake, Certificate (11): { [2412 bytes data] * TLSv1.2 (IN), TLS header, Supplemental data (23): { [5 bytes data] * TLSv1.3 (IN), TLS handshake, CERT verify (15): { [264 bytes data] * TLSv1.2 (IN), TLS header, Supplemental data (23): { [5 bytes data] * TLSv1.3 (IN), TLS handshake, Finished (20): { [52 bytes data] * TLSv1.2 (OUT), TLS header, Finished (20): } [5 bytes data] * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): } [1 bytes data] * TLSv1.2 (OUT), TLS header, Supplemental data (23): } [5 bytes data] * TLSv1.3 (OUT), TLS handshake, Finished (20): } [52 bytes data] * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN: server did not agree on a protocol. Uses default. * Server certificate: * subject: O=Example Company; CN=j-server.lxd * start date: Jan 3 12:31:18 2023 GMT * expire date: Jan 3 12:31:18 2024 GMT * common name: j-server.lxd (matched) * issuer: CN=Example Company * SSL certificate verify ok. * TLSv1.2 (OUT), TLS header, Supplemental data (23): } [5 bytes data] > GET / HTTP/1.1 > Host: j-server.lxd:4433 > User-Agent: curl/7.86.0 > Accept: */* > * TLSv1.2 (IN), TLS header, Supplemental data (23): { [5 bytes data] * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): { [233 bytes data] * TLSv1.2 (IN), TLS header, Supplemental data (23): { [5 bytes data] * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): { [233 bytes data] * old SSL session ID is stale, removing I've seen this old bug report[2] which looks similar, and suggests it's some quirk in openssl or TLS itself, but given it works as expected in s_client and wget, maybe there is something else that curl is doing? Below I'm showing the summary of the curl build options for bionic (where it works as expected) and lunar (where it uses TLSv1.3 even when MaxProtocol is TLSv1.2). Bionic curl build summary: curl version: 7.58.0 Host setup: x86_64-pc-linux-gnu Install prefix: /usr Compiler: gcc SSL support: enabled (OpenSSL) SSH support: no (--with-libssh2) zlib support: enabled brotli support: no (--with-brotli) GSS-API support: enabled (MIT Kerberos/Heimdal) TLS-SRP support: enabled resolver: POSIX threaded IPv6 support: enabled Unix sockets support: enabled IDN support: enabled (libidn2) Build libcurl: Shared=yes, Static=yes Built-in manual: enabled --libcurl option: enabled (--disable-libcurl-option) Verbose errors: enabled (--disable-verbose) SSPI support: no (--enable-sspi) ca cert bundle: /etc/ssl/certs/ca-certificates.crt ca cert path: /etc/ssl/certs ca fallback: no LDAP support: enabled (OpenLDAP) LDAPS support: enabled RTSP support: enabled RTMP support: enabled (librtmp) metalink support: no (--with-libmetalink) PSL support: yes HTTP2 support: enabled (nghttp2) Protocols: DICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS LDAP LDAPS POP3 POP3S RTMP RTSP SMB SMBS SMTP SMTPS TELNET TFTP Lunar build summary: Host setup: x86_64-pc-linux-gnu Install prefix: /usr Compiler: gcc CFLAGS: -g -O2 -ffile-prefix-map=/<<PKGBUILDDIR>>=. -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -Werror-implicit-function-declaration -Wno-system-headers CPPFLAGS: -Wdate-time -D_FORTIFY_SOURCE=2 -isystem /usr/include/mit-krb5 -DOPENSSL_SUPPRESS_DEPRECATED LDFLAGS: -Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -flto=auto -Wl,-z,relro -Wl,-z,now LIBS: -lnghttp2 -lidn2 -lrtmp -lssh -lssh -lpsl -lssl -lcrypto -lssl -lcrypto -L/usr/lib/x86_64-linux-gnu/mit-krb5 -lgssapi_krb5 -llber -lldap -llber -lzstd -lbrotlidec -lz curl version: 7.86.0 SSL: enabled (OpenSSL v3+) SSH: enabled (libSSH) zlib: enabled brotli: enabled (libbrotlidec) zstd: enabled (libzstd) GSS-API: enabled (MIT Kerberos/Heimdal) GSASL: no (libgsasl not found) TLS-SRP: enabled resolver: POSIX threaded IPv6: enabled Unix sockets: enabled IDN: enabled (libidn2) Build libcurl: Shared=yes, Static=yes Built-in manual: enabled --libcurl option: enabled (--disable-libcurl-option) Verbose errors: enabled (--disable-verbose) Code coverage: disabled SSPI: no (--enable-sspi) ca cert bundle: /etc/ssl/certs/ca-certificates.crt ca cert path: /etc/ssl/certs ca fallback: no LDAP: enabled (OpenLDAP) LDAPS: enabled RTSP: enabled RTMP: enabled (librtmp) PSL: enabled Alt-svc: enabled (--disable-alt-svc) Headers API: enabled (--disable-headers-api) HSTS: enabled (--disable-hsts) HTTP1: enabled (internal) HTTP2: enabled (nghttp2) HTTP3: no (--with-ngtcp2, --with-quiche --with-msh3) ECH: no (--enable-ech) WebSockets: no (--enable-websockets) Protocols: DICT FILE FTP FTPS GOPHER GOPHERS HTTP HTTPS IMAP IMAPS LDAP LDAPS MQTT POP3 POP3S RTMP RTSP SCP SFTP SMB SMBS SMTP SMTPS TELNET TFTP Features: AsynchDNS GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets alt-svc brotli libz threadsafe zstd This could all still be a build problem, as the package in Ubuntu and Debian builds in a quite complex way, with 3 different builds and packaging split to accommodate that. It would perhaps be helpful if others could try to replicate my simple test. Thanks, and sorry for the long email. 1. https://www.openssl.org/docs/man3.0/man3/SSL_CONF_cmd.html#MaxProtocol 2. https://github.com/curl/curl/issues/5356 -- Unsubscribe: https://lists.haxx.se/listinfo/curl-users Etiquette: https://curl.se/mail/etiquette.htmlReceived on 2023-01-03