1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-02 09:02:37 +03:00

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.
This commit is contained in:
Peter Eisentraut
2009-01-20 09:10:20 +00:00
parent fe62698218
commit 93a6be63a5
8 changed files with 89 additions and 46 deletions

View File

@ -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 $
*
*-------------------------------------------------------------------------
*/
@ -828,6 +828,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
*/
@ -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