<productname>PostgreSQL</productname> was built with
<acronym>SSL</acronym> support, frontend/backend communications
can be encrypted using <acronym>SSL</acronym>. This provides
communication security in environments where attackers might be
able to capture the session traffic. For more information on
encrypting <productname>PostgreSQL</productname> sessions with
<acronym>SSL</acronym>, see <xref linkend="ssl-tcp"/>.
</para>
<para>
To initiate an <acronym>SSL</acronym>-encrypted connection, the
frontend initially sends an SSLRequest message rather than a
StartupMessage. The server then responds with a single byte
containing <literal>S</literal> or <literal>N</literal>, indicating that it is
willing or unwilling to perform <acronym>SSL</acronym>,
respectively. The frontend might close the connection at this point
if it is dissatisfied with the response. To continue after
<literal>S</literal>, perform an <acronym>SSL</acronym> startup handshake
(not described here, part of the <acronym>SSL</acronym>
specification) with the server. If this is successful, continue
with sending the usual StartupMessage. In this case the
StartupMessage and all subsequent data will be
<acronym>SSL</acronym>-encrypted. To continue after
<literal>N</literal>, send the usual StartupMessage and proceed without
encryption.
(Alternatively, it is permissible to issue a GSSENCRequest message
after an <literal>N</literal> response to try to
use <acronym>GSSAPI</acronym> encryption instead
of <acronym>SSL</acronym>.)
</para>
<para>
The frontend should also be prepared to handle an ErrorMessage
response to SSLRequest from the server. The frontend should not display
this error message to the user/application, since the server has not been
authenticated
(<ulink url="https://www.postgresql.org/support/security/CVE-2024-10977/">CVE-2024-10977</ulink>).
In this case the connection must
be closed, but the frontend might choose to open a fresh connection
and proceed without requesting <acronym>SSL</acronym>.
</para>
<para>
When <acronym>SSL</acronym> encryption can be performed, the server
is expected to send only the single <literal>S</literal> byte and then
wait for the frontend to initiate an <acronym>SSL</acronym> handshake.
If additional bytes are available to read at this point, it likely
means that a man-in-the-middle is attempting to perform a
buffer-stuffing attack
(<ulink url="https://www.postgresql.org/support/security/CVE-2021-23222/">CVE-2021-23222</ulink>).
Frontends should be coded either to read exactly one byte from the
socket before turning the socket over to their SSL library, or to
treat it as a protocol violation if they find they have read additional
bytes.
</para>
<para>
Likewise the server expects the client to not begin
the <acronym>SSL</acronym> negotiation until it receives the server's
single byte response to the <acronym>SSL</acronym> request. If the
client begins the <acronym>SSL</acronym> negotiation immediately without
waiting for the server response to be received it can reduce connection
latency by one round-trip. However this comes at the cost of not being
able to handle the case where the server sends a negative response to the
<acronym>SSL</acronym> request. In that case instead of continuing with either GSSAPI or an
unencrypted connection or a protocol error the server will simply
disconnect.
</para>
<para>
An initial SSLRequest can also be used in a connection that is being
opened to send a CancelRequest message.
</para>
<para>
A second alternate way to initiate <acronym>SSL</acronym> encryption is
available. The server will recognize connections which immediately
begin <acronym>SSL</acronym> negotiation without any previous SSLRequest