diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index ec20e3f3a9..f9156e29ca 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -3524,6 +3524,13 @@ keep_going: /* We will come back to here until there is pollres = pqsecure_open_client(conn); if (pollres == PGRES_POLLING_OK) { + /* ALPN is mandatory with direct SSL negotiation */ + if (conn->current_enc_method == ENC_DIRECT_SSL && !conn->ssl_alpn_used) + { + libpq_append_conn_error(conn, "direct SSL connection was established without ALPN protocol negotiation extension"); + CONNECTION_FAILED(); + } + /* * At this point we should have no data already buffered. * If we do, it was received before we performed the SSL diff --git a/src/interfaces/libpq/fe-secure-openssl.c b/src/interfaces/libpq/fe-secure-openssl.c index e7a4d006e1..8df3c751db 100644 --- a/src/interfaces/libpq/fe-secure-openssl.c +++ b/src/interfaces/libpq/fe-secure-openssl.c @@ -1585,6 +1585,31 @@ open_client_SSL(PGconn *conn) } } + /* Get the protocol selected by ALPN */ + { + const unsigned char *selected; + unsigned int len; + + SSL_get0_alpn_selected(conn->ssl, &selected, &len); + + /* If ALPN is used, check that we negotiated the expected protocol */ + if (selected != NULL) + { + if (len == strlen(PG_ALPN_PROTOCOL) && + memcmp(selected, PG_ALPN_PROTOCOL, strlen(PG_ALPN_PROTOCOL)) == 0) + { + conn->ssl_alpn_used = true; + } + else + { + /* shouldn't happen */ + 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. @@ -1632,6 +1657,7 @@ pgtls_close(PGconn *conn) conn->ssl = NULL; conn->ssl_in_use = false; conn->ssl_handshake_started = false; + conn->ssl_alpn_used = false; destroy_needed = true; } diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index 3691e5ee96..a6792917cf 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -569,6 +569,7 @@ struct pg_conn bool ssl_handshake_started; bool ssl_cert_requested; /* Did the server ask us for a cert? */ bool ssl_cert_sent; /* Did we send one in reply? */ + bool ssl_alpn_used; /* Did we negotiate a protocol with TLS ALPN? */ #ifdef USE_SSL #ifdef USE_OPENSSL