diff options
author | Peter Eisentraut <peter_e@gmx.net> | 2009-01-20 09:10:20 +0000 |
---|---|---|
committer | Peter Eisentraut <peter_e@gmx.net> | 2009-01-20 09:10:20 +0000 |
commit | 93a6be63a55a8cd0d73b3fa81eb6a46013a3a974 (patch) | |
tree | 687e12b06f610c10bd3acf2210275fbeb7cdfb84 /src/backend | |
parent | fe626982182bd1c8cd2606027a4d49a2f31a01c3 (diff) | |
download | postgresql-93a6be63a55a8cd0d73b3fa81eb6a46013a3a974.tar.gz postgresql-93a6be63a55a8cd0d73b3fa81eb6a46013a3a974.zip |
Revise the permission checking on user mapping DDL commands.
CREATE/ALTER/DROP USER MAPPING are now allowed either by the server owner or
by a user with USAGE privileges for his own user name. This is more or less
what the SQL standard wants anyway (plus "implementation-defined")
Hide information_schema.user_mapping_options.option_value, unless the current
user is the one associated with the user mapping, or is the server owner and
the mapping is for PUBLIC, or is a superuser. This is to protect passwords.
Also, fix a bug in information_schema._pg_foreign_servers, which hid servers
using wrappers where the current user did not have privileges on the wrapper.
The correct behavior is to hide servers where the current user has no
privileges on the server.
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/information_schema.sql | 17 | ||||
-rw-r--r-- | src/backend/commands/foreigncmds.c | 56 |
2 files changed, 43 insertions, 30 deletions
diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql index 5bb46eedf8a..470a454f690 100644 --- a/src/backend/catalog/information_schema.sql +++ b/src/backend/catalog/information_schema.sql @@ -4,7 +4,7 @@ * * Copyright (c) 2003-2009, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.49 2009/01/14 21:12:09 petere Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.50 2009/01/20 09:10:20 petere Exp $ */ /* @@ -2465,12 +2465,12 @@ CREATE VIEW _pg_foreign_servers AS s.srvoptions, CAST(current_database() AS sql_identifier) AS foreign_server_catalog, CAST(srvname AS sql_identifier) AS foreign_server_name, - w.foreign_data_wrapper_catalog, - w.foreign_data_wrapper_name, + CAST(current_database() AS sql_identifier) AS foreign_data_wrapper_catalog, + CAST(w.fdwname AS sql_identifier) AS foreign_data_wrapper_name, CAST(srvtype AS character_data) AS foreign_server_type, CAST(srvversion AS character_data) AS foreign_server_version, CAST(u.rolname AS sql_identifier) AS authorization_identifier - FROM pg_foreign_server s, _pg_foreign_data_wrappers w, pg_authid u + FROM pg_foreign_server s, pg_foreign_data_wrapper w, pg_authid u WHERE w.oid = s.srvfdw AND u.oid = s.srvowner AND (pg_has_role(s.srvowner, 'USAGE') @@ -2512,9 +2512,11 @@ GRANT SELECT ON foreign_servers TO PUBLIC; CREATE VIEW _pg_user_mappings AS SELECT um.oid, um.umoptions, + um.umuser, CAST(COALESCE(u.rolname,'PUBLIC') AS sql_identifier ) AS authorization_identifier, s.foreign_server_catalog, - s.foreign_server_name + s.foreign_server_name, + s.authorization_identifier AS srvowner FROM pg_user_mapping um LEFT JOIN pg_authid u ON (u.oid = um.umuser), _pg_foreign_servers s WHERE s.oid = um.umserver; @@ -2529,7 +2531,10 @@ CREATE VIEW user_mapping_options AS foreign_server_catalog, foreign_server_name, CAST((pg_options_to_table(um.umoptions)).option_name AS sql_identifier) AS option_name, - CAST((pg_options_to_table(um.umoptions)).option_value AS character_data) AS option_value + CAST(CASE WHEN (umuser <> 0 AND authorization_identifier = current_user) + OR (umuser = 0 AND pg_has_role(srvowner, 'USAGE')) + OR (SELECT rolsuper FROM pg_authid WHERE rolname = current_user) THEN (pg_options_to_table(um.umoptions)).option_value + ELSE NULL END AS character_data) AS option_value FROM _pg_user_mappings um; GRANT SELECT ON user_mapping_options TO PUBLIC; diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index 17336c35f38..0967001aa3f 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/foreigncmds.c,v 1.4 2009/01/01 17:23:38 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/foreigncmds.c,v 1.5 2009/01/20 09:10:20 petere Exp $ * *------------------------------------------------------------------------- */ @@ -829,6 +829,33 @@ RemoveForeignServerById(Oid srvId) /* + * Common routine to check permission for user-mapping-related DDL + * commands. We allow server owners to operate on any mapping, and + * users to operate on their own mapping. + */ +static void +user_mapping_ddl_aclcheck(Oid umuserid, Oid serverid, const char *servername) +{ + Oid curuserid = GetUserId(); + + if (!pg_foreign_server_ownercheck(serverid, curuserid)) + { + if (umuserid == curuserid) + { + AclResult aclresult; + + aclresult = pg_foreign_server_aclcheck(serverid, curuserid, ACL_USAGE); + if (aclresult != ACLCHECK_OK) + aclcheck_error(aclresult, ACL_KIND_FOREIGN_SERVER, servername); + } + else + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER, + servername); + } +} + + +/* * Create user mapping */ void @@ -841,24 +868,17 @@ CreateUserMapping(CreateUserMappingStmt *stmt) HeapTuple tuple; Oid useId; Oid umId; - Oid ownerId; ObjectAddress myself; ObjectAddress referenced; ForeignServer *srv; ForeignDataWrapper *fdw; - ownerId = GetUserId(); - useId = GetUserOidFromMapping(stmt->username, false); - /* - * Check that the server exists and that the we own it. - */ + /* Check that the server exists. */ srv = GetForeignServerByName(stmt->servername, false); - if (!pg_foreign_server_ownercheck(srv->serverid, ownerId)) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER, - stmt->servername); + user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername); /* * Check that the user mapping is unique within server. @@ -951,12 +971,7 @@ AlterUserMapping(AlterUserMappingStmt *stmt) errmsg("user mapping \"%s\" does not exist for the server", MappingUserName(useId)))); - /* - * Must be owner of the server to alter user mapping. - */ - if (!pg_foreign_server_ownercheck(srv->serverid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER, - stmt->servername); + user_mapping_ddl_aclcheck(useId, srv->serverid, stmt->servername); tp = SearchSysCacheCopy(USERMAPPINGOID, ObjectIdGetDatum(umId), @@ -1071,14 +1086,7 @@ RemoveUserMapping(DropUserMappingStmt *stmt) return; } - /* - * Only allow DROP if we own the server. - */ - if (!pg_foreign_server_ownercheck(srv->serverid, GetUserId())) - { - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER, - srv->servername); - } + user_mapping_ddl_aclcheck(useId, srv->serverid, srv->servername); /* * Do the deletion |