]> granicus.if.org Git - postgresql/commitdiff
Remove support for password_encryption='off' / 'plain'.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 8 May 2017 08:26:07 +0000 (11:26 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Mon, 8 May 2017 08:26:07 +0000 (11:26 +0300)
Storing passwords in plaintext hasn't been a good idea for a very long
time, if ever. Now seems like a good time to finally forbid it, since we're
messing with this in PostgreSQL 10 anyway.

Remove the CREATE/ALTER USER UNENCRYPTED PASSSWORD 'foo' syntax, since
storing passwords unencrypted is no longer supported. ENCRYPTED PASSWORD
'foo' is still accepted, but ENCRYPTED is now just a noise-word, it does
the same as just PASSWORD 'foo'.

Likewise, remove the --unencrypted option from createuser, but accept
--encrypted as a no-op for backward compatibility. AFAICS, --encrypted was
a no-op even before this patch, because createuser encrypted the password
before sending it to the server even if --encrypted was not specified. It
added the ENCRYPTED keyword to the SQL command, but since the password was
already in encrypted form, it didn't make any difference. The documentation
was not clear on whether that was intended or not, but it's moot now.

Also, while password_encryption='on' is still accepted as an alias for
'md5', it is now marked as hidden, so that it is not listed as an accepted
value in error hints, for example. That's not directly related to removing
'plain', but it seems better this way.

Reviewed by Michael Paquier

Discussion: https://www.postgresql.org/message-id/16e9b768-fd78-0b12-cfc1-7b6b7f238fde@iki.fi

21 files changed:
contrib/passwordcheck/passwordcheck.c
doc/src/sgml/config.sgml
doc/src/sgml/ref/alter_role.sgml
doc/src/sgml/ref/alter_user.sgml
doc/src/sgml/ref/create_group.sgml
doc/src/sgml/ref/create_role.sgml
doc/src/sgml/ref/create_user.sgml
doc/src/sgml/ref/createuser.sgml
src/backend/commands/user.c
src/backend/libpq/auth-scram.c
src/backend/libpq/auth.c
src/backend/libpq/crypt.c
src/backend/parser/gram.y
src/backend/utils/misc/guc.c
src/bin/psql/tab-complete.c
src/bin/scripts/createuser.c
src/include/libpq/crypt.h
src/interfaces/libpq/fe-auth.c
src/test/authentication/t/001_password.pl
src/test/regress/expected/password.out
src/test/regress/sql/password.sql

index c988bf5169b95df00ac2577e8b7414856d385615..59f73a1e6ba0b28148d22c7ec63f1bb0e8877d95 100644 (file)
@@ -39,8 +39,8 @@ extern void _PG_init(void);
  *
  * username: name of role being created or changed
  * password: new password (possibly already encrypted)
- * password_type: PASSWORD_TYPE_PLAINTEXT or PASSWORD_TYPE_MD5 (there
- *                     could be other encryption schemes in future)
+ * password_type: PASSWORD_TYPE_* code, to indicate if the password is
+ *                     in plaintext or encrypted form.
  * validuntil_time: password expiration time, as a timestamptz Datum
  * validuntil_null: true if password expiration time is NULL
  *
index 0b9e3002fb64f6ad113ca6926aa2da85669c9c6c..20bc3c61b12e48339dccb549e02c2f3fabfde6ae 100644 (file)
@@ -1188,14 +1188,16 @@ include_dir 'conf.d'
       <listitem>
        <para>
         When a password is specified in <xref linkend="sql-createrole"> or
-        <xref linkend="sql-alterrole"> without writing either <literal>ENCRYPTED</>
-        or <literal>UNENCRYPTED</>, this parameter determines whether the
-        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.  Setting
-        this parameter to <literal>scram-sha-256</> will encrypt the password
-        with SCRAM-SHA-256.
+        <xref linkend="sql-alterrole">, this parameter determines the algorithm
+        to use to encrypt the password. The default value is <literal>md5</>,
+        which stores the password as an MD5 hash (<literal>on</> is also
+        accepted, as alias for <literal>md5</>). Setting this parameter to
+        <literal>scram-sha-256</> will encrypt the password with SCRAM-SHA-256.
+       </para>
+       <para>
+        Note that older clients might lack support for the SCRAM authentication
+        mechanism, and hence not work with passwords encrypted with
+        SCRAM-SHA-256.
        </para>
       </listitem>
      </varlistentry>
index 37fcfb926c11169f0ce0584046c58e2b86b84182..8cd8602bc4f692adc17f99e11a4740477e18646f 100644 (file)
@@ -33,7 +33,7 @@ ALTER ROLE <replaceable class="PARAMETER">role_specification</replaceable> [ WIT
     | REPLICATION | NOREPLICATION
     | BYPASSRLS | NOBYPASSRLS
     | CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
-    | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
+    | [ ENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
     | VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
 
 ALTER ROLE <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
@@ -168,9 +168,7 @@ ALTER ROLE { <replaceable class="PARAMETER">role_specification</replaceable> | A
       <term><literal>BYPASSRLS</literal></term>
       <term><literal>NOBYPASSRLS</literal></term>
       <term><literal>CONNECTION LIMIT</literal> <replaceable class="parameter">connlimit</replaceable></term>
-      <term><literal>PASSWORD</> <replaceable class="parameter">password</replaceable></term>
-      <term><literal>ENCRYPTED</></term>
-      <term><literal>UNENCRYPTED</></term>
+      <term>[ <literal>ENCRYPTED</> ] <literal>PASSWORD</> <replaceable class="parameter">password</replaceable></term>
       <term><literal>VALID UNTIL</literal> '<replaceable class="parameter">timestamp</replaceable>'</term>
       <listitem>
        <para>
index 5962a8e166c6f0fa8fce791a10c47d6d342f23ca..9b8a39b37681209700f207e123806ea0833d9edb 100644 (file)
@@ -33,7 +33,7 @@ ALTER USER <replaceable class="PARAMETER">role_specification</replaceable> [ WIT
     | REPLICATION | NOREPLICATION
     | BYPASSRLS | NOBYPASSRLS
     | CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
-    | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
+    | [ ENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
     | VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
 
 ALTER USER <replaceable class="PARAMETER">name</replaceable> RENAME TO <replaceable>new_name</replaceable>
index 1d5cc9b5969842985fc657c27d3becd3a3f6af0e..158617cb9391c9af84c34df19eedb9df39083f5a 100644 (file)
@@ -30,7 +30,7 @@ CREATE GROUP <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <repla
     | CREATEROLE | NOCREATEROLE
     | INHERIT | NOINHERIT
     | LOGIN | NOLOGIN
-    | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
+    | [ ENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
     | VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
     | IN ROLE <replaceable class="PARAMETER">role_name</replaceable> [, ...]
     | IN GROUP <replaceable class="PARAMETER">role_name</replaceable> [, ...]
index 99d1c8336c405f67380dd0097012d298ffd0f4e0..43f2303b4817686ec761de016678b4f58f408ff6 100644 (file)
@@ -33,7 +33,7 @@ CREATE ROLE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replac
     | REPLICATION | NOREPLICATION
     | BYPASSRLS | NOBYPASSRLS
     | CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
-    | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
+    | [ ENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
     | VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
     | IN ROLE <replaceable class="PARAMETER">role_name</replaceable> [, ...]
     | IN GROUP <replaceable class="PARAMETER">role_name</replaceable> [, ...]
@@ -207,7 +207,7 @@ CREATE ROLE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replac
      </varlistentry>
 
      <varlistentry>
-      <term><literal>PASSWORD</> <replaceable class="parameter">password</replaceable></term>
+      <term>[ <literal>ENCRYPTED</> ] <literal>PASSWORD</> <replaceable class="parameter">password</replaceable></term>
       <listitem>
        <para>
         Sets the role's password.  (A password is only of use for
@@ -219,30 +219,18 @@ CREATE ROLE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replac
         user.  A null password can optionally be written explicitly as
         <literal>PASSWORD NULL</literal>.
        </para>
-      </listitem>
-     </varlistentry>
-
-     <varlistentry>
-      <term><literal>ENCRYPTED</></term>
-      <term><literal>UNENCRYPTED</></term>
-      <listitem>
        <para>
-        These key words control whether the password is stored
-        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 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
+        The password is always stored encrypted in the system catalogs. The
+        <literal>ENCRYPTED</> keyword has no effect, but is accepted for
+        backwards compatibility. The method of encryption is determined
+        by the configuration parameter <xref linkend="guc-password-encryption">.
+        If the presented password string is already in MD5-encrypted or
+        SCRAM-encrypted format, then it is stored as-is regardless of
+        <varname>password_encryption</> (since the system cannot decrypt
+        the specified encrypted password string, to encrypt it in a
+        different format).  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>
 
index 574604f796d7a55211fdad7d24f2ae72918869b0..8a596eec9f2511ca2768fdb9cab68f7e3162975a 100644 (file)
@@ -33,7 +33,7 @@ CREATE USER <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replac
     | REPLICATION | NOREPLICATION
     | BYPASSRLS | NOBYPASSRLS
     | CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
-    | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
+    | [ ENCRYPTED ] PASSWORD '<replaceable class="PARAMETER">password</replaceable>'
     | VALID UNTIL '<replaceable class="PARAMETER">timestamp</replaceable>'
     | IN ROLE <replaceable class="PARAMETER">role_name</replaceable> [, ...]
     | IN GROUP <replaceable class="PARAMETER">role_name</replaceable> [, ...]
index 4332008c68bd69d1192d730d5cf1d66b4d147ca8..fda77976ff29f479a8154b70fffb55041fc10d18 100644 (file)
@@ -124,8 +124,8 @@ PostgreSQL documentation
       <term><option>--encrypted</></term>
       <listitem>
        <para>
-        Encrypts the user's password stored in the database. If not
-        specified, the default password behavior is used.
+        This option is obsolete but still accepted for backward
+        compatibility.
        </para>
       </listitem>
      </varlistentry>
@@ -204,17 +204,6 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
-     <varlistentry>
-      <term><option>-N</></term>
-      <term><option>--unencrypted</></term>
-      <listitem>
-       <para>
-        Does not encrypt the user's password stored in the database. If
-        not specified, the default password behavior is used.
-       </para>
-      </listitem>
-     </varlistentry>
-
      <varlistentry>
       <term><option>-P</></term>
       <term><option>--pwprompt</></term>
@@ -481,11 +470,7 @@ PostgreSQL documentation
 </screen>
     In the above example, the new password isn't actually echoed when typed,
     but we show what was typed for clarity.  As you see, the password is
-    encrypted before it is sent to the client.  If the option <option>--unencrypted</option>
-    is used, the password <emphasis>will</> appear in the echoed command
-    (and possibly also in the server log and elsewhere),
-    so you don't want to use <option>-e</> in that case, if
-    anyone else can see your screen.
+    encrypted before it is sent to the client.
    </para>
  </refsect1>
 
index c719682274dff70079f6b6357ba1d5ee5155bc13..36d5f40f0626d572f81c39712dee49ea85af88bb 100644 (file)
@@ -80,7 +80,6 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
        ListCell   *item;
        ListCell   *option;
        char       *password = NULL;    /* user password */
-       int                     password_type = Password_encryption;
        bool            issuper = false;        /* Make the user a superuser? */
        bool            inherit = true; /* Auto inherit privileges? */
        bool            createrole = false;             /* Can this user create roles? */
@@ -128,9 +127,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
        {
                DefElem    *defel = (DefElem *) lfirst(option);
 
-               if (strcmp(defel->defname, "password") == 0 ||
-                       strcmp(defel->defname, "encryptedPassword") == 0 ||
-                       strcmp(defel->defname, "unencryptedPassword") == 0)
+               if (strcmp(defel->defname, "password") == 0)
                {
                        if (dpassword)
                                ereport(ERROR,
@@ -138,15 +135,6 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
                                                 errmsg("conflicting or redundant options"),
                                                 parser_errposition(pstate, defel->location)));
                        dpassword = defel;
-                       if (strcmp(defel->defname, "encryptedPassword") == 0)
-                       {
-                               if (Password_encryption == PASSWORD_TYPE_SCRAM_SHA_256)
-                                       password_type = PASSWORD_TYPE_SCRAM_SHA_256;
-                               else
-                                       password_type = PASSWORD_TYPE_MD5;
-                       }
-                       else if (strcmp(defel->defname, "unencryptedPassword") == 0)
-                               password_type = PASSWORD_TYPE_PLAINTEXT;
                }
                else if (strcmp(defel->defname, "sysid") == 0)
                {
@@ -400,7 +388,8 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
                /* Encrypt the password to the requested format. */
                char       *shadow_pass;
 
-               shadow_pass = encrypt_password(password_type, stmt->role, password);
+               shadow_pass = encrypt_password(Password_encryption, stmt->role,
+                                                                          password);
                new_record[Anum_pg_authid_rolpassword - 1] =
                        CStringGetTextDatum(shadow_pass);
        }
@@ -503,7 +492,6 @@ AlterRole(AlterRoleStmt *stmt)
        ListCell   *option;
        char       *rolename = NULL;
        char       *password = NULL;    /* user password */
-       int                     password_type = Password_encryption;
        int                     issuper = -1;   /* Make the user a superuser? */
        int                     inherit = -1;   /* Auto inherit privileges? */
        int                     createrole = -1;        /* Can this user create roles? */
@@ -537,24 +525,13 @@ AlterRole(AlterRoleStmt *stmt)
        {
                DefElem    *defel = (DefElem *) lfirst(option);
 
-               if (strcmp(defel->defname, "password") == 0 ||
-                       strcmp(defel->defname, "encryptedPassword") == 0 ||
-                       strcmp(defel->defname, "unencryptedPassword") == 0)
+               if (strcmp(defel->defname, "password") == 0)
                {
                        if (dpassword)
                                ereport(ERROR,
                                                (errcode(ERRCODE_SYNTAX_ERROR),
                                                 errmsg("conflicting or redundant options")));
                        dpassword = defel;
-                       if (strcmp(defel->defname, "encryptedPassword") == 0)
-                       {
-                               if (Password_encryption == PASSWORD_TYPE_SCRAM_SHA_256)
-                                       password_type = PASSWORD_TYPE_SCRAM_SHA_256;
-                               else
-                                       password_type = PASSWORD_TYPE_MD5;
-                       }
-                       else if (strcmp(defel->defname, "unencryptedPassword") == 0)
-                               password_type = PASSWORD_TYPE_PLAINTEXT;
                }
                else if (strcmp(defel->defname, "superuser") == 0)
                {
@@ -809,7 +786,8 @@ AlterRole(AlterRoleStmt *stmt)
                /* Encrypt the password to the requested format. */
                char       *shadow_pass;
 
-               shadow_pass = encrypt_password(password_type, rolename, password);
+               shadow_pass = encrypt_password(Password_encryption, rolename,
+                                                                          password);
                new_record[Anum_pg_authid_rolpassword - 1] =
                        CStringGetTextDatum(shadow_pass);
                new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
index 3acc2acfe417aebc2452ce695748184e518fea2f..99feb0ce9477cdafa9919934f5c6a421e55105d4 100644 (file)
@@ -199,27 +199,11 @@ pg_be_scram_init(const char *username, const char *shadow_pass)
                                got_verifier = false;
                        }
                }
-               else if (password_type == PASSWORD_TYPE_PLAINTEXT)
-               {
-                       /*
-                        * The stored password is in plain format.  Generate a fresh SCRAM
-                        * verifier from it, and proceed with that.
-                        */
-                       char       *verifier;
-
-                       verifier = pg_be_scram_build_verifier(shadow_pass);
-
-                       (void) parse_scram_verifier(verifier, &state->iterations, &state->salt,
-                                                                               state->StoredKey, state->ServerKey);
-                       pfree(verifier);
-
-                       got_verifier = true;
-               }
                else
                {
                        /*
-                        * The user doesn't have SCRAM verifier, nor could we generate
-                        * one. (You cannot do SCRAM authentication with an MD5 hash.)
+                        * The user doesn't have SCRAM verifier. (You cannot do SCRAM
+                        * authentication with an MD5 hash.)
                         */
                        state->logdetail = psprintf(_("User \"%s\" does not have a valid SCRAM verifier."),
                                                                                state->username);
index ab4be21943121eac599f99cd43343b586692382f..6d3ff68607dcf8e06a4fbb0127917c1d97be4f3d 100644 (file)
@@ -754,17 +754,13 @@ CheckPWChallengeAuth(Port *port, char **logdetail)
        shadow_pass = get_role_password(port->user_name, 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-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
-        * failure to the client even if correct password was given.
+        * If the user does not exist, or has no password or it's expired, 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-sha-256' authentication based on
+        * current password_encryption setting.  The idea is that most genuine
+        * users probably have a password of that type, and if we pretend that
+        * this user had a password of that type, too, it "blends in" best.
         */
        if (!shadow_pass)
                pwtype = Password_encryption;
@@ -775,21 +771,15 @@ CheckPWChallengeAuth(Port *port, char **logdetail)
         * If 'md5' authentication is allowed, decide whether to perform 'md5' or
         * '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.
+        * a SCRAM verifier, we must do SCRAM authentication.
         *
         * If MD5 authentication is not allowed, always use SCRAM.  If the user
         * had an MD5 password, CheckSCRAMAuth() will fail.
         */
        if (port->hba->auth_method == uaMD5 && pwtype == PASSWORD_TYPE_MD5)
-       {
                auth_result = CheckMD5Auth(port, shadow_pass, logdetail);
-       }
        else
-       {
                auth_result = CheckSCRAMAuth(port, shadow_pass, logdetail);
-       }
 
        if (shadow_pass)
                pfree(shadow_pass);
index 9fe79b48946386bffca7a6fe27c914b5ec9599ef..e7a6b04fb5a549355f9011c81047288c185d459f 100644 (file)
@@ -109,9 +109,8 @@ get_password_type(const char *shadow_pass)
  * Given a user-supplied password, convert it into a verifier of
  * 'target_type' kind.
  *
- * If the password looks like a valid MD5 hash, it is stored as it is.
- * We cannot reverse the hash, so even if the caller requested a plaintext
- * plaintext password, the MD5 hash is returned.
+ * If the password is already in encrypted form, we cannot reverse the
+ * hash, so it is stored as it is regardless of the requested type.
  */
 char *
 encrypt_password(PasswordType target_type, const char *role,
@@ -120,54 +119,30 @@ encrypt_password(PasswordType target_type, const char *role,
        PasswordType guessed_type = get_password_type(password);
        char       *encrypted_password;
 
-       switch (target_type)
+       if (guessed_type != PASSWORD_TYPE_PLAINTEXT)
        {
-               case PASSWORD_TYPE_PLAINTEXT:
-
-                       /*
-                        * We cannot convert a hashed password back to plaintext, so just
-                        * store the password as it was, whether it was hashed or not.
-                        */
-                       return pstrdup(password);
+               /*
+                * Cannot convert an already-encrypted password from one
+                * format to another, so return it as it is.
+                */
+               return pstrdup(password);
+       }
 
+       switch (target_type)
+       {
                case PASSWORD_TYPE_MD5:
-                       switch (guessed_type)
-                       {
-                               case PASSWORD_TYPE_PLAINTEXT:
-                                       encrypted_password = palloc(MD5_PASSWD_LEN + 1);
-
-                                       if (!pg_md5_encrypt(password, role, strlen(role),
-                                                                               encrypted_password))
-                                               elog(ERROR, "password encryption failed");
-                                       return encrypted_password;
+                       encrypted_password = palloc(MD5_PASSWD_LEN + 1);
 
-                               case PASSWORD_TYPE_SCRAM_SHA_256:
-
-                                       /*
-                                        * cannot convert a SCRAM verifier to an MD5 hash, so fall
-                                        * through to save the SCRAM verifier instead.
-                                        */
-                               case PASSWORD_TYPE_MD5:
-                                       return pstrdup(password);
-                       }
-                       break;
+                       if (!pg_md5_encrypt(password, role, strlen(role),
+                                                               encrypted_password))
+                               elog(ERROR, "password encryption failed");
+                       return encrypted_password;
 
                case PASSWORD_TYPE_SCRAM_SHA_256:
-                       switch (guessed_type)
-                       {
-                               case PASSWORD_TYPE_PLAINTEXT:
-                                       return pg_be_scram_build_verifier(password);
-
-                               case PASSWORD_TYPE_MD5:
+                       return pg_be_scram_build_verifier(password);
 
-                                       /*
-                                        * cannot convert an MD5 hash to a SCRAM verifier, so fall
-                                        * through to save the MD5 hash instead.
-                                        */
-                               case PASSWORD_TYPE_SCRAM_SHA_256:
-                                       return pstrdup(password);
-                       }
-                       break;
+               case PASSWORD_TYPE_PLAINTEXT:
+                       elog(ERROR, "cannot encrypt password with 'plaintext'");
        }
 
        /*
@@ -197,10 +172,17 @@ md5_crypt_verify(const char *role, const char *shadow_pass,
 {
        int                     retval;
        char            crypt_pwd[MD5_PASSWD_LEN + 1];
-       char            crypt_pwd2[MD5_PASSWD_LEN + 1];
 
        Assert(md5_salt_len > 0);
 
+       if (get_password_type(shadow_pass) != PASSWORD_TYPE_MD5)
+       {
+               /* incompatible password hash format. */
+               *logdetail = psprintf(_("User \"%s\" has a password that cannot be used with MD5 authentication."),
+                                                         role);
+               return STATUS_ERROR;
+       }
+
        /*
         * Compute the correct answer for the MD5 challenge.
         *
@@ -208,40 +190,12 @@ md5_crypt_verify(const char *role, const char *shadow_pass,
         * below: the only possible error is out-of-memory, which is unlikely, and
         * if it did happen adding a psprintf call would only make things worse.
         */
-       switch (get_password_type(shadow_pass))
+       /* stored password already encrypted, only do salt */
+       if (!pg_md5_encrypt(shadow_pass + strlen("md5"),
+                                               md5_salt, md5_salt_len,
+                                               crypt_pwd))
        {
-               case PASSWORD_TYPE_MD5:
-                       /* stored password already encrypted, only do salt */
-                       if (!pg_md5_encrypt(shadow_pass + strlen("md5"),
-                                                               md5_salt, md5_salt_len,
-                                                               crypt_pwd))
-                       {
-                               return STATUS_ERROR;
-                       }
-                       break;
-
-               case PASSWORD_TYPE_PLAINTEXT:
-                       /* stored password is plain, double-encrypt */
-                       if (!pg_md5_encrypt(shadow_pass,
-                                                               role,
-                                                               strlen(role),
-                                                               crypt_pwd2))
-                       {
-                               return STATUS_ERROR;
-                       }
-                       if (!pg_md5_encrypt(crypt_pwd2 + strlen("md5"),
-                                                               md5_salt, md5_salt_len,
-                                                               crypt_pwd))
-                       {
-                               return STATUS_ERROR;
-                       }
-                       break;
-
-               default:
-                       /* unknown password hash format. */
-                       *logdetail = psprintf(_("User \"%s\" has a password that cannot be used with MD5 authentication."),
-                                                                 role);
-                       return STATUS_ERROR;
+               return STATUS_ERROR;
        }
 
        if (strcmp(client_pass, crypt_pwd) == 0)
@@ -259,8 +213,8 @@ md5_crypt_verify(const char *role, const char *shadow_pass,
 /*
  * Check given password for given user, and return STATUS_OK or STATUS_ERROR.
  *
- * 'shadow_pass' is the user's correct password or password hash, as stored
- * in pg_authid.rolpassword.
+ * 'shadow_pass' is the user's correct password hash, as stored in
+ * pg_authid.rolpassword.
  * 'client_pass' is the password given by the remote user.
  *
  * In the error case, optionally store a palloc'd string at *logdetail
@@ -320,14 +274,10 @@ plain_crypt_verify(const char *role, const char *shadow_pass,
                        break;
 
                case PASSWORD_TYPE_PLAINTEXT:
-                       if (strcmp(client_pass, shadow_pass) == 0)
-                               return STATUS_OK;
-                       else
-                       {
-                               *logdetail = psprintf(_("Password does not match for user \"%s\"."),
-                                                                         role);
-                               return STATUS_ERROR;
-                       }
+                       /*
+                        * We never store passwords in plaintext, so this shouldn't
+                        * happen.
+                        */
                        break;
        }
 
index 818d2c29d494710573be3a69a2bc1f904ebea2fb..2cad8b25b8a60ac58257c020f9e0c81840600a24 100644 (file)
@@ -994,13 +994,21 @@ AlterOptRoleElem:
                                }
                        | ENCRYPTED PASSWORD Sconst
                                {
-                                       $$ = makeDefElem("encryptedPassword",
+                                       /*
+                                        * These days, passwords are always stored in encrypted
+                                        * form, so there is no difference between PASSWORD and
+                                        * ENCRYPTED PASSWORD.
+                                        */
+                                       $$ = makeDefElem("password",
                                                                         (Node *)makeString($3), @1);
                                }
                        | UNENCRYPTED PASSWORD Sconst
                                {
-                                       $$ = makeDefElem("unencryptedPassword",
-                                                                        (Node *)makeString($3), @1);
+                                       ereport(ERROR,
+                                                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                                                        errmsg("UNENCRYPTED PASSWORD is no longer supported"),
+                                                        errhint("Remove UNENCRYPTED to store the password in encrypted form instead."),
+                                                        parser_errposition(@1)));
                                }
                        | INHERIT
                                {
index 587fbce147fa2f8e151d9852eac4ba9e4cb1943c..cb4e621c8488eb69e550af78d71537d8f83dcb38 100644 (file)
@@ -405,20 +405,16 @@ static const struct config_enum_entry force_parallel_mode_options[] = {
 
 /*
  * password_encryption used to be a boolean, so accept all the likely
- * variants of "on" and "off", too.
+ * variants of "on", too. "off" used to store passwords in plaintext,
+ * but we don't support that anymore.
  */
 static const struct config_enum_entry password_encryption_options[] = {
-       {"plain", PASSWORD_TYPE_PLAINTEXT, false},
        {"md5", PASSWORD_TYPE_MD5, false},
        {"scram-sha-256", PASSWORD_TYPE_SCRAM_SHA_256, false},
-       {"off", PASSWORD_TYPE_PLAINTEXT, false},
-       {"on", PASSWORD_TYPE_MD5, false},
+       {"on", PASSWORD_TYPE_MD5, true},
        {"true", PASSWORD_TYPE_MD5, true},
-       {"false", PASSWORD_TYPE_PLAINTEXT, true},
        {"yes", PASSWORD_TYPE_MD5, true},
-       {"no", PASSWORD_TYPE_PLAINTEXT, true},
        {"1", PASSWORD_TYPE_MD5, true},
-       {"0", PASSWORD_TYPE_PLAINTEXT, true},
        {NULL, 0, false}
 };
 
index e2a335121043363c6e9bf1fb0b58f6c6e52ad088..183fc376296e5cc05b81f225f1f27e2eaf3a01e1 100644 (file)
@@ -1634,10 +1634,10 @@ psql_completion(const char *text, int start, int end)
        {
                static const char *const list_ALTERUSER[] =
                {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
-                       "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
+                       "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
                        "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
                        "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
-                       "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
+                       "REPLICATION", "RESET", "SET", "SUPERUSER",
                "VALID UNTIL", "WITH", NULL};
 
                COMPLETE_WITH_LIST(list_ALTERUSER);
@@ -1649,18 +1649,15 @@ psql_completion(const char *text, int start, int end)
                /* Similar to the above, but don't complete "WITH" again. */
                static const char *const list_ALTERUSER_WITH[] =
                {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
-                       "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS",
+                       "ENCRYPTED PASSWORD", "INHERIT", "LOGIN", "NOBYPASSRLS",
                        "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
                        "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO",
-                       "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED",
+                       "REPLICATION", "RESET", "SET", "SUPERUSER",
                "VALID UNTIL", NULL};
 
                COMPLETE_WITH_LIST(list_ALTERUSER_WITH);
        }
 
-       /* complete ALTER USER,ROLE <name> ENCRYPTED,UNENCRYPTED with PASSWORD */
-       else if (Matches4("ALTER", "USER|ROLE", MatchAny, "ENCRYPTED|UNENCRYPTED"))
-               COMPLETE_WITH_CONST("PASSWORD");
        /* ALTER DEFAULT PRIVILEGES */
        else if (Matches3("ALTER", "DEFAULT", "PRIVILEGES"))
                COMPLETE_WITH_LIST2("FOR ROLE", "IN SCHEMA");
@@ -2502,10 +2499,10 @@ psql_completion(const char *text, int start, int end)
        {
                static const char *const list_CREATEROLE[] =
                {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
-                       "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
+                       "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
                        "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
                        "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
-                       "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
+                       "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
                "VALID UNTIL", "WITH", NULL};
 
                COMPLETE_WITH_LIST(list_CREATEROLE);
@@ -2517,21 +2514,15 @@ psql_completion(const char *text, int start, int end)
                /* Similar to the above, but don't complete "WITH" again. */
                static const char *const list_CREATEROLE_WITH[] =
                {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE",
-                       "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
+                       "ENCRYPTED PASSWORD", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS",
                        "NOCREATEDB", "NOCREATEROLE", "NOINHERIT",
                        "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD",
-                       "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED",
+                       "REPLICATION", "ROLE", "SUPERUSER", "SYSID",
                "VALID UNTIL", NULL};
 
                COMPLETE_WITH_LIST(list_CREATEROLE_WITH);
        }
 
-       /*
-        * complete CREATE ROLE,USER,GROUP <name> ENCRYPTED,UNENCRYPTED with
-        * PASSWORD
-        */
-       else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "ENCRYPTED|UNENCRYPTED"))
-               COMPLETE_WITH_CONST("PASSWORD");
        /* complete CREATE ROLE,USER,GROUP <name> IN with ROLE,GROUP */
        else if (Matches4("CREATE", "ROLE|USER|GROUP", MatchAny, "IN"))
                COMPLETE_WITH_LIST2("GROUP", "ROLE");
index 35a53bf2064d9bde325d940e6c454322d7b347cb..d88093f8b6e9e80bf6c9e93e332ffde26eea1669 100644 (file)
@@ -48,7 +48,6 @@ main(int argc, char *argv[])
                {"connection-limit", required_argument, NULL, 'c'},
                {"pwprompt", no_argument, NULL, 'P'},
                {"encrypted", no_argument, NULL, 'E'},
-               {"unencrypted", no_argument, NULL, 'N'},
                {NULL, 0, NULL, 0}
        };
 
@@ -75,8 +74,7 @@ main(int argc, char *argv[])
                                createrole = TRI_DEFAULT,
                                inherit = TRI_DEFAULT,
                                login = TRI_DEFAULT,
-                               replication = TRI_DEFAULT,
-                               encrypted = TRI_DEFAULT;
+                               replication = TRI_DEFAULT;
 
        PQExpBufferData sql;
 
@@ -88,7 +86,7 @@ main(int argc, char *argv[])
 
        handle_help_version_opts(argc, argv, "createuser", help);
 
-       while ((c = getopt_long(argc, argv, "h:p:U:g:wWedDsSaArRiIlLc:PEN",
+       while ((c = getopt_long(argc, argv, "h:p:U:g:wWedDsSaArRiIlLc:PE",
                                                        long_options, &optindex)) != -1)
        {
                switch (c)
@@ -153,10 +151,7 @@ main(int argc, char *argv[])
                                pwprompt = true;
                                break;
                        case 'E':
-                               encrypted = TRI_YES;
-                               break;
-                       case 'N':
-                               encrypted = TRI_NO;
+                               /* no-op, accepted for backward compatibility */
                                break;
                        case 1:
                                replication = TRI_YES;
@@ -264,31 +259,22 @@ main(int argc, char *argv[])
        printfPQExpBuffer(&sql, "CREATE ROLE %s", fmtId(newuser));
        if (newpassword)
        {
-               if (encrypted == TRI_YES)
-                       appendPQExpBufferStr(&sql, " ENCRYPTED");
-               if (encrypted == TRI_NO)
-                       appendPQExpBufferStr(&sql, " UNENCRYPTED");
+               char       *encrypted_password;
+
                appendPQExpBufferStr(&sql, " PASSWORD ");
 
-               if (encrypted != TRI_NO)
+               encrypted_password = PQencryptPasswordConn(conn,
+                                                                                                  newpassword,
+                                                                                                  newuser,
+                                                                                                  NULL);
+               if (!encrypted_password)
                {
-                       char       *encrypted_password;
-
-                       encrypted_password = PQencryptPasswordConn(conn,
-                                                                                                          newpassword,
-                                                                                                          newuser,
-                                                                                                          NULL);
-                       if (!encrypted_password)
-                       {
-                               fprintf(stderr, _("%s: password encryption failed: %s"),
-                                               progname, PQerrorMessage(conn));
-                               exit(1);
-                       }
-                       appendStringLiteralConn(&sql, encrypted_password, conn);
-                       PQfreemem(encrypted_password);
+                       fprintf(stderr, _("%s: password encryption failed: %s"),
+                                       progname, PQerrorMessage(conn));
+                       exit(1);
                }
-               else
-                       appendStringLiteralConn(&sql, newpassword, conn);
+               appendStringLiteralConn(&sql, encrypted_password, conn);
+               PQfreemem(encrypted_password);
        }
        if (superuser == TRI_YES)
                appendPQExpBufferStr(&sql, " SUPERUSER");
@@ -361,14 +347,12 @@ help(const char *progname)
        printf(_("  -d, --createdb            role can create new databases\n"));
        printf(_("  -D, --no-createdb         role cannot create databases (default)\n"));
        printf(_("  -e, --echo                show the commands being sent to the server\n"));
-       printf(_("  -E, --encrypted           encrypt stored password\n"));
        printf(_("  -g, --role=ROLE           new role will be a member of this role\n"));
        printf(_("  -i, --inherit             role inherits privileges of roles it is a\n"
                         "                            member of (default)\n"));
        printf(_("  -I, --no-inherit          role does not inherit privileges\n"));
        printf(_("  -l, --login               role can login (default)\n"));
        printf(_("  -L, --no-login            role cannot login\n"));
-       printf(_("  -N, --unencrypted         do not encrypt stored password\n"));
        printf(_("  -P, --pwprompt            assign a password to new role\n"));
        printf(_("  -r, --createrole          role can create new roles\n"));
        printf(_("  -R, --no-createrole       role cannot create roles (default)\n"));
index 63724f39ee2044f916f3ad6e81295c88ee59493a..9bad67c89021467f1315e5e4bd00bacfad5607bb 100644 (file)
 #include "datatype/timestamp.h"
 
 /*
- * Types of password hashes or verifiers that can be stored in
- * pg_authid.rolpassword.
+ * Types of password hashes or verifiers.
  *
- * This is also used for the password_encryption GUC.
+ * Plaintext passwords can be passed in by the user, in a CREATE/ALTER USER
+ * command. They will be encrypted to MD5 or SCRAM-SHA-256 format, before
+ * storing on-disk, so only MD5 and SCRAM-SHA-256 passwords should appear
+ * in pg_authid.rolpassword. They are also the allowed values for the
+ * password_encryption GUC.
  */
 typedef enum PasswordType
 {
index 54acd0f6bf8694be0827b45ae95a486fc0cc5b4a..f4397afc64901bd30bdfafb7489e544e4d078def 100644 (file)
@@ -1183,8 +1183,7 @@ PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user,
         * send the password in plaintext even if it was "off".
         */
        if (strcmp(algorithm, "on") == 0 ||
-               strcmp(algorithm, "off") == 0 ||
-               strcmp(algorithm, "plain") == 0)
+               strcmp(algorithm, "off") == 0)
                algorithm = "md5";
 
        /*
index 216bdc031c81c9e46c246a60f8885fb9e6ef749a..5a21ecd7e66f027446c53cbbe6cf2bb8bf291412 100644 (file)
@@ -10,7 +10,7 @@ use strict;
 use warnings;
 use PostgresNode;
 use TestLib;
-use Test::More tests => 12;
+use Test::More tests => 8;
 
 # Delete pg_hba.conf from the given node, add a new entry to it
 # and then execute a reload to refresh it.
@@ -53,32 +53,26 @@ SKIP:
        # password is used for all of them.
        $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';
 
        # For "trust" method, all users should be able to connect.
        reset_pg_hba($node, 'trust');
        test_role($node, 'scram_role', 'trust', 0);
        test_role($node, 'md5_role', 'trust', 0);
-       test_role($node, 'plain_role', 'trust', 0);
 
        # For plain "password" method, all users should also be able to connect.
        reset_pg_hba($node, 'password');
        test_role($node, 'scram_role', 'password', 0);
        test_role($node, 'md5_role', 'password', 0);
-       test_role($node, 'plain_role', 'password', 0);
 
-       # For "scram-sha-256" method, user "plain_role" and "scram_role" should
-       # be able to connect.
+       # For "scram-sha-256" method, user "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.)
        reset_pg_hba($node, 'md5');
        test_role($node, 'scram_role', 'md5', 0);
        test_role($node, 'md5_role', 'md5', 0);
-       test_role($node, 'plain_role', 'md5', 0);
 }
index 5b0b955b29bbaeeee168fbcffdd9ff6f998255f2..bb25ad0c2cfb21508fc8920d60c5dc3fbc7d5966 100644 (file)
@@ -4,22 +4,18 @@
 -- Tests for GUC password_encryption
 SET password_encryption = 'novalue'; -- error
 ERROR:  invalid value for parameter "password_encryption": "novalue"
-HINT:  Available values: plain, md5, scram-sha-256, off, on.
+HINT:  Available values: md5, scram-sha-256.
 SET password_encryption = true; -- ok
 SET password_encryption = 'md5'; -- ok
-SET password_encryption = 'plain'; -- ok
 SET password_encryption = 'scram-sha-256'; -- ok
 -- consistency of password entries
-SET password_encryption = 'plain';
-CREATE ROLE regress_passwd1 PASSWORD 'role_pwd1';
 SET password_encryption = 'md5';
-CREATE ROLE regress_passwd2 PASSWORD 'role_pwd2';
+CREATE ROLE regress_passwd1 PASSWORD 'role_pwd1';
 SET password_encryption = 'on';
-CREATE ROLE regress_passwd3 PASSWORD 'role_pwd3';
+CREATE ROLE regress_passwd2 PASSWORD 'role_pwd2';
 SET password_encryption = 'scram-sha-256';
-CREATE ROLE regress_passwd4 PASSWORD 'role_pwd4';
-SET password_encryption = 'plain';
-CREATE ROLE regress_passwd5 PASSWORD NULL;
+CREATE ROLE regress_passwd3 PASSWORD 'role_pwd3';
+CREATE ROLE regress_passwd4 PASSWORD NULL;
 -- check list of created entries
 --
 -- The scram verifier will look something like:
@@ -33,56 +29,57 @@ SELECT rolname, regexp_replace(rolpassword, '(SCRAM-SHA-256)\$(\d+):([a-zA-Z0-9+
     ORDER BY rolname, rolpassword;
      rolname     |                rolpassword_masked                 
 -----------------+---------------------------------------------------
- regress_passwd1 | role_pwd1
+ regress_passwd1 | md5783277baca28003b33453252be4dbb34
  regress_passwd2 | md54044304ba511dd062133eb5b4b84a2a3
- regress_passwd3 | md50e5699b6911d87f17a08b8d76a21e8b8
- regress_passwd4 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
- regress_passwd5 | 
-(5 rows)
+ regress_passwd3 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
+ regress_passwd4 | 
+(4 rows)
 
 -- Rename a role
-ALTER ROLE regress_passwd3 RENAME TO regress_passwd3_new;
+ALTER ROLE regress_passwd2 RENAME TO regress_passwd2_new;
 NOTICE:  MD5 password cleared because of role rename
 -- md5 entry should have been removed
 SELECT rolname, rolpassword
     FROM pg_authid
-    WHERE rolname LIKE 'regress_passwd3_new'
+    WHERE rolname LIKE 'regress_passwd2_new'
     ORDER BY rolname, rolpassword;
        rolname       | rolpassword 
 ---------------------+-------------
- regress_passwd3_new | 
+ regress_passwd2_new | 
 (1 row)
 
-ALTER ROLE regress_passwd3_new RENAME TO regress_passwd3;
--- ENCRYPTED and UNENCRYPTED passwords
-ALTER ROLE regress_passwd1 UNENCRYPTED PASSWORD 'foo'; -- unencrypted
-ALTER ROLE regress_passwd2 UNENCRYPTED PASSWORD 'md5dfa155cadd5f4ad57860162f3fab9cdb'; -- encrypted with MD5
+ALTER ROLE regress_passwd2_new RENAME TO regress_passwd2;
+-- Change passwords with ALTER USER. With plaintext or already-encrypted
+-- passwords.
 SET password_encryption = 'md5';
-ALTER ROLE regress_passwd3 ENCRYPTED PASSWORD 'foo'; -- encrypted with MD5
-ALTER ROLE regress_passwd4 ENCRYPTED PASSWORD 'SCRAM-SHA-256$4096:VLK4RMaQLCvNtQ==$6YtlR4t69SguDiwFvbVgVZtuz6gpJQQqUMZ7IQJK5yI=:ps75jrHeYU4lXCcXI4O8oIdJ3eO8o2jirjruw9phBTo='; -- client-supplied SCRAM verifier, use as it is
+-- encrypt with MD5
+ALTER ROLE regress_passwd2 PASSWORD 'foo';
+-- already encrypted, use as they are
+ALTER ROLE regress_passwd1 PASSWORD 'md5cd3578025fe2c3d7ed1b9a9b26238b70';
+ALTER ROLE regress_passwd3 PASSWORD 'SCRAM-SHA-256$4096:VLK4RMaQLCvNtQ==$6YtlR4t69SguDiwFvbVgVZtuz6gpJQQqUMZ7IQJK5yI=:ps75jrHeYU4lXCcXI4O8oIdJ3eO8o2jirjruw9phBTo=';
 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
+-- create SCRAM verifier
+ALTER ROLE  regress_passwd4 PASSWORD 'foo';
+-- already encrypted with MD5, use as it is
+CREATE ROLE regress_passwd5 PASSWORD 'md5e73a4b11df52a6068f8b39f90be36023';
 SELECT rolname, regexp_replace(rolpassword, '(SCRAM-SHA-256)\$(\d+):([a-zA-Z0-9+/=]+)\$([a-zA-Z0-9+=/]+):([a-zA-Z0-9+/=]+)', '\1$\2:<salt>$<storedkey>:<serverkey>') as rolpassword_masked
     FROM pg_authid
     WHERE rolname LIKE 'regress_passwd%'
     ORDER BY rolname, rolpassword;
      rolname     |                rolpassword_masked                 
 -----------------+---------------------------------------------------
- regress_passwd1 | foo
+ regress_passwd1 | md5cd3578025fe2c3d7ed1b9a9b26238b70
  regress_passwd2 | md5dfa155cadd5f4ad57860162f3fab9cdb
- regress_passwd3 | md5530de4c298af94b3b9f7d20305d2a1bf
+ regress_passwd3 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
  regress_passwd4 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
- regress_passwd5 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
- regress_passwd6 | md53725413363ab045e20521bf36b8d8d7f
-(6 rows)
+ regress_passwd5 | md5e73a4b11df52a6068f8b39f90be36023
+(5 rows)
 
 DROP ROLE regress_passwd1;
 DROP ROLE regress_passwd2;
 DROP ROLE regress_passwd3;
 DROP ROLE regress_passwd4;
 DROP ROLE regress_passwd5;
-DROP ROLE regress_passwd6;
 -- all entries should have been removed
 SELECT rolname, rolpassword
     FROM pg_authid
index d2e9eea79d2a207094f8f01f8a6bb82b4d5ff101..f16824372541642eeddb572debe608f149bdd918 100644 (file)
@@ -6,20 +6,16 @@
 SET password_encryption = 'novalue'; -- error
 SET password_encryption = true; -- ok
 SET password_encryption = 'md5'; -- ok
-SET password_encryption = 'plain'; -- ok
 SET password_encryption = 'scram-sha-256'; -- ok
 
 -- consistency of password entries
-SET password_encryption = 'plain';
-CREATE ROLE regress_passwd1 PASSWORD 'role_pwd1';
 SET password_encryption = 'md5';
-CREATE ROLE regress_passwd2 PASSWORD 'role_pwd2';
+CREATE ROLE regress_passwd1 PASSWORD 'role_pwd1';
 SET password_encryption = 'on';
-CREATE ROLE regress_passwd3 PASSWORD 'role_pwd3';
+CREATE ROLE regress_passwd2 PASSWORD 'role_pwd2';
 SET password_encryption = 'scram-sha-256';
-CREATE ROLE regress_passwd4 PASSWORD 'role_pwd4';
-SET password_encryption = 'plain';
-CREATE ROLE regress_passwd5 PASSWORD NULL;
+CREATE ROLE regress_passwd3 PASSWORD 'role_pwd3';
+CREATE ROLE regress_passwd4 PASSWORD NULL;
 
 -- check list of created entries
 --
@@ -34,25 +30,29 @@ SELECT rolname, regexp_replace(rolpassword, '(SCRAM-SHA-256)\$(\d+):([a-zA-Z0-9+
     ORDER BY rolname, rolpassword;
 
 -- Rename a role
-ALTER ROLE regress_passwd3 RENAME TO regress_passwd3_new;
+ALTER ROLE regress_passwd2 RENAME TO regress_passwd2_new;
 -- md5 entry should have been removed
 SELECT rolname, rolpassword
     FROM pg_authid
-    WHERE rolname LIKE 'regress_passwd3_new'
+    WHERE rolname LIKE 'regress_passwd2_new'
     ORDER BY rolname, rolpassword;
-ALTER ROLE regress_passwd3_new RENAME TO regress_passwd3;
+ALTER ROLE regress_passwd2_new RENAME TO regress_passwd2;
 
--- ENCRYPTED and UNENCRYPTED passwords
-ALTER ROLE regress_passwd1 UNENCRYPTED PASSWORD 'foo'; -- unencrypted
-ALTER ROLE regress_passwd2 UNENCRYPTED PASSWORD 'md5dfa155cadd5f4ad57860162f3fab9cdb'; -- encrypted with MD5
+-- Change passwords with ALTER USER. With plaintext or already-encrypted
+-- passwords.
 SET password_encryption = 'md5';
-ALTER ROLE regress_passwd3 ENCRYPTED PASSWORD 'foo'; -- encrypted with MD5
 
-ALTER ROLE regress_passwd4 ENCRYPTED PASSWORD 'SCRAM-SHA-256$4096:VLK4RMaQLCvNtQ==$6YtlR4t69SguDiwFvbVgVZtuz6gpJQQqUMZ7IQJK5yI=:ps75jrHeYU4lXCcXI4O8oIdJ3eO8o2jirjruw9phBTo='; -- client-supplied SCRAM verifier, use as it is
+-- encrypt with MD5
+ALTER ROLE regress_passwd2 PASSWORD 'foo';
+-- already encrypted, use as they are
+ALTER ROLE regress_passwd1 PASSWORD 'md5cd3578025fe2c3d7ed1b9a9b26238b70';
+ALTER ROLE regress_passwd3 PASSWORD 'SCRAM-SHA-256$4096:VLK4RMaQLCvNtQ==$6YtlR4t69SguDiwFvbVgVZtuz6gpJQQqUMZ7IQJK5yI=:ps75jrHeYU4lXCcXI4O8oIdJ3eO8o2jirjruw9phBTo=';
 
 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
+-- create SCRAM verifier
+ALTER ROLE  regress_passwd4 PASSWORD 'foo';
+-- already encrypted with MD5, use as it is
+CREATE ROLE regress_passwd5 PASSWORD 'md5e73a4b11df52a6068f8b39f90be36023';
 
 SELECT rolname, regexp_replace(rolpassword, '(SCRAM-SHA-256)\$(\d+):([a-zA-Z0-9+/=]+)\$([a-zA-Z0-9+=/]+):([a-zA-Z0-9+/=]+)', '\1$\2:<salt>$<storedkey>:<serverkey>') as rolpassword_masked
     FROM pg_authid
@@ -64,7 +64,6 @@ DROP ROLE regress_passwd2;
 DROP ROLE regress_passwd3;
 DROP ROLE regress_passwd4;
 DROP ROLE regress_passwd5;
-DROP ROLE regress_passwd6;
 
 -- all entries should have been removed
 SELECT rolname, rolpassword