Skip to content

Commit 5e8e009

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 b2f833e commit 5e8e009

File tree

5 files changed

+856
-829
lines changed

5 files changed

+856
-829
lines changed

doc/src/sgml/catalogs.sgml

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9211,17 +9211,37 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
92119211
<entry><type>text[]</type></entry>
92129212
<entry></entry>
92139213
<entry>
9214-
User mapping specific options, as <quote>keyword=value</>
9215-
strings. This column will show as null unless the current user
9216-
is the user being mapped, or the mapping is for
9217-
<literal>PUBLIC</literal> and the current user is the server
9218-
owner, or the current user is a superuser. The intent is
9219-
to protect password information stored as user mapping option.
9214+
User mapping specific options, as <quote>keyword=value</> strings
92209215
</entry>
92219216
</row>
92229217
</tbody>
92239218
</tgroup>
92249219
</table>
9220+
9221+
<para>
9222+
To protect password information stored as a user mapping option,
9223+
the <structfield>umoptions</structfield> column will read as null
9224+
unless one of the following applies:
9225+
<itemizedlist>
9226+
<listitem>
9227+
<para>
9228+
current user is the user being mapped, and owns the server or
9229+
holds <literal>USAGE</> privilege on it
9230+
</para>
9231+
</listitem>
9232+
<listitem>
9233+
<para>
9234+
current user is the server owner and mapping is for <literal>PUBLIC</>
9235+
</para>
9236+
</listitem>
9237+
<listitem>
9238+
<para>
9239+
current user is a superuser
9240+
</para>
9241+
</listitem>
9242+
</itemizedlist>
9243+
</para>
9244+
92259245
</sect1>
92269246

92279247

src/backend/catalog/system_views.sql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -696,7 +696,9 @@ CREATE VIEW pg_user_mappings AS
696696
ELSE
697697
A.rolname
698698
END AS usename,
699-
CASE WHEN (U.umuser <> 0 AND A.rolname = current_user)
699+
CASE WHEN (U.umuser <> 0 AND A.rolname = current_user
700+
AND (pg_has_role(S.srvowner, 'USAGE')
701+
OR has_server_privilege(S.oid, 'USAGE')))
700702
OR (U.umuser = 0 AND pg_has_role(S.srvowner, 'USAGE'))
701703
OR (SELECT rolsuper FROM pg_authid WHERE rolname = current_user)
702704
THEN U.umoptions

src/test/regress/expected/foreign_data.out

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,10 +1142,11 @@ ERROR: permission denied for foreign-data wrapper foo
11421142
ALTER SERVER s9 VERSION '1.1';
11431143
GRANT USAGE ON FOREIGN SERVER s9 TO regress_test_role;
11441144
CREATE USER MAPPING FOR current_user SERVER s9;
1145+
-- We use terse mode to avoid ordering issues in cascade detail output.
1146+
\set VERBOSITY terse
11451147
DROP SERVER s9 CASCADE;
11461148
NOTICE: drop cascades to 2 other objects
1147-
DETAIL: drop cascades to user mapping for public on server s9
1148-
drop cascades to user mapping for unprivileged_role on server s9
1149+
\set VERBOSITY default
11491150
RESET ROLE;
11501151
CREATE SERVER s9 FOREIGN DATA WRAPPER foo;
11511152
GRANT USAGE ON FOREIGN SERVER s9 TO unprivileged_role;
@@ -1161,57 +1162,62 @@ ERROR: must be owner of foreign server s9
11611162
SET ROLE regress_test_role;
11621163
CREATE SERVER s10 FOREIGN DATA WRAPPER foo;
11631164
CREATE USER MAPPING FOR public SERVER s10 OPTIONS (user 'secret');
1164-
GRANT USAGE ON FOREIGN SERVER s10 TO unprivileged_role;
1165-
-- owner of server can see option fields
1165+
CREATE USER MAPPING FOR unprivileged_role SERVER s10 OPTIONS (user 'secret');
1166+
-- owner of server can see some option fields
11661167
\deu+
11671168
List of user mappings
11681169
Server | User name | FDW Options
11691170
--------+-------------------+-------------------
11701171
s10 | public | ("user" 'secret')
1172+
s10 | unprivileged_role |
11711173
s4 | foreign_data_user |
11721174
s5 | regress_test_role | (modified '1')
11731175
s6 | regress_test_role |
11741176
s8 | foreign_data_user |
11751177
s8 | public |
11761178
s9 | unprivileged_role |
11771179
t1 | public | (modified '1')
1178-
(8 rows)
1180+
(9 rows)
11791181

11801182
RESET ROLE;
1181-
-- superuser can see option fields
1183+
-- superuser can see all option fields
11821184
\deu+
11831185
List of user mappings
11841186
Server | User name | FDW Options
11851187
--------+-------------------+---------------------
11861188
s10 | public | ("user" 'secret')
1189+
s10 | unprivileged_role | ("user" 'secret')
11871190
s4 | foreign_data_user |
11881191
s5 | regress_test_role | (modified '1')
11891192
s6 | regress_test_role |
11901193
s8 | foreign_data_user | (password 'public')
11911194
s8 | public |
11921195
s9 | unprivileged_role |
11931196
t1 | public | (modified '1')
1194-
(8 rows)
1197+
(9 rows)
11951198

1196-
-- unprivileged user cannot see option fields
1199+
-- unprivileged user cannot see any option field
11971200
SET ROLE unprivileged_role;
11981201
\deu+
11991202
List of user mappings
12001203
Server | User name | FDW Options
12011204
--------+-------------------+-------------
12021205
s10 | public |
1206+
s10 | unprivileged_role |
12031207
s4 | foreign_data_user |
12041208
s5 | regress_test_role |
12051209
s6 | regress_test_role |
12061210
s8 | foreign_data_user |
12071211
s8 | public |
12081212
s9 | unprivileged_role |
12091213
t1 | public |
1210-
(8 rows)
1214+
(9 rows)
12111215

12121216
RESET ROLE;
1217+
\set VERBOSITY terse
12131218
DROP SERVER s10 CASCADE;
1214-
NOTICE: drop cascades to user mapping for public on server s10
1219+
NOTICE: drop cascades to 2 other objects
1220+
\set VERBOSITY default
12151221
-- DROP FOREIGN TABLE
12161222
DROP FOREIGN TABLE no_table; -- ERROR
12171223
ERROR: foreign table "no_table" does not exist
@@ -1236,16 +1242,12 @@ owner of user mapping for regress_test_role on server s6
12361242
DROP SERVER t1 CASCADE;
12371243
NOTICE: drop cascades to user mapping for public on server t1
12381244
DROP USER MAPPING FOR regress_test_role SERVER s6;
1239-
-- This test causes some order dependent cascade detail output,
1240-
-- so switch to terse mode for it.
12411245
\set VERBOSITY terse
12421246
DROP FOREIGN DATA WRAPPER foo CASCADE;
12431247
NOTICE: drop cascades to 5 other objects
1244-
\set VERBOSITY default
12451248
DROP SERVER s8 CASCADE;
12461249
NOTICE: drop cascades to 2 other objects
1247-
DETAIL: drop cascades to user mapping for foreign_data_user on server s8
1248-
drop cascades to user mapping for public on server s8
1250+
\set VERBOSITY default
12491251
DROP ROLE regress_test_indirect;
12501252
DROP ROLE regress_test_role;
12511253
DROP ROLE unprivileged_role; -- ERROR

0 commit comments

Comments
 (0)