libpq: Enforce ALPN in direct SSL connections
authorHeikki Linnakangas <[email protected]>
Mon, 29 Apr 2024 15:12:24 +0000 (18:12 +0300)
committerHeikki Linnakangas <[email protected]>
Mon, 29 Apr 2024 15:12:24 +0000 (18:12 +0300)
ALPN is mandatory with direct SSL connections. That is documented, and
the server checks it, but libpq was missing the check.

Reported-by: Jacob Champion
Reviewed-by: Michael Paquier
Discussion: https://www.postgresql.org/message-id/CAOYmi+=sj+1uydS0NR4nYzw-LRWp3Q-s5speBug5UCLSPMbvGA@mail.gmail.com

src/interfaces/libpq/fe-secure-openssl.c

index 33362000d3c94d09a09ae048d7a9983092dc4e9a..0de21dc7e456c764b503c631cbf3131c9f87fec8 100644 (file)
@@ -1585,6 +1585,34 @@ open_client_SSL(PGconn *conn)
        }
    }
 
+   /* ALPN is mandatory with direct SSL connections */
+   if (conn->current_enc_method == ENC_DIRECT_SSL)
+   {
+       const unsigned char *selected;
+       unsigned int len;
+
+       SSL_get0_alpn_selected(conn->ssl, &selected, &len);
+
+       if (selected == NULL)
+       {
+           libpq_append_conn_error(conn, "direct SSL connection was established without ALPN protocol negotiation extension");
+           pgtls_close(conn);
+           return PGRES_POLLING_FAILED;
+       }
+
+       /*
+        * We only support one protocol so that's what the negotiation should
+        * always choose, but doesn't hurt to check.
+        */
+       if (len != strlen(PG_ALPN_PROTOCOL) ||
+           memcmp(selected, PG_ALPN_PROTOCOL, strlen(PG_ALPN_PROTOCOL)) != 0)
+       {
+           libpq_append_conn_error(conn, "SSL connection was established with unexpected ALPN protocol");
+           pgtls_close(conn);
+           return PGRES_POLLING_FAILED;
+       }
+   }
+
    /*
     * We already checked the server certificate in initialize_SSL() using
     * SSL_CTX_set_verify(), if root.crt exists.