8000 Again match pg_user_mappings to information_schema.user_mapping_options. · dirbacke/postgres@b6e39ca · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit b6e39ca

Browse files
committed
Again match pg_user_mappings to information_schema.user_mapping_options.
Commit 3eefc51 claimed to make pg_user_mappings enforce the qualifications user_mapping_options had been enforcing, but its removal of a longstanding restriction left them distinct when the current user is the subject of a mapping yet has no server privileges. user_mapping_options emits no rows for such a mapping, but pg_user_mappings includes full umoptions. Change pg_user_mappings to show null for umoptions. Back-patch to 9.2, like the above commit. Reviewed by Tom Lane. Reported by Jeff Janes. Security: CVE-2017-7547
1 parent d5d46d9 commit b6e39ca

File tree

5 files changed

+57
-30
lines changed

5 files changed

+57
-30
lines changed

doc/src/sgml/catalogs.sgml

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9418,17 +9418,37 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
94189418
<entry><type>text[]</type></entry>
94199419
<entry></entry>
94209420
<entry>
9421-
User mapping specific options, as <quote>keyword=value</>
9422-
strings. This column will show as null unless the current user
9423-
is the user being mapped, or the mapping is for
9424-
<literal>PUBLIC</literal> and the current user is the server
9425-
owner, or the current user is a superuser. The intent is
9426-
to protect password information stored as user mapping option.
9421+
User mapping specific options, as <quote>keyword=value</> strings
94279422
</entry>
94289423
</row>
94299424
</tbody>
94309425
</tgroup>
94319426
</table>
9427+
9428+
<para>
9429+
To protect password information stored as a user mapping option,
9430+
the <structfield>umoptions</structfield> column will read as null
9431+
unless one of the following applies:
9432+
<itemizedlist>
9433+
<listitem>
9434+
<para>
9435+
current user is the user being mapped, and owns the server or
9436+
holds <literal>USAGE</> privilege on it
9437+
</para>
9438+
</listitem>
9439+
<listitem>
9440+
<para>
9441+
current user is the server owner and mapping is for <literal>PUBLIC</>
9442+
</para>
9443+
</listitem>
9444+
<listitem>
9445+
<para>
9446+
current user is a superuser
9447+
</para>
9448+
</listitem>
9449+
</itemizedlist>
9450+
</para>
9451+
94329452
</sect1>
94339453

94349454

src/backend/catalog/system_views.sql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,9 @@ CREATE VIEW pg_user_mappings AS
725725
ELSE
726726
A.rolname
727727
END AS usename,
728-
CASE WHEN (U.umuser <> 0 AND A.rolname = current_user)
728+
CASE WHEN (U.umuser <> 0 AND A.rolname = current_user
729+
AND (pg_has_role(S.srvowner, 'USAGE')
730+
OR has_server_privilege(S.oid, 'USAGE')))
729731
OR (U.umuser = 0 AND pg_has_role(S.srvowner, 'USAGE'))
730732
OR (SELECT rolsuper FROM pg_authid WHERE rolname = current_user)
731733
THEN U.umoptions

