Skip to content

Commit a34c18a

Browse files
committed
Apply 0007-Support-for-SCRAM-SHA-256-authentication-RFC-5802-an.patch, fix all conflicts
1 parent a338a0d commit a34c18a

File tree

31 files changed

+2438
-73
lines changed

31 files changed

+2438
-73
lines changed

contrib/passwordcheck/passwordcheck.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#endif
2222

2323
#include "commands/user.h"
24+
#include "libpq/scram.h"
2425
#include "fmgr.h"
2526
#include "libpq/md5.h"
2627

@@ -57,14 +58,15 @@ check_password(const char *username,
5758
{
5859
int namelen = strlen(username);
5960
int pwdlen = strlen(password);
60-
char encrypted[MD5_PASSWD_LEN + 1];
61+
char *encrypted;
6162
int i;
6263
bool pwd_has_letter,
6364
pwd_has_nonletter;
6465

6566
switch (password_type)
6667
{
6768
case PASSWORD_TYPE_MD5:
69+
case PASSWORD_TYPE_SCRAM:
6870

6971
/*
7072
* Unfortunately we cannot perform exhaustive checks on encrypted
@@ -74,12 +76,23 @@ check_password(const char *username,
7476
*
7577
* We only check for username = password.
7678
*/
77-
if (!pg_md5_encrypt(username, username, namelen, encrypted))
78-
elog(ERROR, "password encryption failed");
79+
if (password_type == PASSWORD_TYPE_MD5)
80+
{
81+
encrypted = palloc(MD5_PASSWD_LEN + 1);
82+
if (pg_md5_encrypt(username, username, namelen, encrypted))
83+
elog(ERROR, "password encryption failed");
84+
}
85+
else if (password_type == PASSWORD_TYPE_SCRAM)
86+
{
87+
encrypted = scram_build_verifier(username, password, 0);
88+
}
89+
else
90+
Assert(0); /* should not happen */
7991
if (strcmp(password, encrypted) == 0)
8092
ereport(ERROR,
8193
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
8294
errmsg("password must not contain user name")));
95+
pfree(encrypted);
8396
break;
8497

8598
case PASSWORD_TYPE_PLAINTEXT:

doc/src/sgml/client-auth.sgml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -661,17 +661,24 @@ host all all localhost trust
661661
host postgres all 192.168.93.0/24 ident
662662

663663
# Allow any user from host 192.168.12.10 to connect to database
664-
# "postgres" if the user's password is correctly supplied.
664+
# "postgres" if the user's password is correctly supplied and is
665+
# using the correct password method.
665666
#
666667
# TYPE DATABASE USER ADDRESS METHOD
667668
host postgres all 192.168.12.10/32 md5
669+
host postgres all 192.168.12.10/32 scram
668670

669671
# Allow any user from hosts in the example.com domain to connect to
670-
# any database if the user's password is correctly supplied.
672+
# any database if the user's password is correctly supplied and is using
673+
# a MD5-encrypted password.
671674
#
672675
# TYPE DATABASE USER ADDRESS METHOD
673676
host all all .example.com md5
674677

678+
# Same as previous entry, except that the supplied password must be
679+
# encrypted with SCRAM-SHA-256.
680+
host all all .example.com scram
681+
675682
# In the absence of preceding "host" lines, these two lines will
676683
# reject all connections from 192.168.54.1 (since that entry will be
677684
# matched first), but allow GSSAPI connections from anywhere else
@@ -899,9 +906,9 @@ omicron bryanh guest1
899906

900907
<para>
901908
The password-based authentication methods are <literal>md5</>
902-
and <literal>password</>. These methods operate
909+
<literal>scram</> and <literal>password</>. These methods operate
903910
similarly except for the way that the password is sent across the
904-
connection, namely MD5-hashed and clear-text respectively.
911+
connection, namely MD5-hashed, SCRAM-SHA-256 and clear-text respectively.
905912
</para>
906913

907914
<para>

doc/src/sgml/config.sgml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,9 +1179,10 @@ include_dir 'conf.d'
11791179
password is to be encrypted. The default value is <literal>md5</>, which
11801180
stores the password as an MD5 hash. Setting this to <literal>plain</> stores
11811181
it in plaintext. <literal>on</> and <literal>off</> are also accepted, as
1182-
aliases for <literal>md5</> and <literal>plain</>, respectively.
1183-
</para>
1184-
1182+
aliases for <literal>md5</> and <literal>plain</>, respectively. Setting
1183+
this parameter to <literal>scram</> will encrypt the password with
1184+
SCRAM-SHA-256.
1185+
</para>
11851186
</listitem>
11861187
</varlistentry>
11871188

doc/src/sgml/protocol.sgml

Lines changed: 142 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,11 @@
228228
The server then sends an appropriate authentication request message,
229229
to which the frontend must reply with an appropriate authentication
230230
response message (such as a password).
231-
For all authentication methods except GSSAPI and SSPI, there is at most
232-
one request and one response. In some methods, no response
231+
For all authentication methods except GSSAPI, SSPI and SASL, there is at
232+
most one request and one response. In some methods, no response
233233
at all is needed from the frontend, and so no authentication request
234-
occurs. For GSSAPI and SSPI, multiple exchanges of packets may be needed
235-
to complete the authentication.
234+
occurs. For GSSAPI, SSPI and SASL, multiple exchanges of packets may be
235+
needed to complete the authentication.
236236
</para>
237237

238238
<para>
@@ -366,6 +366,35 @@
366366
</listitem>
367367
</varlistentry>
368368

369+
<varlistentry>
370+
<term>AuthenticationSASL</term>
371+
<listitem>
372+
<para>
373+
The frontend must now initiate a SASL negotiation, using the SASL
374+
mechanism specified in the message. The frontend will send a
375+
PasswordMessage with the first part of the SASL data stream in
376+
response to this. If further messages are needed, the server will
377+
respond with AuthenticationSASLContinue.
378+
</para>
379+
</listitem>
380+
381+
</varlistentry>
382+
<varlistentry>
383+
<term>AuthenticationSASLContinue</term>
384+
<listitem>
385+
<para>
386+
This message contains the response data from the previous step
387+
of SASL negotiation (AuthenticationSASL, or a previous
388+
AuthenticationSASLContinue). If the SASL data in this message
389+
indicates more data is needed to complete the authentication,
390+
the frontend must send that data as another PasswordMessage. If
391+
SASL authentication is completed by this message, the server
392+
will next send AuthenticationOk to indicate successful authentication
393+
or ErrorResponse to indicate failure.
394+
</para>
395+
</listitem>
396+
</varlistentry>
397+
369398
</variablelist>
370399
</para>
371400

@@ -2578,6 +2607,114 @@ AuthenticationGSSContinue (B)
25782607
</listitem>
25792608
</varlistentry>
25802609

2610+
<varlistentry>
2611+
<term>
2612+
AuthenticationSASL (B)
2613+
</term>
2614+
<listitem>
2615+
<para>
2616+
2617+
<variablelist>
2618+
<varlistentry>
2619+
<term>
2620+
Byte1('R')
2621+
</term>
2622+
<listitem>
2623+
<para>
2624+
Identifies the message as an authentication request.
2625+
</para>
2626+
</listitem>
2627+
</varlistentry>
2628+
<varlistentry>
2629+
<term>
2630+
Int32
2631+
</term>
2632+
<listitem>
2633+
<para>
2634+
Length of message contents in bytes, including self.
2635+
</para>
2636+
</listitem>
2637+
</varlistentry>
2638+
<varlistentry>
2639+
<term>
2640+
Int32(10)
2641+
</term>
2642+
<listitem>
2643+
<para>
2644+
Specifies that SASL authentication is started.
2645+
</para>
2646+
</listitem>
2647+
</varlistentry>
2648+
<varlistentry>
2649+
<term>
2650+
String
2651+
</term>
2652+
<listitem>
2653+
<para>
2654+
Name of a SASL authentication mechanism.
2655+
</para>
2656+
</listitem>
2657+
</varlistentry>
2658+
</variablelist>
2659+
2660+
</para>
2661+
</listitem>
2662+
</varlistentry>
2663+
2664+
<varlistentry>
2665+
<term>
2666+
AuthenticationSASLContinue (B)
2667+
</term>
2668+
<listitem>
2669+
<para>
2670+
2671+
<variablelist>
2672+
<varlistentry>
2673+
<term>
2674+
Byte1('R')
2675+
</term>
2676+
<listitem>
2677+
<para>
2678+
Identifies the message as an authentication request.
2679+
</para>
2680+
</listitem>
2681+
</varlistentry>
2682+
<varlistentry>
2683+
<term>
2684+
Int32
2685+
</term>
2686+
<listitem>
2687+
<para>
2688+
Length of message contents in bytes, including self.
2689+
</para>
2690+
</listitem>
2691+
</varlistentry>
2692+
<varlistentry>
2693+
<term>
2694+
Int32(11)
2695+
</term>
2696+
<listitem>
2697+
<para>
2698+
Specifies that this message contains SASL-mechanism specific
2699+
data.
2700+
</para>
2701+
</listitem>
2702+
</varlistentry>
2703+
<varlistentry>
2704+
<term>
2705+
Byte<replaceable>n</replaceable>
2706+
</term>
2707+
<listitem>
2708+
<para>
2709+
SASL data, specific to the SASL mechanism being used.
2710+
</para>
2711+
</listitem>
2712+
</varlistentry>
2713+
</variablelist>
2714+
2715+
</para>
2716+
</listitem>
2717+
</varlistentry>
25812718

25822719
<varlistentry>
25832720
<term>
@@ -4340,7 +4477,7 @@ PasswordMessage (F)
43404477
<listitem>
43414478
<para>
43424479
Identifies the message as a password response. Note that
4343-
this is also used for GSSAPI and SSPI response messages
4480+
this is also used for GSSAPI, SSPI and SASL response messages
43444481
(which is really a design error, since the contained data
43454482
is not a null-terminated string in that case, but can be
43464483
arbitrary binary data).

doc/src/sgml/ref/create_role.sgml

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -229,16 +229,16 @@ CREATE ROLE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replac
229229
encrypted in the system catalogs. (If neither is specified,
230230
the default behavior is determined by the configuration
231231
parameter <xref linkend="guc-password-encryption">.) If the
232-
presented password string is already in MD5-encrypted format,
233-
then it is stored encrypted as-is, regardless of whether
234-
<literal>ENCRYPTED</> or <literal>UNENCRYPTED</> is specified
235-
(since the system cannot decrypt the specified encrypted
236-
password string). This allows reloading of encrypted
237-
passwords during dump/restore.
232+
presented password string is already in MD5-encrypted or
233+
SCRAM-encrypted format, then it is stored encrypted as-is,
234+
regardless of whether <literal>ENCRYPTED</> or <literal>UNENCRYPTED</>
235+
is specified (since the system cannot decrypt the specified encrypted
236+
password string). This allows reloading of encrypted passwords
237+
during dump/restore.
238238
</para>
239239

240240
<para>
241-
Note that older clients might lack support for the MD5
241+
Note that older clients might lack support for the MD5 or SCRAM
242242
authentication mechanism that is needed to work with passwords
243243
that are stored encrypted.
244244
</para>
@@ -254,10 +254,11 @@ CREATE ROLE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replac
254254
attribute, but you can nonetheless define one for roles without it.)
255255
If you do not plan to use password authentication you can omit this
256256
option. The methods supported are <literal>md5</> to enforce
257-
a password to be MD5-encrypted, and <literal>plain</> to use an
258-
unencrypted password. If the password string is already in
259-
MD5-encrypted format, then it is stored encrypted even if
260-
<literal>plain</> is specified.
257+
a password to be MD5-encrypted, <literal>scram</> to enforce a password
258+
to be encrypted with SCRAM-SHA-256, and <literal>plain</> to use
259+
an unencrypted password. If the password string is already in
260+
MD5-encrypted or SCRAM-SHA-256 format, then it is stored encrypted
261+
even if another protocol is specified.
261262
</para>
262263
</listitem>
263264
</varlistentry>

0 commit comments

Comments
 (0)