]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: ssl/cli: crash when crt inserted into a crt-list
authorWilliam Lallemand <wlallemand@haproxy.org>
Mon, 20 Jun 2022 14:51:53 +0000 (16:51 +0200)
committerWilliam Lallemand <wlallemand@haproxy.org>
Mon, 20 Jun 2022 15:27:49 +0000 (17:27 +0200)
The crash occures when the same certificate which is used on both a
server line and a bind line is inserted in a crt-list over the CLI.

This is quite uncommon as using the same file for a client and a server
certificate does not make sense in a lot of environments.

This patch fixes the issue by skipping the insertion of the SNI when no
bind_conf is available in the ckch_inst.

Change the reg-test to reproduce this corner case.

Should fix issue #1748.

Must be backported as far as 2.2. (it was previously in ssl_sock.c)

reg-tests/ssl/add_ssl_crt-list.vtc
src/ssl_crtlist.c

index 5ed72bfe25a796960a42c7f9225bf2765829901a..e62ac48925cfa520ef762e4dc85eb1cf77e729ea 100644 (file)
@@ -50,6 +50,7 @@ haproxy h1 -conf {
         bind "${tmpdir}/ssl.sock" ssl strict-sni crt-list ${testdir}/localhost.crt-list
 
         server s1 ${s1_addr}:${s1_port}
+        server s2 ${s1_addr}:${s1_port} ssl crt "${testdir}/common.pem" weight 0 verify none
 } -start
 
 
@@ -68,6 +69,7 @@ shell {
     echo "new ssl cert ${testdir}/ecdsa.pem" | socat "${tmpdir}/h1/stats" -
     printf "set ssl cert ${testdir}/ecdsa.pem <<\n$(cat ${testdir}/ecdsa.pem)\n\n" | socat "${tmpdir}/h1/stats" -
     echo "commit ssl cert ${testdir}/ecdsa.pem" | socat "${tmpdir}/h1/stats" -
+    printf "add ssl crt-list ${testdir}/localhost.crt-list/ <<\n${testdir}/common.pem [ssl-min-ver SSLv3 verify none allow-0rtt] !*\n\n" | socat "${tmpdir}/h1/stats" -
     printf "add ssl crt-list ${testdir}/localhost.crt-list/ <<\n${testdir}/ecdsa.pem [ssl-min-ver SSLv3 verify none allow-0rtt] localhost !www.test1.com\n\n" | socat "${tmpdir}/h1/stats" -
     printf "add ssl crt-list ${testdir}/localhost.crt-list <<\n${testdir}/ecdsa.pem [verify none allow-0rtt]\n\n" | socat "${tmpdir}/h1/stats" -
     printf "add ssl crt-list ${testdir}/localhost.crt-list/// <<\n${testdir}/ecdsa.pem localhost !www.test1.com\n\n" | socat "${tmpdir}/h1/stats" -
index 8aa4eae2a6e508b2f0ea6a761254bca94a9f1557..a8cd240441c9d50f33a6e35c18b68507df4d8921 100644 (file)
@@ -1138,8 +1138,15 @@ static int cli_io_handler_add_crtlist(struct appctx *appctx)
                ctx->state = ADDCRT_ST_INSERT;
                /* fallthrough */
        case ADDCRT_ST_INSERT:
-               /* insert SNIs in bind_conf */
+               /* the insertion is called for every instance of the store, not
+                * only the one we generated.
+                * But the ssl_sock_load_cert_sni() skip the sni already
+                * inserted. Not every instance has a bind_conf, it could be
+                * the store of a server so we should be careful */
+
                list_for_each_entry(new_inst, &store->ckch_inst, by_ckchs) {
+                       if (!new_inst->bind_conf) /* this is a server instance */
+                               continue;
                        HA_RWLOCK_WRLOCK(SNI_LOCK, &new_inst->bind_conf->sni_lock);
                        ssl_sock_load_cert_sni(new_inst, new_inst->bind_conf);
                        HA_RWLOCK_WRUNLOCK(SNI_LOCK, &new_inst->bind_conf->sni_lock);