Re: Direct SSL connection with ALPN and HBA rules
Heikki Linnakangas <hlinnaka@iki.fi>
From: Heikki Linnakangas <hlinnaka@iki.fi>
To: Jacob Champion <jacob.champion@enterprisedb.com>
Cc: Michael Paquier <michael@paquier.xyz>,
Postgres hackers <pgsql-hackers@lists.postgresql.org>
Date: 2024-04-26T22:50:54Z
Lists: pgsql-hackers
Attachments
- 0001-Reject-SSL-connection-if-ALPN-is-used-but-there-s-no.patch (text/x-patch) patch 0001
On 23/04/2024 20:02, Jacob Champion wrote:
> On Fri, Apr 19, 2024 at 2:43 PM Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>>
>> On 19/04/2024 19:48, Jacob Champion wrote:
>>> On Fri, Apr 19, 2024 at 6:56 AM Heikki Linnakangas <hlinnaka@iki.fi> wrote:
>>>> With direct SSL negotiation, we always require ALPN.
>>>
>>> (As an aside: I haven't gotten to test the version of the patch that
>>> made it into 17 yet, but from a quick glance it looks like we're not
>>> rejecting mismatched ALPN during the handshake as noted in [1].)
>>
>> Ah, good catch, that fell through the cracks. Agreed, the client should
>> reject a direct SSL connection if the server didn't send ALPN. I'll add
>> that to the Open Items so we don't forget again.
>
> Yes, the client should also reject, but that's not what I'm referring
> to above. The server needs to fail the TLS handshake itself with the
> proper error code (I think it's `no_application_protocol`?); otherwise
> a client implementing a different protocol could consume the
> application-level bytes coming back from the server and act on them.
> That's the protocol confusion attack from ALPACA we're trying to
> avoid.
I finally understood what you mean. So if the client supports ALPN, but
the list of protocols that it provides does not include 'postgresql',
the server should reject the connection with 'no_applicaton_protocol'
alert. Makes sense. I thought OpenSSL would do that with the alpn
callback we have, but it does not.
The attached patch makes that change. I used the alpn_cb() function in
openssl's own s_server program as example for that.
Unfortunately the error message you got in the client with that was
horrible (I modified the server to not accept the 'postgresql' protocol):
psql "dbname=postgres sslmode=require host=localhost"
psql: error: connection to server at "localhost" (::1), port 5432
failed: SSL error: SSL error code 167773280
This is similar to the case with system errors discussed at
https://postgr.es/m/b6fb018b-f05c-4afd-abd3-318c649faf18@highgo.ca, but
this one is equally bad on OpenSSL 1.1.1 and 3.3.0. It seems like an
OpenSSL bug to me, because there is an error string "no application
protocol" in the OpenSSL sources (ssl/ssl_err.c):
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NO_APPLICATION_PROTOCOL),
"no application protocol"},
and in the server log, you get that message. But the error code seen in
the client is different. There are also messages for other alerts, for
example:
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_TLSV13_ALERT_MISSING_EXTENSION),
"tlsv13 alert missing extension"},
The bottom line is that that seems like a bug of omission to me in
OpenSSL, but I wouldn't hold my breath waiting for it to be fixed. We
can easily check for that error code and print the right message
ourselves however, as in the attached patch.
--
Heikki Linnakangas
Neon (https://neon.tech)
Commits
-
Remove option to fall back from direct to postgres SSL negotiation
- fb5718f35ff6 17.0 landed
-
Reject SSL connection if ALPN is used but there's no common protocol
- 17a834a04d5a 17.0 landed
-
libpq: Enforce ALPN in direct SSL connections
- 03a0e0d4bb78 17.0 landed
-
libpq: If ALPN is not used, make PQsslAttribute(conn, "alpn") == ""
- 3c184092651b 17.0 landed
-
Fix documentation and comments on what happens after GSS rejection
- 5c9f35fc48ea 17.0 landed
-
doc: Add note to prevent server spoofing with SCRAM
- d0f4824a5410 16.0 cited