diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index d871c041ce5fe8389f74a2b40ae335b0c18c25d5..819db811b26a684d1b9d124842e56d783ce3af83 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -412,7 +412,7 @@ hostnossl <replaceable>database</replaceable> <replaceable>user</replaceable> </varlistentry> <varlistentry> - <term><literal>scram</></term> + <term><literal>scram-sha-256</></term> <listitem> <para> Perform SCRAM-SHA-256 authentication to verify the user's @@ -683,7 +683,7 @@ 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 scram +host postgres all 192.168.12.10/32 scram-sha-256 # Allow any user from hosts in the example.com domain to connect to # any database if the user's password is correctly supplied. @@ -694,7 +694,7 @@ host postgres all 192.168.12.10/32 scram # # TYPE DATABASE USER ADDRESS METHOD host all mike .example.com md5 -host all all .example.com scram +host all all .example.com scram-sha-256 # In the absence of preceding "host" lines, these two lines will # reject all connections from 192.168.54.1 (since that entry will be @@ -922,7 +922,7 @@ omicron bryanh guest1 </indexterm> <para> - The password-based authentication methods are <literal>scram</>, + The password-based authentication methods are <literal>scram-sha-256</>, <literal>md5</>, and <literal>password</>. These methods operate similarly except for the way that the password is sent across the connection. @@ -939,8 +939,9 @@ omicron bryanh guest1 <para> - <literal>scram</> performs SCRAM-SHA-256 authentication, as described - in <ulink url="https://tools.ietf.org/html/rfc5802">RFC5802</ulink>. It + <literal>scram-sha-256</> 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. @@ -953,7 +954,7 @@ omicron bryanh guest1 protection if an attacker manages to steal the password hash from the server, and it cannot be used with the <xref linkend="guc-db-user-namespace"> feature. For all other users, - <literal>md5</> works the same as <literal>scram</>. + <literal>md5</> works the same as <literal>scram-sha-256</>. </para> <para> diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 744c5e8f37ac942d368c20353b97be62af2fee8d..e02b0c80df0e824f2e65e332ffde54d08a560538 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1194,8 +1194,8 @@ include_dir 'conf.d' 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. Setting - this parameter to <literal>scram</> will encrypt the password with - SCRAM-SHA-256. + this parameter to <literal>scram-sha-256</> will encrypt the password + with SCRAM-SHA-256. </para> </listitem> </varlistentry> diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index de264974ae8af4c86056c8787463c0b6fabc21df..c719682274dff70079f6b6357ba1d5ee5155bc13 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -140,8 +140,8 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt) dpassword = defel; if (strcmp(defel->defname, "encryptedPassword") == 0) { - if (Password_encryption == PASSWORD_TYPE_SCRAM) - password_type = PASSWORD_TYPE_SCRAM; + if (Password_encryption == PASSWORD_TYPE_SCRAM_SHA_256) + password_type = PASSWORD_TYPE_SCRAM_SHA_256; else password_type = PASSWORD_TYPE_MD5; } @@ -548,8 +548,8 @@ AlterRole(AlterRoleStmt *stmt) dpassword = defel; if (strcmp(defel->defname, "encryptedPassword") == 0) { - if (Password_encryption == PASSWORD_TYPE_SCRAM) - password_type = PASSWORD_TYPE_SCRAM; + if (Password_encryption == PASSWORD_TYPE_SCRAM_SHA_256) + password_type = PASSWORD_TYPE_SCRAM_SHA_256; else password_type = PASSWORD_TYPE_MD5; } diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c index 338afede9dec2a1813c31dc9f20beb51e60647e6..76c502d415da62d67c416a84312bcb1dc550b087 100644 --- a/src/backend/libpq/auth-scram.c +++ b/src/backend/libpq/auth-scram.c @@ -183,7 +183,7 @@ pg_be_scram_init(const char *username, const char *shadow_pass) { int password_type = get_password_type(shadow_pass); - if (password_type == PASSWORD_TYPE_SCRAM) + if (password_type == PASSWORD_TYPE_SCRAM_SHA_256) { if (parse_scram_verifier(shadow_pass, &state->salt, &state->iterations, state->StoredKey, state->ServerKey)) diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index 848561e188e7d8ef1c90f8df07fc7893c9778e4e..ab4be21943121eac599f99cd43343b586692382f 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -50,7 +50,7 @@ static char *recv_password_packet(Port *port); /*---------------------------------------------------------------- - * Password-based authentication methods (password, md5, and scram) + * Password-based authentication methods (password, md5, and scram-sha-256) *---------------------------------------------------------------- */ static int CheckPasswordAuth(Port *port, char **logdetail); @@ -757,10 +757,10 @@ CheckPWChallengeAuth(Port *port, char **logdetail) * If the user does not exist, or has no password, we still go through the * motions of authentication, to avoid revealing to the client that the * user didn't exist. If 'md5' is allowed, we choose whether to use 'md5' - * or 'scram' authentication based on current password_encryption setting. - * The idea is that most genuine users probably have a password of that - * type, if we pretend that this user had a password of that type, too, it - * "blends in" best. + * or 'scram-sha-256' authentication based on current password_encryption + * setting. The idea is that most genuine users probably have a password + * of that type, if we pretend that this user had a password of that type, + * too, it "blends in" best. * * If the user had a password, but it was expired, we'll use the details * of the expired password for the authentication, but report it as @@ -773,9 +773,9 @@ CheckPWChallengeAuth(Port *port, char **logdetail) /* * If 'md5' authentication is allowed, decide whether to perform 'md5' or - * 'scram' authentication based on the type of password the user has. If - * it's an MD5 hash, we must do MD5 authentication, and if it's a SCRAM - * verifier, we must do SCRAM authentication. If it's stored in + * 'scram-sha-256' authentication based on the type of password the user + * has. If it's an MD5 hash, we must do MD5 authentication, and if it's + * a SCRAM verifier, we must do SCRAM authentication. If it's stored in * plaintext, we could do either one, so we opt for the more secure * mechanism, SCRAM. * diff --git a/src/backend/libpq/crypt.c b/src/backend/libpq/crypt.c index 34beab53342036321883c9afc46fd556d65acb36..03ef3cc65228646c7b5d25b2f40ade1f971ead60 100644 --- a/src/backend/libpq/crypt.c +++ b/src/backend/libpq/crypt.c @@ -101,7 +101,7 @@ get_password_type(const char *shadow_pass) if (strncmp(shadow_pass, "md5", 3) == 0 && strlen(shadow_pass) == MD5_PASSWD_LEN) return PASSWORD_TYPE_MD5; if (strncmp(shadow_pass, "scram-sha-256:", strlen("scram-sha-256:")) == 0) - return PASSWORD_TYPE_SCRAM; + return PASSWORD_TYPE_SCRAM_SHA_256; return PASSWORD_TYPE_PLAINTEXT; } @@ -141,7 +141,7 @@ encrypt_password(PasswordType target_type, const char *role, elog(ERROR, "password encryption failed"); return encrypted_password; - case PASSWORD_TYPE_SCRAM: + case PASSWORD_TYPE_SCRAM_SHA_256: /* * cannot convert a SCRAM verifier to an MD5 hash, so fall @@ -152,7 +152,7 @@ encrypt_password(PasswordType target_type, const char *role, } break; - case PASSWORD_TYPE_SCRAM: + case PASSWORD_TYPE_SCRAM_SHA_256: switch (guessed_type) { case PASSWORD_TYPE_PLAINTEXT: @@ -164,7 +164,7 @@ encrypt_password(PasswordType target_type, const char *role, * cannot convert an MD5 hash to a SCRAM verifier, so fall * through to save the MD5 hash instead. */ - case PASSWORD_TYPE_SCRAM: + case PASSWORD_TYPE_SCRAM_SHA_256: return pstrdup(password); } break; @@ -280,7 +280,7 @@ plain_crypt_verify(const char *role, const char *shadow_pass, */ switch (get_password_type(shadow_pass)) { - case PASSWORD_TYPE_SCRAM: + case PASSWORD_TYPE_SCRAM_SHA_256: if (scram_verify_plain_password(role, client_pass, shadow_pass)) diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index af89fe898a609759c0cc1247701cbc6376b71a54..5561c399da4643dc3ac7e5e21b1f366f882d602c 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -126,7 +126,7 @@ static const char *const UserAuthName[] = "ident", "password", "md5", - "scram", + "scram-sha256", "gss", "sspi", "pam", @@ -1327,7 +1327,7 @@ parse_hba_line(TokenizedLine *tok_line, int elevel) } parsedline->auth_method = uaMD5; } - else if (strcmp(token->string, "scram") == 0) + else if (strcmp(token->string, "scram-sha-256") == 0) parsedline->auth_method = uaSCRAM; else if (strcmp(token->string, "pam") == 0) #ifdef USE_PAM diff --git a/src/backend/libpq/pg_hba.conf.sample b/src/backend/libpq/pg_hba.conf.sample index 6b1778a72136edf52cea56f2ab088b9449df9a48..c853e362329e41db0ef74ae0484891aa65b6ea51 100644 --- a/src/backend/libpq/pg_hba.conf.sample +++ b/src/backend/libpq/pg_hba.conf.sample @@ -42,10 +42,10 @@ # or "samenet" to match any address in any subnet that the server is # directly connected to. # -# METHOD can be "trust", "reject", "md5", "password", "scram", "gss", -# "sspi", "ident", "peer", "pam", "ldap", "radius" or "cert". Note that -# "password" sends passwords in clear text; "md5" or "scram" are preferred -# since they send encrypted passwords. +# METHOD can be "trust", "reject", "md5", "password", "scram-sha-256", +# "gss", "sspi", "ident", "peer", "pam", "ldap", "radius" or "cert". +# Note that "password" sends passwords in clear text; "md5" or +# "scram-sha-256" are preferred since they send encrypted passwords. # # OPTIONS are a set of options for the authentication in the format # NAME=VALUE. The available options depend on the different diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 9ad8361a9bd6a81bd2ea82c35992946b932528a1..a414fb2c767d98eb55aea3cf8e59712f77187419 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -410,7 +410,7 @@ static const struct config_enum_entry force_parallel_mode_options[] = { static const struct config_enum_entry password_encryption_options[] = { {"plain", PASSWORD_TYPE_PLAINTEXT, false}, {"md5", PASSWORD_TYPE_MD5, false}, - {"scram", PASSWORD_TYPE_SCRAM, false}, + {"scram-sha-256", PASSWORD_TYPE_SCRAM_SHA_256, false}, {"off", PASSWORD_TYPE_PLAINTEXT, false}, {"on", PASSWORD_TYPE_MD5, false}, {"true", PASSWORD_TYPE_MD5, true}, diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index d40ed412fc7bb82f6c4caaf5ec08c10cfa2f5b9c..95da8b7722ce47e2348131feeddfa4330edc81d3 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -77,7 +77,7 @@ extern const char *select_default_timezone(const char *share_path); static const char *const auth_methods_host[] = { - "trust", "reject", "md5", "password", "scram", "ident", "radius", + "trust", "reject", "scram-sha-256", "md5", "password", "ident", "radius", #ifdef ENABLE_GSS "gss", #endif @@ -99,7 +99,7 @@ static const char *const auth_methods_host[] = { NULL }; static const char *const auth_methods_local[] = { - "trust", "reject", "md5", "scram", "password", "peer", "radius", + "trust", "reject", "scram-sha-256", "md5", "password", "peer", "radius", #ifdef USE_PAM "pam", "pam ", #endif @@ -1130,12 +1130,12 @@ setup_config(void) "#update_process_title = off"); #endif - if (strcmp(authmethodlocal, "scram") == 0 || - strcmp(authmethodhost, "scram") == 0) + if (strcmp(authmethodlocal, "scram-sha-256") == 0 || + strcmp(authmethodhost, "scram-sha-256") == 0) { conflines = replace_token(conflines, "#password_encryption = md5", - "password_encryption = scram"); + "password_encryption = scram-sha-256"); } snprintf(path, sizeof(path), "%s/postgresql.conf", pg_data); @@ -2329,16 +2329,16 @@ check_need_password(const char *authmethodlocal, const char *authmethodhost) { if ((strcmp(authmethodlocal, "md5") == 0 || strcmp(authmethodlocal, "password") == 0 || - strcmp(authmethodlocal, "scram") == 0) && + strcmp(authmethodlocal, "scram-sha-256") == 0) && (strcmp(authmethodhost, "md5") == 0 || strcmp(authmethodhost, "password") == 0 || - strcmp(authmethodhost, "scram") == 0) && + strcmp(authmethodhost, "scram-sha-256") == 0) && !(pwprompt || pwfilename)) { fprintf(stderr, _("%s: must specify a password for the superuser to enable %s authentication\n"), progname, (strcmp(authmethodlocal, "md5") == 0 || strcmp(authmethodlocal, "password") == 0 || - strcmp(authmethodlocal, "scram") == 0) + strcmp(authmethodlocal, "scram-sha-256") == 0) ? authmethodlocal : authmethodhost); exit(1); diff --git a/src/include/libpq/crypt.h b/src/include/libpq/crypt.h index 3b5da69b08764713aff410703962b9c249f22105..63724f39ee2044f916f3ad6e81295c88ee59493a 100644 --- a/src/include/libpq/crypt.h +++ b/src/include/libpq/crypt.h @@ -25,7 +25,7 @@ typedef enum PasswordType { PASSWORD_TYPE_PLAINTEXT = 0, PASSWORD_TYPE_MD5, - PASSWORD_TYPE_SCRAM + PASSWORD_TYPE_SCRAM_SHA_256 } PasswordType; extern PasswordType get_password_type(const char *shadow_pass); diff --git a/src/test/authentication/t/001_password.pl b/src/test/authentication/t/001_password.pl index d7bc13bd58e5cea6d048ce9f97deb966012c4934..216bdc031c81c9e46c246a60f8885fb9e6ef749a 100644 --- a/src/test/authentication/t/001_password.pl +++ b/src/test/authentication/t/001_password.pl @@ -51,7 +51,7 @@ SKIP: # Create 3 roles with different password methods for each one. The same # password is used for all of them. - $node->safe_psql('postgres', "SET password_encryption='scram'; CREATE ROLE scram_role LOGIN PASSWORD 'pass';"); + $node->safe_psql('postgres', "SET password_encryption='scram-sha-256'; CREATE ROLE scram_role LOGIN PASSWORD 'pass';"); $node->safe_psql('postgres', "SET password_encryption='md5'; CREATE ROLE md5_role LOGIN PASSWORD 'pass';"); $node->safe_psql('postgres', "SET password_encryption='plain'; CREATE ROLE plain_role LOGIN PASSWORD 'pass';"); $ENV{"PGPASSWORD"} = 'pass'; @@ -68,12 +68,12 @@ SKIP: test_role($node, 'md5_role', 'password', 0); test_role($node, 'plain_role', 'password', 0); - # For "scram" method, user "plain_role" and "scram_role" should be able to - # connect. - reset_pg_hba($node, 'scram'); - test_role($node, 'scram_role', 'scram', 0); - test_role($node, 'md5_role', 'scram', 2); - test_role($node, 'plain_role', 'scram', 0); + # For "scram-sha-256" method, user "plain_role" and "scram_role" should + # be able to connect. + reset_pg_hba($node, 'scram-sha-256'); + test_role($node, 'scram_role', 'scram-sha-256', 0); + test_role($node, 'md5_role', 'scram-sha-256', 2); + test_role($node, 'plain_role', 'scram-sha-256', 0); # For "md5" method, all users should be able to connect (SCRAM # authentication will be performed for the user with a scram verifier.) diff --git a/src/test/authentication/t/002_saslprep.pl b/src/test/authentication/t/002_saslprep.pl index 7e373ed7bf4ca0ad3f713bef9aa6178bfb49f3cf..67ba92cdd9b3e2bcef371fdb97ac8785fbb37af8 100644 --- a/src/test/authentication/t/002_saslprep.pl +++ b/src/test/authentication/t/002_saslprep.pl @@ -63,7 +63,7 @@ SKIP: # Create test roles. $node->safe_psql('postgres', -"SET password_encryption='scram'; +"SET password_encryption='scram-sha-256'; SET client_encoding='utf8'; CREATE ROLE saslpreptest1_role LOGIN PASSWORD 'IX'; CREATE ROLE saslpreptest4a_role LOGIN PASSWORD 'a'; @@ -73,7 +73,7 @@ SKIP: "); # Require password from now on. - reset_pg_hba($node, 'scram'); + reset_pg_hba($node, 'scram-sha-256'); # Check that #1 and #5 are treated the same as just 'IX' test_login($node, 'saslpreptest1_role', "I\xc2\xadX", 0); diff --git a/src/test/regress/expected/password.out b/src/test/regress/expected/password.out index c503e43abeb3d31523f5c6af7dba7423a5db39f5..676b3e6ff3f75b63ad4c51a19ec49a68fa895c49 100644 --- a/src/test/regress/expected/password.out +++ b/src/test/regress/expected/password.out @@ -4,11 +4,11 @@ -- Tests for GUC password_encryption SET password_encryption = 'novalue'; -- error ERROR: invalid value for parameter "password_encryption": "novalue" -HINT: Available values: plain, md5, scram, off, on. +HINT: Available values: plain, md5, scram-sha-256, off, on. SET password_encryption = true; -- ok SET password_encryption = 'md5'; -- ok SET password_encryption = 'plain'; -- ok -SET password_encryption = 'scram'; -- ok +SET password_encryption = 'scram-sha-256'; -- ok -- consistency of password entries SET password_encryption = 'plain'; CREATE ROLE regress_passwd1 PASSWORD 'role_pwd1'; @@ -16,7 +16,7 @@ SET password_encryption = 'md5'; CREATE ROLE regress_passwd2 PASSWORD 'role_pwd2'; SET password_encryption = 'on'; CREATE ROLE regress_passwd3 PASSWORD 'role_pwd3'; -SET password_encryption = 'scram'; +SET password_encryption = 'scram-sha-256'; CREATE ROLE regress_passwd4 PASSWORD 'role_pwd4'; SET password_encryption = 'plain'; CREATE ROLE regress_passwd5 PASSWORD NULL; @@ -60,7 +60,7 @@ ALTER ROLE regress_passwd2 UNENCRYPTED PASSWORD 'md5dfa155cadd5f4ad57860162f3fab SET password_encryption = 'md5'; ALTER ROLE regress_passwd3 ENCRYPTED PASSWORD 'foo'; -- encrypted with MD5 ALTER ROLE regress_passwd4 ENCRYPTED PASSWORD 'scram-sha-256:VLK4RMaQLCvNtQ==:4096:3ded2376f7aafa93b1bdbd71bcc18b7d6ee50ed018029cc583d152ef3fc7d430:a6dd36dfc94c181956a6ae95f05e01b1864f0a22a2657d1de4ba84d2a24dc438'; -- client-supplied SCRAM verifier, use as it is -SET password_encryption = 'scram'; +SET password_encryption = 'scram-sha-256'; ALTER ROLE regress_passwd5 ENCRYPTED PASSWORD 'foo'; -- create SCRAM verifier CREATE ROLE regress_passwd6 ENCRYPTED PASSWORD 'md53725413363ab045e20521bf36b8d8d7f'; -- encrypted with MD5, use as it is SELECT rolname, regexp_replace(rolpassword, '(scram-sha-256):([a-zA-Z0-9+/]+==):(\d+):(\w+):(\w+)', '\1:<salt>:\3:<storedkey>:<serverkey>') as rolpassword_masked diff --git a/src/test/regress/sql/password.sql b/src/test/regress/sql/password.sql index f4b3a9ac3a1d6391e6483bd16e123a63fb185563..95557e45660eafb3de9d501ff87c297e68f7a65b 100644 --- a/src/test/regress/sql/password.sql +++ b/src/test/regress/sql/password.sql @@ -7,7 +7,7 @@ SET password_encryption = 'novalue'; -- error SET password_encryption = true; -- ok SET password_encryption = 'md5'; -- ok SET password_encryption = 'plain'; -- ok -SET password_encryption = 'scram'; -- ok +SET password_encryption = 'scram-sha-256'; -- ok -- consistency of password entries SET password_encryption = 'plain'; @@ -16,7 +16,7 @@ SET password_encryption = 'md5'; CREATE ROLE regress_passwd2 PASSWORD 'role_pwd2'; SET password_encryption = 'on'; CREATE ROLE regress_passwd3 PASSWORD 'role_pwd3'; -SET password_encryption = 'scram'; +SET password_encryption = 'scram-sha-256'; CREATE ROLE regress_passwd4 PASSWORD 'role_pwd4'; SET password_encryption = 'plain'; CREATE ROLE regress_passwd5 PASSWORD NULL; @@ -50,7 +50,7 @@ ALTER ROLE regress_passwd3 ENCRYPTED PASSWORD 'foo'; -- encrypted with MD5 ALTER ROLE regress_passwd4 ENCRYPTED PASSWORD 'scram-sha-256:VLK4RMaQLCvNtQ==:4096:3ded2376f7aafa93b1bdbd71bcc18b7d6ee50ed018029cc583d152ef3fc7d430:a6dd36dfc94c181956a6ae95f05e01b1864f0a22a2657d1de4ba84d2a24dc438'; -- client-supplied SCRAM verifier, use as it is -SET password_encryption = 'scram'; +SET password_encryption = 'scram-sha-256'; ALTER ROLE regress_passwd5 ENCRYPTED PASSWORD 'foo'; -- create SCRAM verifier CREATE ROLE regress_passwd6 ENCRYPTED PASSWORD 'md53725413363ab045e20521bf36b8d8d7f'; -- encrypted with MD5, use as it is