Skip to content

Commit e568e1e

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 bf6b9e9 commit e568e1e

File tree

5 files changed

+61
-35
lines changed

5 files changed

+61
-35
lines changed

doc/src/sgml/catalogs.sgml

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11099,17 +11099,37 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
1109911099
<entry><type>text[]</type></entry>
1110011100
<entry></entry>
1110111101
<entry>
11102-
User mapping specific options, as <quote>keyword=value</>
11103-
strings. This column will show as null unless the current user
11104-
is the user being mapped, or the mapping is for
11105-
<literal>PUBLIC</literal> and the current user is the server
11106-
owner, or the current user is a superuser. The intent is
11107-
to protect password information stored as user mapping option.
11102+
User mapping specific options, as <quote>keyword=value</> strings
1110811103
</entry>
1110911104
</row>
1111011105
</tbody>
1111111106
</tgroup>
1111211107
</table>
11108+
11109+
<para>
11110+
To protect password information stored as a user mapping option,
11111+
the <structfield>umoptions</structfield> column will read as null
11112+
unless one of the following applies:
11113+
<itemizedlist>
11114+
<listitem>
11115+
<para>
11116+
current user is the user being mapped, and owns the server or
11117+
holds <literal>USAGE</> privilege on it
11118+
</para>
11119+
</listitem>
11120+
<listitem>
11121+
<para>
11122+
current user is the server owner and mapping is for <literal>PUBLIC</>
11123+
</para>
11124+
</listitem>
11125+
<listitem>
11126+
<para>
11127+
current user is a superuser
11128+
</para>
11129+
</listitem>
11130+
</itemizedlist>
11131+
</para>
11132+
1111311133
</sect1>
1111411134

1111511135

src/backend/catalog/system_views.sql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,9 @@ CREATE VIEW pg_user_mappings AS
910910
ELSE
911911
A.rolname
912912
END AS usename,
913-
CASE WHEN (U.umuser <> 0 AND A.rolname = current_user)
913+
CASE WHEN (U.umuser <> 0 AND A.rolname = current_user
914+
AND (pg_has_role(S.srvowner, 'USAGE')
915+
OR has_server_privilege(S.oid, 'USAGE')))
914916
OR (U.umuser = 0 AND pg_has_role(S.srvowner, 'USAGE'))
915917
OR (SELECT rolsuper FROM pg_authid WHERE rolname = current_user)
916918
THEN U.umoptions

src/test/regress/expected/foreign_data.out

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,10 +1185,11 @@ ERROR: permission denied for foreign-data wrapper foo
11851185
ALTER SERVER s9 VERSION '1.1';
11861186
GRANT USAGE ON FOREIGN SERVER s9 TO regress_test_role;
11871187
CREATE USER MAPPING FOR current_user SERVER s9;
1188+
-- We use terse mode to avoid ordering issues in cascade detail output.
1189+
\set VERBOSITY terse
11881190
DROP SERVER s9 CASCADE;
11891191
NOTICE: drop cascades to 2 other objects
1190-
DETAIL: drop cascades to user mapping for public on server s9
1191-
drop cascades to user mapping for regress_unprivileged_role on server s9
1192+
\set VERBOSITY default
11921193
RESET ROLE;
11931194
CREATE SERVER s9 FOREIGN DATA WRAPPER foo;
11941195
GRANT USAGE ON FOREIGN SERVER s9 TO regress_unprivileged_role;
@@ -1204,57 +1205,62 @@ ERROR: must be owner of foreign server s9
12041205
SET ROLE regress_test_role;
12051206
CREATE SERVER s10 FOREIGN DATA WRAPPER foo;
12061207
CREATE USER MAPPING FOR public SERVER s10 OPTIONS (user 'secret');
1207-
GRANT USAGE ON FOREIGN SERVER s10 TO regress_unprivileged_role;
1208-
-- owner of server can see option fields
1208+
CREATE USER MAPPING FOR regress_unprivileged_role SERVER s10 OPTIONS (user 'secret');
1209+
-- owner of server can see some option fields
12091210
\deu+
12101211
List of user mappings
12111212
Server | User name | FDW options
12121213
--------+---------------------------+-------------------
12131214
s10 | public | ("user" 'secret')
1215+
s10 | regress_unprivileged_role |
12141216
s4 | regress_foreign_data_user |
12151217
s5 | regress_test_role | (modified '1')
12161218
s6 | regress_test_role |
12171219
s8 | public |
12181220
s8 | regress_foreign_data_user |
12191221
s9 | regress_unprivileged_role |
12201222
t1 | public | (modified '1')
1221-
(8 rows)
1223+
(9 rows)
12221224

