8000 Match pg_user_mappings limits to information_schema.user_mapping_opti… · dinesh372/postgres@db21581 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit db21581

Browse files
committed
Match pg_user_mappings limits to information_schema.user_mapping_options.
Both views replace the umoptions field with NULL when the user does not meet qualifications to see it. They used different qualifications, and pg_user_mappings documented qualifications did not match its implemented qualifications. Make its documentation and implementation match those of user_mapping_options. One might argue for stronger qualifications, but these have long, documented tenure. pg_user_mappings has always exhibited this problem, so back-patch to 9.2 (all supported versions). Michael Paquier and Feike Steenbergen. Reviewed by Jeff Janes. Reported by Andrew Wheelwright. Security: CVE-2017-7486
1 parent 96d7454 commit db21581

File tree

5 files changed

+82
-8
lines changed

5 files changed

+82
-8
lines changed

doc/src/sgml/catalogs.sgml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9990,8 +9990,11 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
99909990
<entry></entry>
99919991
<entry>
99929992
User mapping specific options, as <quote>keyword=value</>
9993-
strings, if the current user is the owner of the foreign
9994-
server, else null
9993+
strings. This column will show as null unless the current user
9994+
is the user being mapped, or the mapping is for
9995+
<literal>PUBLIC</literal> and the current user is the server
9996+
owner, or the current user is a superuser. The intent is
9997+
to protect password information stored as user mapping option.
99959998
</entry>
99969999
</row>
999710000
</tbody>

src/backend/catalog/system_views.sql

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -775,11 +775,11 @@ CREATE VIEW pg_user_mappings AS
775775
ELSE
776776
A.rolname
777777
END AS usename,
778-
CASE WHEN pg_has_role(S.srvowner, 'USAGE') OR has_server_privilege(S.oid, 'USAGE') THEN
779-
U.umoptions
780-
ELSE
781-
NULL
782-
END AS umoptions
778+
CASE WHEN (U.umuser <> 0 AND A.rolname = current_user)
779+
OR (U.umuser = 0 AND pg_has_role(S.srvowner, 'USAGE'))
780+
OR (SELECT rolsuper FROM pg_authid WHERE rolname = current_user)
781+
THEN U.umoptions
782+
ELSE NULL END AS umoptions
783783
FROM pg_user_mapping U
784784
LEFT JOIN pg_authid A ON (A.oid = U.umuser) JOIN
785785
pg_foreign_server S ON (U.umserver = S.oid);

src/test/regress/expected/foreign_data.out

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,7 +1194,61 @@ WARNING: no privileges were granted for "s9"
11941194
CREATE USER MAPPING FOR current_user SERVER s9;
11951195
DROP SERVER s9 CASCADE; -- ERROR
11961196
ERROR: must be owner of foreign server s9
1197+
-- Check visibility of user mapping data
1198+
SET ROLE regress_test_role;
1199+
CREATE SERVER s10 FOREIGN DATA WRAPPER foo;
1200+
CREATE USER MAPPING FOR public SERVER s10 OPTIONS (user 'secret');
1201+
GRANT USAGE ON FOREIGN SERVER s10 TO unprivileged_role;
1202+
-- owner of server can see option fields
1203+
\deu+
1204+
List of user mappings
1205+
Server | User name | FDW Options
1206+
--------+-------------------+-------------------
1207+
s10 | public | ("user" 'secret')
1208+
s4 | foreign_data_user |
1209+
s5 | regress_test_role | (modified '1')
1210+
s6 | regress_test_role |
1211+
s8 | foreign_data_user |
1212+
s8 | public |
1213+
s9 | unprivileged_role |
1214+
t1 | public | (modified '1')
1215+
(8 rows)
1216+
1217+
RESET ROLE;
1218+
-- superuser can see option fields
1219+
\deu+
1220+
List of user mappings
1221+
Server | User name | FDW Options
1222+
--------+-------------------+---------------------
1223+
s10 | public | ("user" 'secret')
1224+
s4 | foreign_data_user |
1225+
s5 | regress_test_role | (modified '1')
1226+
s6 | regress_test_role |
1227+
s8 | foreign_data_user | (password 'public')
1228+
s8 | public |
1229+
s9 | unprivileged_role |
1230+
t1 | public | (modified '1')
1231+
(8 rows)
1232+
1233+
-- unprivileged user cannot see option fields
1234+
SET ROLE unprivileged_role;
1235+
\deu+
1236+
List of user mappings
1237+
Server | User name | FDW Options
1238+
--------+-------------------+-------------
1239+
s10 | public |
1240+
s4 | foreign_data_user |
1241+
s5 | regress_test_role |
1242+
s6 | regress_test_role |
1243+
s8 | foreign_data_user |
1244+
s8 | public |
1245+
s9 | unprivileged_role |
1246+
t1 | public |
1247+
(8 rows)
1248+
11971249
RESET ROLE;
1250+
DROP SERVER s10 CASCADE;
1251+
NOTICE: drop cascades to user mapping for public on server s10
11981252
-- Triggers
11991253
CREATE FUNCTION dummy_trigger() RETURNS TRIGGER AS $$
12001254
BEGIN

src/test/regress/expected/rules.out

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2102,7 +2102,9 @@ pg_user_mappings| SELECT u.oid AS umid,
21022102
ELSE a.rolname
21032103
END AS usename,
21042104
CASE
2105-
WHEN (pg_has_role(s.srvowner, 'USAGE'::text) OR has_server_privilege(s.oid, 'USAGE'::text)) THEN u.umoptions
2105+
WHEN (((u.umuser <> (0)::oid) AND (a.rolname = "current_user"())) OR ((u.umuser = (0)::oid) AND pg_has_role(s.srvowner, 'USAGE'::text)) OR ( SELECT pg_authid.rolsuper
2106+
FROM pg_authid
2107+
WHERE (pg_authid.rolname = "current_user"()))) THEN u.umoptions
21062108
ELSE NULL::text[]
21072109
END AS umoptions
21082110
FROM ((pg_user_mapping u

src/test/regress/sql/foreign_data.sql

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,22 @@ ALTER SERVER s9 VERSION '1.2'; -- ERROR
490490
GRANT USAGE ON FOREIGN SERVER s9 TO regress_test_role; -- WARNING
491491
CREATE USER MAPPING FOR current_user SERVER s9;
492492
DROP SERVER s9 CASCADE; -- ERROR
493+
494+
-- Check visibility of user mapping data
495+
SET ROLE regress_test_role;
496+
CREATE SERVER s10 FOREIGN DATA WRAPPER foo;
497+
CREATE USER MAPPING FOR public SERVER s10 OPTIONS (user 'secret');
498+
GRANT USAGE ON FOREIGN SERVER s10 TO unprivileged_role;
499+
-- owner of server can see option fields
500+
\deu+
501+
RESET ROLE;
502+
-- superuser can see option fields
503+
\deu+
504+
-- unprivileged user cannot see option fields
505+
SET ROLE unprivileged_role;
506+
\deu+
493507
RESET ROLE;
508+
DROP SERVER s10 CASCADE;
494509

495510
-- Triggers
496511
CREATE FUNCTION dummy_trigger() RETURNS TRIGGER AS $$

0 commit comments

Comments
 (0)
0