From d1470936ab5784b1dafc5fdc777dd8004c5f57ba Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Thu, 5 Oct 2023 14:45:35 +0200 Subject: [PATCH v4 4/5] Allow tests to pass in OpenSSL FIPS mode (rest) This adds alternative expected files for various tests. XXX maybe some of these could be reorgnized to make the patch smaller? --- .../expected/passwordcheck_1.out | 18 +++ contrib/uuid-ossp/expected/uuid_ossp_1.out | 135 ++++++++++++++++ src/test/regress/expected/md5_1.out | 35 ++++ src/test/regress/expected/password_1.out | 150 ++++++++++++++++++ 4 files changed, 338 insertions(+) create mode 100644 contrib/passwordcheck/expected/passwordcheck_1.out create mode 100644 contrib/uuid-ossp/expected/uuid_ossp_1.out create mode 100644 src/test/regress/expected/md5_1.out create mode 100644 src/test/regress/expected/password_1.out diff --git a/contrib/passwordcheck/expected/passwordcheck_1.out b/contrib/passwordcheck/expected/passwordcheck_1.out new file mode 100644 index 0000000000..5d8d5dcc1c --- /dev/null +++ b/contrib/passwordcheck/expected/passwordcheck_1.out @@ -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 index 0000000000..58104dbe18 --- /dev/null +++ b/contrib/uuid-ossp/expected/uuid_ossp_1.out @@ -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 index 0000000000..174b70bafb --- /dev/null +++ b/src/test/regress/expected/md5_1.out @@ -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 diff --git a/src/test/regress/expected/password_1.out b/src/test/regress/expected/password_1.out new file mode 100644 index 0000000000..3bb411949e --- /dev/null +++ b/src/test/regress/expected/password_1.out @@ -0,0 +1,150 @@ +-- +-- 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 PASSWORD 'role_pwd1'; +ERROR: password encryption failed: unsupported +CREATE 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:$:') as rolpassword_masked + FROM pg_authid + WHERE rolname LIKE 'regress_passwd%' + ORDER BY rolname, rolpassword; + rolname | rolpassword_masked +-----------------+--------------------------------------------------- + regress_passwd3 | SCRAM-SHA-256$4096:$: + regress_passwd4 | +(2 rows) + +-- Rename a role +ALTER ROLE regress_passwd2 RENAME TO regress_passwd2_new; +ERROR: role "regress_passwd2" does not exist +-- md5 entry should have been removed +SELECT rolname, rolpassword + FROM pg_authid + WHERE rolname LIKE 'regress_passwd2_new' + ORDER BY rolname, rolpassword; + rolname | rolpassword +---------+------------- +(0 rows) + +ALTER ROLE regress_passwd2_new RENAME TO regress_passwd2; +ERROR: role "regress_passwd2_new" does not exist +-- 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: role "regress_passwd2" does not exist +-- already encrypted, use as they are +ALTER ROLE regress_passwd1 PASSWORD 'md5cd3578025fe2c3d7ed1b9a9b26238b70'; +ERROR: role "regress_passwd1" does not exist +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:$:') as rolpassword_masked + FROM pg_authid + WHERE rolname LIKE 'regress_passwd%' + ORDER BY rolname, rolpassword; + rolname | rolpassword_masked +-----------------+--------------------------------------------------- + regress_passwd3 | SCRAM-SHA-256$4096:$: + regress_passwd4 | SCRAM-SHA-256$4096:$: + regress_passwd5 | md5e73a4b11df52a6068f8b39f90be36023 + regress_passwd6 | SCRAM-SHA-256$4096:$: + regress_passwd7 | SCRAM-SHA-256$4096:$: + regress_passwd8 | SCRAM-SHA-256$4096:$: + regress_passwd9 | SCRAM-SHA-256$1024:$: +(7 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; +ERROR: role "regress_passwd1" does not exist +DROP ROLE regress_passwd2; +ERROR: role "regress_passwd2" does not exist +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) + -- 2.42.0