12231225
RESET ROLE;
1224-
-- superuser can see option fields
1226+
-- superuser can see all option fields
12251227
\deu+
12261228
List of user mappings
12271229
Server | User name | FDW options
12281230
--------+---------------------------+---------------------
12291231
s10 | public | ("user" 'secret')
1232+
s10 | regress_unprivileged_role | ("user" 'secret')
12301233
s4 | regress_foreign_data_user |
12311234
s5 | regress_test_role | (modified '1')
12321235
s6 | regress_test_role |
12331236
s8 | public |
12341237
s8 | regress_foreign_data_user | (password 'public')
12351238
s9 | regress_unprivileged_role |
12361239
t1 | public | (modified '1')
1237-
(8 rows)
1240+
(9 rows)
12381241

1239-
-- unprivileged user cannot see option fields
1242+
-- unprivileged user cannot see any option field
12401243
SET ROLE regress_unprivileged_role;
12411244
\deu+
12421245
List of user mappings
12431246
Server | User name | FDW options
12441247
--------+---------------------------+-------------
12451248
s10 | public |
1249+
s10 | regress_unprivileged_role |
12461250
s4 | regress_foreign_data_user |
12471251
s5 | regress_test_role |
12481252
s6 | regress_test_role |
12491253
s8 | public |
12501254
s8 | regress_foreign_data_user |
12511255
s9 | regress_unprivileged_role |
12521256
t1 | public |
1253-
(8 rows)
1257+
(9 rows)
12541258

12551259
RESET ROLE;
1260+
\set VERBOSITY terse
12561261
DROP SERVER s10 CASCADE;
1257-
NOTICE: drop cascades to user mapping for public on server s10
1262+
NOTICE: drop cascades to 2 other objects
1263+
\set VERBOSITY default
12581264
-- Triggers
12591265
CREATE FUNCTION dummy_trigger() RETURNS TRIGGER AS $$
12601266
BEGIN
@@ -1596,15 +1602,12 @@ Inherits: pt1
15961602
Child tables: ct3,
15971603
ft3
15981604

1605+
\set VERBOSITY terse
15991606
DROP FOREIGN TABLE ft2; -- ERROR
16001607
ERROR: cannot drop foreign table ft2 because other objects depend on it
1601-
DETAIL: table ct3 depends on foreign table ft2
1602-
foreign table ft3 depends on foreign table ft2
1603-
HINT: Use DROP ... CASCADE to drop the dependent objects too.
16041608
DROP FOREIGN TABLE ft2 CASCADE;
16051609
NOTICE: drop cascades to 2 other objects
1606-
DETAIL: drop cascades to table ct3
1607-
drop cascades to foreign table ft3
1610+
\set VERBOSITY default
16081611
CREATE FOREIGN TABLE ft2 (
16091612
c1 integer NOT NULL,
16101613
c2 text,
@@ -2026,16 +2029,12 @@ owner of user mapping for regress_test_role on server s6
20262029
DROP SERVER t1 CASCADE;
20272030
NOTICE: drop cascades to user mapping for public on server t1
20282031
DROP USER MAPPING FOR regress_test_role SERVER s6;
2029-
-- This test causes some order dependent cascade detail output,
2030-
-- so switch to terse mode for it.
20312032
\set VERBOSITY terse
20322033
DROP FOREIGN DATA WRAPPER foo CASCADE;
20332034
NOTICE: drop cascades to 5 other objects
2034-
\set VERBOSITY default
20352035
DROP SERVER s8 CASCADE;
20362036
NOTICE: drop cascades to 2 other objects
2037-
DETAIL: drop cascades to user mapping for regress_foreign_data_user on server s8
2038-
drop cascades to user mapping for public on server s8
2037+
\set VERBOSITY default
20392038
DROP ROLE regress_test_indirect;
20402039
DROP ROLE regress_test_role;
20412040
DROP ROLE regress_unprivileged_role; -- ERROR

src/test/regress/expected/rules.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2228,7 +2228,7 @@ pg_user_mappings| SELECT u.oid AS umid,
22282228
ELSE a.rolname
22292229
END AS usename,
22302230
CASE
2231-
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
2231+
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
22322232
FROM pg_authid
22332233
WHERE (pg_authid.rolname = CURRENT_USER))) THEN u.umoptions
22342234
ELSE NULL::text[]

