Allow tests to pass in OpenSSL FIPS mode (rest)
authorPeter Eisentraut <[email protected]>
Fri, 17 Nov 2023 13:40:13 +0000 (14:40 +0100)
committerPeter Eisentraut <[email protected]>
Fri, 17 Nov 2023 16:58:39 +0000 (17:58 +0100)
This adds alternative expected files for various tests.

In src/test/regress/sql/password.sql, we make a small change to the
test so that the CREATE ROLE still succeeds even if the ALTER ROLE
that attempts to set a password might fail.  That way, the roles are
available for the rest of the test file in either case.

Reviewed-by: Tom Lane <[email protected]>
Reviewed-by: Daniel Gustafsson <[email protected]>
Discussion: https://www.postgresql.org/message-id/flat/dbbd927f-ef1f-c9a1-4ec6-c759778ac852%40enterprisedb.com

contrib/passwordcheck/expected/passwordcheck_1.out[new file with mode: 0644]
contrib/uuid-ossp/expected/uuid_ossp_1.out[new file with mode: 0644]
src/test/regress/expected/md5_1.out[new file with mode: 0644]
src/test/regress/expected/password.out
src/test/regress/expected/password_1.out[new file with mode: 0644]
src/test/regress/sql/password.sql

diff --git a/contrib/passwordcheck/expected/passwordcheck_1.out b/contrib/passwordcheck/expected/passwordcheck_1.out
new file mode 100644 (file)
index 0000000..5d8d5dc
--- /dev/null
@@ -0,0 +1,18 @@
+LOAD 'passwordcheck';
+CREATE USER regress_passwordcheck_user1;
+-- ok
+ALTER USER regress_passwordcheck_user1 PASSWORD 'a_nice_long_password';
+-- error: too short
+ALTER USER regress_passwordcheck_user1 PASSWORD 'tooshrt';
+ERROR:  password is too short
+-- error: contains user name
+ALTER USER regress_passwordcheck_user1 PASSWORD 'xyzregress_passwordcheck_user1';
+ERROR:  password must not contain user name
+-- error: contains only letters
+ALTER USER regress_passwordcheck_user1 PASSWORD 'alessnicelongpassword';
+ERROR:  password must contain both letters and nonletters
+-- encrypted ok (password is "secret")
+ALTER USER regress_passwordcheck_user1 PASSWORD 'md592350e12ac34e52dd598f90893bb3ae7';
+-- error: password is user name
+ALTER USER regress_passwordcheck_user1 PASSWORD 'md507a112732ed9f2087fa90b192d44e358';
+DROP USER regress_passwordcheck_user1;
diff --git a/contrib/uuid-ossp/expected/uuid_ossp_1.out b/contrib/uuid-ossp/expected/uuid_ossp_1.out
new file mode 100644 (file)
index 0000000..58104db
--- /dev/null
@@ -0,0 +1,135 @@
+CREATE EXTENSION "uuid-ossp";
+SELECT uuid_nil();
+               uuid_nil               
+--------------------------------------
+ 00000000-0000-0000-0000-000000000000
+(1 row)
+
+SELECT uuid_ns_dns();
+             uuid_ns_dns              
+--------------------------------------
+ 6ba7b810-9dad-11d1-80b4-00c04fd430c8
+(1 row)
+
+SELECT uuid_ns_url();
+             uuid_ns_url              
+--------------------------------------
+ 6ba7b811-9dad-11d1-80b4-00c04fd430c8
+(1 row)
+
+SELECT uuid_ns_oid();
+             uuid_ns_oid              
+--------------------------------------
+ 6ba7b812-9dad-11d1-80b4-00c04fd430c8
+(1 row)
+
+SELECT uuid_ns_x500();
+             uuid_ns_x500             
+--------------------------------------
+ 6ba7b814-9dad-11d1-80b4-00c04fd430c8
+(1 row)
+
+-- some quick and dirty field extraction functions
+-- this is actually timestamp concatenated with clock sequence, per RFC 4122
+CREATE FUNCTION uuid_timestamp_bits(uuid) RETURNS varbit AS
+$$ SELECT ('x' || substr($1::text, 15, 4) || substr($1::text, 10, 4) ||
+           substr($1::text, 1, 8) || substr($1::text, 20, 4))::bit(80)
+          & x'0FFFFFFFFFFFFFFF3FFF' $$
+LANGUAGE SQL STRICT IMMUTABLE;
+CREATE FUNCTION uuid_version_bits(uuid) RETURNS varbit AS
+$$ SELECT ('x' || substr($1::text, 15, 2))::bit(8) & '11110000' $$
+LANGUAGE SQL STRICT IMMUTABLE;
+CREATE FUNCTION uuid_reserved_bits(uuid) RETURNS varbit AS
+$$ SELECT ('x' || substr($1::text, 20, 2))::bit(8) & '11000000' $$
+LANGUAGE SQL STRICT IMMUTABLE;
+CREATE FUNCTION uuid_multicast_bit(uuid) RETURNS bool AS
+$$ SELECT (('x' || substr($1::text, 25, 2))::bit(8) & '00000001') != '00000000' $$
+LANGUAGE SQL STRICT IMMUTABLE;
+CREATE FUNCTION uuid_local_admin_bit(uuid) RETURNS bool AS
+$$ SELECT (('x' || substr($1::text, 25, 2))::bit(8) & '00000010') != '00000000' $$
+LANGUAGE SQL STRICT IMMUTABLE;
+CREATE FUNCTION uuid_node(uuid) RETURNS text AS
+$$ SELECT substr($1::text, 25) $$
+LANGUAGE SQL STRICT IMMUTABLE;
+-- Ideally, the multicast bit would never be set in V1 output, but the
+-- UUID library may fall back to MC if it can't get the system MAC address.
+-- Also, the local-admin bit might be set (if so, we're probably inside a VM).
+-- So we can't test either bit here.
+SELECT uuid_version_bits(uuid_generate_v1()),
+       uuid_reserved_bits(uuid_generate_v1());
+ uuid_version_bits | uuid_reserved_bits 
+-------------------+--------------------
+ 00010000          | 10000000
+(1 row)
+
+-- Although RFC 4122 only requires the multicast bit to be set in V1MC style
+-- UUIDs, our implementation always sets the local-admin bit as well.
+SELECT uuid_version_bits(uuid_generate_v1mc()),
+       uuid_reserved_bits(uuid_generate_v1mc()),
+       uuid_multicast_bit(uuid_generate_v1mc()),
+       uuid_local_admin_bit(uuid_generate_v1mc());
+ uuid_version_bits | uuid_reserved_bits | uuid_multicast_bit | uuid_local_admin_bit 
+-------------------+--------------------+--------------------+----------------------
+ 00010000          | 10000000           | t                  | t
+(1 row)
+
+-- timestamp+clock sequence should be monotonic increasing in v1
+SELECT uuid_timestamp_bits(uuid_generate_v1()) < uuid_timestamp_bits(uuid_generate_v1());
+ ?column? 
+----------
+ t
+(1 row)
+
+SELECT uuid_timestamp_bits(uuid_generate_v1mc()) < uuid_timestamp_bits(uuid_generate_v1mc());
+ ?column? 
+----------
+ t
+(1 row)
+
+-- Ideally, the node value is stable in V1 addresses, but OSSP UUID
+-- falls back to V1MC behavior if it can't get the system MAC address.
+SELECT CASE WHEN uuid_multicast_bit(uuid_generate_v1()) AND
+                 uuid_local_admin_bit(uuid_generate_v1()) THEN
+         true -- punt, no test
+       ELSE
+         uuid_node(uuid_generate_v1()) = uuid_node(uuid_generate_v1())
+       END;
+ case 
+------
+ t
+(1 row)
+
+-- In any case, V1MC node addresses should be random.
+SELECT uuid_node(uuid_generate_v1()) <> uuid_node(uuid_generate_v1mc());
+ ?column? 
+----------
+ t
+(1 row)
+
+SELECT uuid_node(uuid_generate_v1mc()) <> uuid_node(uuid_generate_v1mc());
+ ?column? 
+----------
+ t
+(1 row)
+
+SELECT uuid_generate_v3(uuid_ns_dns(), 'www.widgets.com');
+ERROR:  could not initialize MD5 context: unsupported
+SELECT uuid_generate_v5(uuid_ns_dns(), 'www.widgets.com');
+           uuid_generate_v5           
+--------------------------------------
+ 21f7f8de-8051-5b89-8680-0195ef798b6a
+(1 row)
+
+SELECT uuid_version_bits(uuid_generate_v4()),
+       uuid_reserved_bits(uuid_generate_v4());
+ uuid_version_bits | uuid_reserved_bits 
+-------------------+--------------------
+ 01000000          | 10000000
+(1 row)
+
+SELECT uuid_generate_v4() <> uuid_generate_v4();
+ ?column? 
+----------
+ t
+(1 row)
+
diff --git a/src/test/regress/expected/md5_1.out b/src/test/regress/expected/md5_1.out
new file mode 100644 (file)
index 0000000..174b70b
--- /dev/null
@@ -0,0 +1,35 @@
+--
+-- MD5 test suite - from IETF RFC 1321
+-- (see: https://www.rfc-editor.org/rfc/rfc1321)
+--
+-- (The md5() function will error in OpenSSL FIPS mode.  By keeping
+-- this test in a separate file, it is easier to manage variant
+-- results.)
+select md5('') = 'd41d8cd98f00b204e9800998ecf8427e' AS "TRUE";
+ERROR:  could not compute MD5 hash: unsupported
+select md5('a') = '0cc175b9c0f1b6a831c399e269772661' AS "TRUE";
+ERROR:  could not compute MD5 hash: unsupported
+select md5('abc') = '900150983cd24fb0d6963f7d28e17f72' AS "TRUE";
+ERROR:  could not compute MD5 hash: unsupported
+select md5('message digest') = 'f96b697d7cb7938d525a2f31aaf161d0' AS "TRUE";
+ERROR:  could not compute MD5 hash: unsupported
+select md5('abcdefghijklmnopqrstuvwxyz') = 'c3fcd3d76192e4007dfb496cca67e13b' AS "TRUE";
+ERROR:  could not compute MD5 hash: unsupported
+select md5('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') = 'd174ab98d277d9f5a5611c2c9f419d9f' AS "TRUE";
+ERROR:  could not compute MD5 hash: unsupported
+select md5('12345678901234567890123456789012345678901234567890123456789012345678901234567890') = '57edf4a22be3c955ac49da2e2107b67a' AS "TRUE";
+ERROR:  could not compute MD5 hash: unsupported
+select md5(''::bytea) = 'd41d8cd98f00b204e9800998ecf8427e' AS "TRUE";
+ERROR:  could not compute MD5 hash: unsupported
+select md5('a'::bytea) = '0cc175b9c0f1b6a831c399e269772661' AS "TRUE";
+ERROR:  could not compute MD5 hash: unsupported
+select md5('abc'::bytea) = '900150983cd24fb0d6963f7d28e17f72' AS "TRUE";
+ERROR:  could not compute MD5 hash: unsupported
+select md5('message digest'::bytea) = 'f96b697d7cb7938d525a2f31aaf161d0' AS "TRUE";
+ERROR:  could not compute MD5 hash: unsupported
+select md5('abcdefghijklmnopqrstuvwxyz'::bytea) = 'c3fcd3d76192e4007dfb496cca67e13b' AS "TRUE";
+ERROR:  could not compute MD5 hash: unsupported
+select md5('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'::bytea) = 'd174ab98d277d9f5a5611c2c9f419d9f' AS "TRUE";
+ERROR:  could not compute MD5 hash: unsupported
+select md5('12345678901234567890123456789012345678901234567890123456789012345678901234567890'::bytea) = '57edf4a22be3c955ac49da2e2107b67a' AS "TRUE";
+ERROR:  could not compute MD5 hash: unsupported
index 847523173567531cf94bc22b5e84774b09337953..924d6e001d457fbe62c6a034d8b2de70f002d03e 100644 (file)
@@ -12,8 +12,10 @@ SET password_encryption = 'md5'; -- ok
 SET password_encryption = 'scram-sha-256'; -- ok
 -- consistency of password entries
 SET password_encryption = 'md5';
-CREATE ROLE regress_passwd1 PASSWORD 'role_pwd1';
-CREATE ROLE regress_passwd2 PASSWORD 'role_pwd2';
+CREATE ROLE regress_passwd1;
+ALTER ROLE regress_passwd1 PASSWORD 'role_pwd1';
+CREATE ROLE regress_passwd2;
+ALTER ROLE regress_passwd2 PASSWORD 'role_pwd2';
 SET password_encryption = 'scram-sha-256';
 CREATE ROLE regress_passwd3 PASSWORD 'role_pwd3';
 CREATE ROLE regress_passwd4 PASSWORD NULL;
diff --git a/src/test/regress/expected/password_1.out b/src/test/regress/expected/password_1.out
new file mode 100644 (file)
index 0000000..9d2cc94
--- /dev/null
@@ -0,0 +1,152 @@
+--
+-- Tests for password types
+--
+-- Tests for GUC password_encryption
+SET password_encryption = 'novalue'; -- error
+ERROR:  invalid value for parameter "password_encryption": "novalue"
+HINT:  Available values: md5, scram-sha-256.
+SET password_encryption = true; -- error
+ERROR:  invalid value for parameter "password_encryption": "true"
+HINT:  Available values: md5, scram-sha-256.
+SET password_encryption = 'md5'; -- ok
+SET password_encryption = 'scram-sha-256'; -- ok
+-- consistency of password entries
+SET password_encryption = 'md5';
+CREATE ROLE regress_passwd1;
+ALTER ROLE regress_passwd1 PASSWORD 'role_pwd1';
+ERROR:  password encryption failed: unsupported
+CREATE ROLE regress_passwd2;
+ALTER ROLE regress_passwd2 PASSWORD 'role_pwd2';
+ERROR:  password encryption failed: unsupported
+SET password_encryption = 'scram-sha-256';
+CREATE ROLE regress_passwd3 PASSWORD 'role_pwd3';
+CREATE ROLE regress_passwd4 PASSWORD NULL;
+-- check list of created entries
+--
+-- The scram secret will look something like:
+-- SCRAM-SHA-256$4096:E4HxLGtnRzsYwg==$6YtlR4t69SguDiwFvbVgVZtuz6gpJQQqUMZ7IQJK5yI=:ps75jrHeYU4lXCcXI4O8oIdJ3eO8o2jirjruw9phBTo=
+--
+-- Since the salt is random, the exact value stored will be different on every test
+-- run. Use a regular expression to mask the changing parts.
+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 | 
+ regress_passwd2 | 
+ regress_passwd3 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
+ regress_passwd4 | 
+(4 rows)
+
+-- Rename a role
+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_passwd2_new'
+    ORDER BY rolname, rolpassword;
+       rolname       | rolpassword 
+---------------------+-------------
+ regress_passwd2_new | 
+(1 row)
+
+ALTER ROLE regress_passwd2_new RENAME TO regress_passwd2;
+-- Change passwords with ALTER USER. With plaintext or already-encrypted
+-- passwords.
+SET password_encryption = 'md5';
+-- encrypt with MD5
+ALTER ROLE regress_passwd2 PASSWORD 'foo';
+ERROR:  password encryption failed: unsupported
+-- 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';
+-- create SCRAM secret
+ALTER ROLE  regress_passwd4 PASSWORD 'foo';
+-- already encrypted with MD5, use as it is
+CREATE ROLE regress_passwd5 PASSWORD 'md5e73a4b11df52a6068f8b39f90be36023';
+-- This looks like a valid SCRAM-SHA-256 secret, but it is not
+-- so it should be hashed with SCRAM-SHA-256.
+CREATE ROLE regress_passwd6 PASSWORD 'SCRAM-SHA-256$1234';
+-- These may look like valid MD5 secrets, but they are not, so they
+-- should be hashed with SCRAM-SHA-256.
+-- trailing garbage at the end
+CREATE ROLE regress_passwd7 PASSWORD 'md5012345678901234567890123456789zz';
+-- invalid length
+CREATE ROLE regress_passwd8 PASSWORD 'md501234567890123456789012345678901zz';
+-- Changing the SCRAM iteration count
+SET scram_iterations = 1024;
+CREATE ROLE regress_passwd9 PASSWORD 'alterediterationcount';
+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 | md5cd3578025fe2c3d7ed1b9a9b26238b70
+ regress_passwd2 | 
+ regress_passwd3 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
+ regress_passwd4 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
+ regress_passwd5 | md5e73a4b11df52a6068f8b39f90be36023
+ regress_passwd6 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
+ regress_passwd7 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
+ regress_passwd8 | SCRAM-SHA-256$4096:<salt>$<storedkey>:<serverkey>
+ regress_passwd9 | SCRAM-SHA-256$1024:<salt>$<storedkey>:<serverkey>
+(9 rows)
+
+-- An empty password is not allowed, in any form
+CREATE ROLE regress_passwd_empty PASSWORD '';
+NOTICE:  empty string is not a valid password, clearing password
+ALTER ROLE regress_passwd_empty PASSWORD 'md585939a5ce845f1a1b620742e3c659e0a';
+ALTER ROLE regress_passwd_empty PASSWORD 'SCRAM-SHA-256$4096:hpFyHTUsSWcR7O9P$LgZFIt6Oqdo27ZFKbZ2nV+vtnYM995pDh9ca6WSi120=:qVV5NeluNfUPkwm7Vqat25RjSPLkGeoZBQs6wVv+um4=';
+NOTICE:  empty string is not a valid password, clearing password
+SELECT rolpassword FROM pg_authid WHERE rolname='regress_passwd_empty';
+ rolpassword 
+-------------
+(1 row)
+
+-- Test with invalid stored and server keys.
+--
+-- The first is valid, to act as a control. The others have too long
+-- stored/server keys. They will be re-hashed.
+CREATE ROLE regress_passwd_sha_len0 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96Rqw=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZI=';
+CREATE ROLE regress_passwd_sha_len1 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96RqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZI=';
+CREATE ROLE regress_passwd_sha_len2 PASSWORD 'SCRAM-SHA-256$4096:A6xHKoH/494E941doaPOYg==$Ky+A30sewHIH3VHQLRN9vYsuzlgNyGNKCh37dy96Rqw=:COPdlNiIkrsacU5QoxydEuOH6e/KfiipeETb/bPw8ZIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=';
+-- Check that the invalid secrets were re-hashed. A re-hashed secret
+-- should not contain the original salt.
+SELECT rolname, rolpassword not like '%A6xHKoH/494E941doaPOYg==%' as is_rolpassword_rehashed
+    FROM pg_authid
+    WHERE rolname LIKE 'regress_passwd_sha_len%'
+    ORDER BY rolname;
+         rolname         | is_rolpassword_rehashed 
+-------------------------+-------------------------
+ regress_passwd_sha_len0 | f
+ regress_passwd_sha_len1 | t
+ regress_passwd_sha_len2 | t
+(3 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;
+DROP ROLE regress_passwd7;
+DROP ROLE regress_passwd8;
+DROP ROLE regress_passwd9;
+DROP ROLE regress_passwd_empty;
+DROP ROLE regress_passwd_sha_len0;
+DROP ROLE regress_passwd_sha_len1;
+DROP ROLE regress_passwd_sha_len2;
+-- all entries should have been removed
+SELECT rolname, rolpassword
+    FROM pg_authid
+    WHERE rolname LIKE 'regress_passwd%'
+    ORDER BY rolname, rolpassword;
+ rolname | rolpassword 
+---------+-------------
+(0 rows)
+
index 53e86b0b6ce9e18912a64d6d229787d5781dccf5..bb82aa4aa244b364e233d8423e1a1e7e06ee7c69 100644 (file)
@@ -10,8 +10,10 @@ SET password_encryption = 'scram-sha-256'; -- ok
 
 -- consistency of password entries
 SET password_encryption = 'md5';
-CREATE ROLE regress_passwd1 PASSWORD 'role_pwd1';
-CREATE ROLE regress_passwd2 PASSWORD 'role_pwd2';
+CREATE ROLE regress_passwd1;
+ALTER ROLE regress_passwd1 PASSWORD 'role_pwd1';
+CREATE ROLE regress_passwd2;
+ALTER ROLE regress_passwd2 PASSWORD 'role_pwd2';
 SET password_encryption = 'scram-sha-256';
 CREATE ROLE regress_passwd3 PASSWORD 'role_pwd3';
 CREATE ROLE regress_passwd4 PASSWORD NULL;