src/test/regress/expected/foreign_data.out

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,10 +1140,11 @@ ERROR: permission denied for foreign-data wrapper foo
11401140
ALTER SERVER s9 VERSION '1.1';
11411141
GRANT USAGE ON FOREIGN SERVER s9 TO regress_test_role;
11421142
CREATE USER MAPPING FOR current_user SERVER s9;
1143+
-- We use terse mode to avoid ordering issues in cascade detail output.
1144+
\set VERBOSITY terse
11431145
DROP SERVER s9 CASCADE;
11441146
NOTICE: drop cascades to 2 other objects
1145-
DETAIL: drop cascades to user mapping for public on server s9
1146-
drop cascades to user mapping for unprivileged_role on server s9
1147+
\set VERBOSITY default
11471148
RESET ROLE;
11481149
CREATE SERVER s9 FOREIGN DATA WRAPPER foo;
11491150
GRANT USAGE ON FOREIGN SERVER s9 TO unprivileged_role;
@@ -1159,57 +1160,62 @@ ERROR: must be owner of foreign server s9
11591160
SET ROLE regress_test_role;
11601161
CREATE SERVER s10 FOREIGN DATA WRAPPER foo;
11611162
CREATE USER MAPPING FOR public SERVER s10 OPTIONS (user 'secret');
1162-
GRANT USAGE ON FOREIGN SERVER s10 TO unprivileged_role;
1163-
-- owner of server can see option fields
1163+
CREATE USER MAPPING FOR unprivileged_role SERVER s10 OPTIONS (user 'secret');
1164+
-- owner of server can see some option fields
11641165
\deu+
11651166
List of user mappings
11661167
Server | User name | FDW Options
11671168
--------+-------------------+-------------------
11681169
s10 | public | ("user" 'secret')
1170+
s10 | unprivileged_role |
11691171
s4 | foreign_data_user |
11701172
s5 | regress_test_role | (modified '1')
11711173
s6 | regress_test_role |
11721174
s8 | foreign_data_user |
11731175
s8 | public |
11741176
s9 | unprivileged_role |
11751177
t1 | public | (modified '1')
1176-
(8 rows)
1178+
(9 rows)
11771179

11781180
RESET ROLE;
1179-
-- superuser can see option fields
1181+
-- superuser can see all option fields
11801182
\deu+
11811183
List of user mappings
11821184
Server | User name | FDW Options
11831185
--------+-------------------+---------------------
11841186
s10 | public | ("user" 'secret')
1187+
s10 | unprivileged_role | ("user" 'secret')
11851188
s4 | foreign_data_user |
11861189
s5 | regress_test_role | (modified '1')
11871190
s6 | regress_test_role |
11881191
s8 | foreign_data_user | (password 'public')
11891192
s8 | public |
11901193
s9 | unprivileged_role |
11911194
t1 | public | (modified '1')
1192-
(8 rows)
1195+
(9 rows)
11931196

1194-
-- unprivileged user cannot see option fields
1197+
-- unprivileged user cannot see any option field
11951198
SET ROLE unprivileged_role;
11961199
\deu+
11971200
List of user mappings
11981201
Server | User name | FDW Options
11991202
--------+-------------------+-------------
12001203
s10 | public |
1204+
s10 | unprivileged_role |
12011205
s4 | foreign_data_user |
12021206
s5 | regress_test_role |
12031207
s6 | regress_test_role |
12041208
s8 | foreign_data_user |
12051209
s8 | public |
12061210
s9 | unprivileged_role |
12071211
t1 | public |
1208-
(8 rows)
1212+
(9 rows)
12091213

12101214
RESET ROLE;
1215+
\set VERBOSITY terse
12111216
DROP SERVER s10 CASCADE;
1212-
NOTICE: drop cascades to user mapping for public on server s10
1217+
NOTICE: drop cascades to 2 other objects
1218+
\set VERBOSITY default
12131219
-- Triggers
12141220
CREATE FUNCTION dummy_trigger() RETURNS TRIGGER AS $$
12151221
BEGIN
@@ -1271,16 +1277,12 @@ owner of user mapping for regress_test_role on server s6
12711277
DROP SERVER t1 CASCADE;
12721278
NOTICE: drop cascades to user mapping for public on server t1
12731279
DROP USER MAPPING FOR regress_test_role SERVER s6;
1274-
-- This test causes some order dependent cascade detail output,
1275-
-- so switch to terse mode for it.
12761280
\set VERBOSITY terse
12771281
DROP FOREIGN DATA WRAPPER foo CASCADE;
12781282
NOTICE: drop cascades to 5 other objects
1279-
\set VERBOSITY default
12801283
DROP SERVER s8 CASCADE;
12811284
NOTICE: drop cascades to 2 other objects
1282-
DETAIL: drop cascades to user mapping for foreign_data_user on server s8
1283-
drop cascades to user mapping for public on server s8
1285+
\set VERBOSITY default
12841286
DROP ROLE regress_test_indirect;
12851287
DROP ROLE regress_test_role;
12861288
DROP ROLE unprivileged_role; -- ERROR