src/test/regress/sql/foreign_data.sql

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,10 @@ CREATE SERVER s10 FOREIGN DATA WRAPPER foo; -- ERROR
484484
ALTER SERVER s9 VERSION '1.1';
485485
GRANT USAGE ON FOREIGN SERVER s9 TO regress_test_role;
486486
CREATE USER MAPPING FOR current_user SERVER s9;
487+
-- We use terse mode to avoid ordering issues in cascade detail output.
488+
\set VERBOSITY terse
487489
DROP SERVER s9 CASCADE;
490+
\set VERBOSITY default
488491
RESET ROLE;
489492
CREATE SERVER s9 FOREIGN DATA WRAPPER foo;
490493
GRANT USAGE ON FOREIGN SERVER s9 TO regress_unprivileged_role;
@@ -498,17 +501,19 @@ DROP SERVER s9 CASCADE; -- ERROR
498501
SET ROLE regress_test_role;
499502
CREATE SERVER s10 FOREIGN DATA WRAPPER foo;
500503
CREATE USER MAPPING FOR public SERVER s10 OPTIONS (user 'secret');
501-
GRANT USAGE ON FOREIGN SERVER s10 TO regress_unprivileged_role;
502-
-- owner of server can see option fields
504+
CREATE USER MAPPING FOR regress_unprivileged_role SERVER s10 OPTIONS (user 'secret');
505+
-- owner of server can see some option fields
503506
\deu+
504507
RESET ROLE;
505-
-- superuser can see option fields
508+
-- superuser can see all option fields
506509
\deu+
507-
-- unprivileged user cannot see option fields
510+
-- unprivileged user cannot see any option field
508511
SET ROLE regress_unprivileged_role;
509512
\deu+
510513
RESET ROLE;
514+
\set VERBOSITY terse
511515
DROP SERVER s10 CASCADE;
516+
\set VERBOSITY default
512517

513518
-- Triggers
514519
CREATE FUNCTION dummy_trigger() RETURNS TRIGGER AS $$
@@ -638,8 +643,10 @@ SELECT relname, conname, contype, conislocal, coninhcount, connoinherit
638643
-- child does not inherit NO INHERIT constraints
639644
\d+ pt1
640645
\d+ ft2
646+
\set VERBOSITY terse
641647
DROP FOREIGN TABLE ft2; -- ERROR
642648
DROP FOREIGN TABLE ft2 CASCADE;
649+
\set VERBOSITY default
643650
CREATE FOREIGN TABLE ft2 (
644651
c1 integer NOT NULL,
645652
c2 text,
@@ -784,12 +791,10 @@ DROP SCHEMA foreign_schema CASCADE;
784791
DROP ROLE regress_test_role; -- ERROR
785792
DROP SERVER t1 CASCADE;
786793
DROP USER MAPPING FOR regress_test_role SERVER s6;
787-
-- This test causes some order dependent cascade detail output,
788-
-- so switch to terse mode for it.
789794
\set VERBOSITY terse
790795
DROP FOREIGN DATA WRAPPER foo CASCADE;
791-
\set VERBOSITY default
792796
DROP SERVER s8 CASCADE;
797+
\set VERBOSITY default
793798
DROP ROLE regress_test_indirect;
794799
DROP ROLE regress_test_role;
795800
DROP ROLE regress_unprivileged_role; -- ERROR

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy