Rename "scram" to "scram-sha-256" in pg_hba.conf and password_encryption.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Tue, 18 Apr 2017 11:50:50 +0000 (14:50 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Tue, 18 Apr 2017 11:50:50 +0000 (14:50 +0300)
Per discussion, plain "scram" is confusing because we actually implement
SCRAM-SHA-256 rather than the original SCRAM that uses SHA-1 as the hash
algorithm. If we add support for SCRAM-SHA-512 or some other mechanism in
the SCRAM family in the future, that would become even more confusing.

Most of the internal files and functions still use just "scram" as a
shorthand for SCRMA-SHA-256, but I did change PASSWORD_TYPE_SCRAM to
PASSWORD_TYPE_SCRAM_SHA_256, as that could potentially be used by 3rd
party extensions that hook into the password-check hook.

Michael Paquier did this in an earlier version of the SCRAM patch set
already, but I didn't include that in the version that was committed.

Discussion: https://www.postgresql.org/message-id/fde71ff1-5858-90c8-99a9-1c2427e7bafb@iki.fi

15 files changed:
doc/src/sgml/client-auth.sgml
doc/src/sgml/config.sgml
src/backend/commands/user.c
src/backend/libpq/auth-scram.c
src/backend/libpq/auth.c
src/backend/libpq/crypt.c
src/backend/libpq/hba.c
src/backend/libpq/pg_hba.conf.sample
src/backend/utils/misc/guc.c
src/bin/initdb/initdb.c
src/include/libpq/crypt.h
src/test/authentication/t/001_password.pl
src/test/authentication/t/002_saslprep.pl
src/test/regress/expected/password.out
src/test/regress/sql/password.sql

index d871c041ce5fe8389f74a2b40ae335b0c18c25d5..819db811b26a684d1b9d124842e56d783ce3af83 100644 (file)
@@ -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>
index 744c5e8f37ac942d368c20353b97be62af2fee8d..e02b0c80df0e824f2e65e332ffde54d08a560538 100644 (file)
@@ -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>
index de264974ae8af4c86056c8787463c0b6fabc21df..c719682274dff70079f6b6357ba1d5ee5155bc13 100644 (file)
@@ -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;
            }
index 338afede9dec2a1813c31dc9f20beb51e60647e6..76c502d415da62d67c416a84312bcb1dc550b087 100644 (file)
@@ -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))
index 848561e188e7d8ef1c90f8df07fc7893c9778e4e..ab4be21943121eac599f99cd43343b586692382f 100644 (file)
@@ -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.
     *
index 34beab53342036321883c9afc46fd556d65acb36..03ef3cc65228646c7b5d25b2f40ade1f971ead60 100644 (file)
@@ -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))
index af89fe898a609759c0cc1247701cbc6376b71a54..5561c399da4643dc3ac7e5e21b1f366f882d602c 100644 (file)
@@ -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
index 6b1778a72136edf52cea56f2ab088b9449df9a48..c853e362329e41db0ef74ae0484891aa65b6ea51 100644 (file)
 # 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
index 9ad8361a9bd6a81bd2ea82c35992946b932528a1..a414fb2c767d98eb55aea3cf8e59712f77187419 100644 (file)
@@ -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},
index d40ed412fc7bb82f6c4caaf5ec08c10cfa2f5b9c..95da8b7722ce47e2348131feeddfa4330edc81d3 100644 (file)
@@ -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);
index 3b5da69b08764713aff410703962b9c249f22105..63724f39ee2044f916f3ad6e81295c88ee59493a 100644 (file)
@@ -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);
index d7bc13bd58e5cea6d048ce9f97deb966012c4934..216bdc031c81c9e46c246a60f8885fb9e6ef749a 100644 (file)
@@ -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.)
index 7e373ed7bf4ca0ad3f713bef9aa6178bfb49f3cf..67ba92cdd9b3e2bcef371fdb97ac8785fbb37af8 100644 (file)
@@ -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);
index c503e43abeb3d31523f5c6af7dba7423a5db39f5..676b3e6ff3f75b63ad4c51a19ec49a68fa895c49 100644 (file)
@@ -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
index f4b3a9ac3a1d6391e6483bd16e123a63fb185563..95557e45660eafb3de9d501ff87c297e68f7a65b 100644 (file)
@@ -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