src/test/regress/expected/rules.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2051,7 +2051,7 @@ pg_user_mappings| SELECT u.oid AS umid,
20512051
ELSE a.rolname
20522052
END AS usename,
20532053
CASE
2054-
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
2054+
WHEN (((((u.umuser <> (0)::oid) AND (a.rolname = "current_user"())) AND (pg_has_role(s.srvowner, 'USAGE'::text) OR has_server_privilege(s.oid, 'USAGE'::text))) OR ((u.umuser = (0)::oid) AND pg_has_role(s.srvowner, 'USAGE'::text))) OR ( SELECT pg_authid.rolsuper
20552055
FROM pg_authid
20562056
WHERE (pg_authid.rolname = "current_user"()))) THEN u.umoptions
20572057
ELSE NULL::text[]

src/test/regress/sql/foreign_data.sql

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,10 @@ CREATE SERVER s10 FOREIGN DATA WRAPPER foo; -- ERROR
459459
ALTER SERVER s9 VERSION '1.1';
460460
GRANT USAGE ON FOREIGN SERVER s9 TO regress_test_role;
461461
CREATE USER MAPPING FOR current_user SERVER s9;
462+
-- We use terse mode to avoid ordering issues in cascade detail output.
463+
\set VERBOSITY terse
462464
DROP SERVER s9 CASCADE;
465+
\set VERBOSITY default
463466
RESET ROLE;
464467
CREATE SERVER s9 FOREIGN DATA WRAPPER foo;
465468
GRANT USAGE ON FOREIGN SERVER s9 TO unprivileged_role;
@@ -473,17 +476,19 @@ DROP SERVER s9 CASCADE; -- ERROR
473476
SET ROLE regress_test_role;
474477
CREATE SERVER s10 FOREIGN DATA WRAPPER foo;
475478
CREATE USER MAPPING FOR public SERVER s10 OPTIONS (user 'secret');
476-
GRANT USAGE ON FOREIGN SERVER s10 TO unprivileged_role;
477-
-- owner of server can see option fields
479+
CREATE USER MAPPING FOR unprivileged_role SERVER s10 OPTIONS (user 'secret');
480+
-- owner of server can see some option fields
478481
\deu+
479482
RESET ROLE;
480-
-- superuser can see option fields
483+
-- superuser can see all option fields
481484
\deu+
482-
-- unprivileged user cannot see option fields
485+
-- unprivileged user cannot see any option field
483486
SET ROLE unprivileged_role;
484487
\deu+
485488
RESET ROLE;
489+
\set VERBOSITY terse
486490
DROP SERVER s10 CASCADE;
491+
\set VERBOSITY default
487492

488493
-- Triggers
489494
CREATE FUNCTION dummy_trigger() RETURNS TRIGGER AS $$
@@ -544,12 +549,10 @@ DROP SCHEMA foreign_schema CASCADE;
544549
DROP ROLE regress_test_role; -- ERROR
545550
DROP SERVER t1 CASCADE;
546551
DROP USER MAPPING FOR regress_test_role SERVER s6;
547-
-- This test causes some order dependent cascade detail output,
548-
-- so switch to terse mode for it.
549552
\set VERBOSITY terse
550553
DROP FOREIGN DATA WRAPPER foo CASCADE;
551-
\set VERBOSITY default
552554
DROP SERVER s8 CASCADE;
555+
\set VERBOSITY default
553556
DROP ROLE regress_test_indirect;
554557
DROP ROLE regress_test_role;
555558
DROP ROLE unprivileged_role; -- ERROR

0 commit comments

Comments
 (0)
0