mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
Support SCRAM-SHA-256 authentication (RFC 5802 and 7677).
This introduces a new generic SASL authentication method, similar to the GSS and SSPI methods. The server first tells the client which SASL authentication mechanism to use, and then the mechanism-specific SASL messages are exchanged in AuthenticationSASLcontinue and PasswordMessage messages. Only SCRAM-SHA-256 is supported at the moment, but this allows adding more SASL mechanisms in the future, without changing the overall protocol. Support for channel binding, aka SCRAM-SHA-256-PLUS is left for later. The SASLPrep algorithm, for pre-processing the password, is not yet implemented. That could cause trouble, if you use a password with non-ASCII characters, and a client library that does implement SASLprep. That will hopefully be added later. Authorization identities, as specified in the SCRAM-SHA-256 specification, are ignored. SET SESSION AUTHORIZATION provides more or less the same functionality, anyway. If a user doesn't exist, perform a "mock" authentication, by constructing an authentic-looking challenge on the fly. The challenge is derived from a new system-wide random value, "mock authentication nonce", which is created at initdb, and stored in the control file. We go through these motions, in order to not give away the information on whether the user exists, to unauthenticated users. Bumps PG_CONTROL_VERSION, because of the new field in control file. Patch by Michael Paquier and Heikki Linnakangas, reviewed at different stages by Robert Haas, Stephen Frost, David Steele, Aleksander Alekseev, and many others. Discussion: https://www.postgresql.org/message-id/CAB7nPqRbR3GmFYdedCAhzukfKrgBLTLtMvENOmPrVWREsZkF8g%40mail.gmail.com Discussion: https://www.postgresql.org/message-id/CAB7nPqSMXU35g%3DW9X74HVeQp0uvgJxvYOuA4A-A3M%2B0wfEBv-w%40mail.gmail.com Discussion: https://www.postgresql.org/message-id/55192AFE.6080106@iki.fi
This commit is contained in:
@ -1334,14 +1334,8 @@
|
||||
<entry><structfield>rolpassword</structfield></entry>
|
||||
<entry><type>text</type></entry>
|
||||
<entry>
|
||||
Password (possibly encrypted); null if none. If the password
|
||||
is encrypted, this column will begin with the string <literal>md5</>
|
||||
followed by a 32-character hexadecimal MD5 hash. The MD5 hash
|
||||
will be of the user's password concatenated to their user name.
|
||||
For example, if user <literal>joe</> has password <literal>xyzzy</>,
|
||||
<productname>PostgreSQL</> will store the md5 hash of
|
||||
<literal>xyzzyjoe</>. A password that does not follow that
|
||||
format is assumed to be unencrypted.
|
||||
Password (possibly encrypted); null if none. The format depends
|
||||
on the form of encryption used.
|
||||
</entry>
|
||||
</row>
|
||||
|
||||
@ -1355,6 +1349,21 @@
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<para>
|
||||
For an MD5 encrypted password, <structfield>rolpassword</structfield>
|
||||
column will begin with the string <literal>md5</> followed by a
|
||||
32-character hexadecimal MD5 hash. The MD5 hash will be of the user's
|
||||
password concatenated to their user name. For example, if user
|
||||
<literal>joe</> has password <literal>xyzzy</>, <productname>PostgreSQL</>
|
||||
will store the md5 hash of <literal>xyzzyjoe</>. If the password is
|
||||
encrypted with SCRAM-SHA-256, it consists of 5 fields separated by colons.
|
||||
The first field is the constant <literal>scram-sha-256</literal>, to
|
||||
identify the password as a SCRAM-SHA-256 verifier. The second field is a
|
||||
salt, Base64-encoded, and the third field is the number of iterations used
|
||||
to generate the password. The fourth field and fifth field are the stored
|
||||
key and server key, respectively, in hexadecimal format. A password that
|
||||
does not follow either of those formats is assumed to be unencrypted.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
|
||||
|
@ -422,6 +422,17 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>scram</></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Perform SCRAM-SHA-256 authentication to verify the user's
|
||||
password.
|
||||
See <xref linkend="auth-password"> for details.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><literal>password</></term>
|
||||
<listitem>
|
||||
@ -673,13 +684,19 @@ host postgres all 192.168.93.0/24 ident
|
||||
# "postgres" if the user's password is correctly supplied.
|
||||
#
|
||||
# TYPE DATABASE USER ADDRESS METHOD
|
||||
host postgres all 192.168.12.10/32 md5
|
||||
host postgres all 192.168.12.10/32 scram
|
||||
|
||||
# Allow any user from hosts in the example.com domain to connect to
|
||||
# any database if the user's password is correctly supplied.
|
||||
#
|
||||
# Most users use SCRAM authentication, but some users use older clients
|
||||
# that don't support SCRAM authentication, and need to be able to log
|
||||
# in using MD5 authentication. Such users are put in the @md5users
|
||||
# group, everyone else must use SCRAM.
|
||||
#
|
||||
# TYPE DATABASE USER ADDRESS METHOD
|
||||
host all all .example.com md5
|
||||
host all @md5users .example.com md5
|
||||
host all all .example.com scram
|
||||
|
||||
# In the absence of preceding "host" lines, these two lines will
|
||||
# reject all connections from 192.168.54.1 (since that entry will be
|
||||
@ -907,21 +924,37 @@ omicron bryanh guest1
|
||||
</indexterm>
|
||||
|
||||
<para>
|
||||
The password-based authentication methods are <literal>md5</>
|
||||
and <literal>password</>. These methods operate
|
||||
The password-based authentication methods are <literal>scram</>
|
||||
<literal>md5</> and <literal>password</>. These methods operate
|
||||
similarly except for the way that the password is sent across the
|
||||
connection, namely MD5-hashed and clear-text respectively.
|
||||
connection.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If you are at all concerned about password
|
||||
<quote>sniffing</> attacks then <literal>md5</> is preferred.
|
||||
Plain <literal>password</> should always be avoided if possible.
|
||||
However, <literal>md5</> cannot be used with the <xref
|
||||
linkend="guc-db-user-namespace"> feature. If the connection is
|
||||
protected by SSL encryption then <literal>password</> can be used
|
||||
safely (though SSL certificate authentication might be a better
|
||||
choice if one is depending on using SSL).
|
||||
Plain <literal>password</> sends the password in clear-text, and is
|
||||
therefore vulnerable to password <quote>sniffing</> attacks. It should
|
||||
always be avoided if possible. If the connection is protected by SSL
|
||||
encryption then <literal>password</> can be used safely, though.
|
||||
(Though SSL certificate authentication might be a better choice if one
|
||||
is depending on using SSL).
|
||||
</para>
|
||||
|
||||
|
||||
<para>
|
||||
<literal>scram</> performs SCRAM-SHA-256 authentication, as described
|
||||
in <ulink url="https://tools.ietf.org/html/rfc5802">RFC5802</ulink>. It
|
||||
is a challenge-response scheme, that prevents password sniffing on
|
||||
untrusted connections. It is more secure than the <literal>md5</>
|
||||
method, but might not be supported by older clients.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In <literal>md5</>, the client sends a hash of a random challenge,
|
||||
generated by the server, and the password. It prevents password sniffing,
|
||||
but is less secure than <literal>scram</>, and provides no protection
|
||||
if an attacker manages to steal the password hash from the server.
|
||||
<literal>md5</> cannot be used with the <xref
|
||||
linkend="guc-db-user-namespace"> feature.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
@ -1193,9 +1193,10 @@ include_dir 'conf.d'
|
||||
password is to be encrypted. The default value is <literal>md5</>, which
|
||||
stores the password as an MD5 hash. Setting this to <literal>plain</> stores
|
||||
it in plaintext. <literal>on</> and <literal>off</> are also accepted, as
|
||||
aliases for <literal>md5</> and <literal>plain</>, respectively.
|
||||
</para>
|
||||
|
||||
aliases for <literal>md5</> and <literal>plain</>, respectively. Setting
|
||||
this parameter to <literal>scram</> will encrypt the password with
|
||||
SCRAM-SHA-256.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
@ -228,11 +228,11 @@
|
||||
The server then sends an appropriate authentication request message,
|
||||
to which the frontend must reply with an appropriate authentication
|
||||
response message (such as a password).
|
||||
For all authentication methods except GSSAPI and SSPI, there is at most
|
||||
one request and one response. In some methods, no response
|
||||
For all authentication methods except GSSAPI, SSPI and SASL, there is at
|
||||
most one request and one response. In some methods, no response
|
||||
at all is needed from the frontend, and so no authentication request
|
||||
occurs. For GSSAPI and SSPI, multiple exchanges of packets may be needed
|
||||
to complete the authentication.
|
||||
occurs. For GSSAPI, SSPI and SASL, multiple exchanges of packets may be
|
||||
needed to complete the authentication.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -366,6 +366,35 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>AuthenticationSASL</term>
|
||||
<listitem>
|
||||
<para>
|
||||
The frontend must now initiate a SASL negotiation, using the SASL
|
||||
mechanism specified in the message. The frontend will send a
|
||||
PasswordMessage with the first part of the SASL data stream in
|
||||
response to this. If further messages are needed, the server will
|
||||
respond with AuthenticationSASLContinue.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>AuthenticationSASLContinue</term>
|
||||
<listitem>
|
||||
<para>
|
||||
This message contains the response data from the previous step
|
||||
of SASL negotiation (AuthenticationSASL, or a previous
|
||||
AuthenticationSASLContinue). If the SASL data in this message
|
||||
indicates more data is needed to complete the authentication,
|
||||
the frontend must send that data as another PasswordMessage. If
|
||||
SASL authentication is completed by this message, the server
|
||||
will next send AuthenticationOk to indicate successful authentication
|
||||
or ErrorResponse to indicate failure.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
@ -2782,6 +2811,114 @@ AuthenticationGSSContinue (B)
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
AuthenticationSASL (B)
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
Byte1('R')
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Identifies the message as an authentication request.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
Int32
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Length of message contents in bytes, including self.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
Int32(10)
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Specifies that SASL authentication is started.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
String
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Name of a SASL authentication mechanism.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
AuthenticationSASLContinue (B)
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>
|
||||
Byte1('R')
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Identifies the message as an authentication request.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
Int32
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Length of message contents in bytes, including self.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
Int32(11)
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Specifies that this message contains SASL-mechanism specific
|
||||
data.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>
|
||||
Byte<replaceable>n</replaceable>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
SASL data, specific to the SASL mechanism being used.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>
|
||||
@ -4544,7 +4681,7 @@ PasswordMessage (F)
|
||||
<listitem>
|
||||
<para>
|
||||
Identifies the message as a password response. Note that
|
||||
this is also used for GSSAPI and SSPI response messages
|
||||
this is also used for GSSAPI, SSPI and SASL response messages
|
||||
(which is really a design error, since the contained data
|
||||
is not a null-terminated string in that case, but can be
|
||||
arbitrary binary data).
|
||||
|
@ -231,12 +231,17 @@ CREATE ROLE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replac
|
||||
encrypted in the system catalogs. (If neither is specified,
|
||||
the default behavior is determined by the configuration
|
||||
parameter <xref linkend="guc-password-encryption">.) If the
|
||||
presented password string is already in MD5-encrypted format,
|
||||
then it is stored encrypted as-is, regardless of whether
|
||||
<literal>ENCRYPTED</> or <literal>UNENCRYPTED</> is specified
|
||||
(since the system cannot decrypt the specified encrypted
|
||||
password string). This allows reloading of encrypted
|
||||
passwords during dump/restore.
|
||||
presented password string is already in MD5-encrypted or
|
||||
SCRAM-encrypted format, then it is stored encrypted as-is,
|
||||
regardless of whether <literal>ENCRYPTED</> or <literal>UNENCRYPTED</>
|
||||
is specified (since the system cannot decrypt the specified encrypted
|
||||
password string). This allows reloading of encrypted passwords
|
||||
during dump/restore.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Note that older clients might lack support for the SCRAM
|
||||
authentication mechanism.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
Reference in New Issue
Block a user