]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-master: haproxy - Honor PP2 SSL TLV verify and client cert flags
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 23 Apr 2026 10:44:11 +0000 (10:44 +0000)
committertimo.sirainen <timo.sirainen@open-xchange.com>
Thu, 30 Apr 2026 10:26:00 +0000 (10:26 +0000)
Previously the parser ignored both the verify field and the
PP2_CLIENT_CERT_CONN / PP2_CLIENT_CERT_SESS bits in the client byte
of the PP2_TYPE_SSL TLV, and unconditionally copied the client
certificate common name into the connection. This meant that a
common name reported by HAProxy was trusted even when HAProxy itself
had reported a verification failure (verify != 0).

Set ssl_client_cert from the cert presence bits, and only trust the
common name when a client certificate was presented and verified
successfully. When verify is non-zero, the certificate sub-TLVs are
ignored.

src/lib-master/master-service-haproxy.c

index e2129da44631d2745da0d86042ca1230278e5aa8..519cd7944a307e125c1ef7d924bba5080c9ccc9f 100644 (file)
@@ -222,6 +222,16 @@ master_service_haproxy_parse_ssl_tlv(struct master_service_haproxy_conn *hpconn,
 {
        hpconn->conn.haproxy.ssl = (ssl_kv->client & (PP2_CLIENT_SSL)) != 0;
 
+       /* The client byte indicates whether a client certificate was
+          presented on this connection or session. Only trust the
+          sub-TLVs (e.g. the common name) when HAProxy reports the
+          certificate was successfully verified (verify == 0). */
+       bool client_cert_present =
+               (ssl_kv->client &
+                (PP2_CLIENT_CERT_CONN | PP2_CLIENT_CERT_SESS)) != 0;
+       bool client_cert_verified =
+               client_cert_present && ssl_kv->verify == 0;
+
        /* try parse some more */
        for(size_t i = 0; i < ssl_kv->len;) {
                struct haproxy_pp2_tlv kv;
@@ -238,6 +248,8 @@ master_service_haproxy_parse_ssl_tlv(struct master_service_haproxy_conn *hpconn,
                case PP2_SUBTYPE_SSL_KEY_ALG:
                        break;
                case PP2_SUBTYPE_SSL_CN:
+                       if (!client_cert_verified)
+                               break;
                        hpconn->conn.haproxy.cert_common_name =
                                p_strndup(hpconn->pool, kv.data, kv.len);
                        break;