1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-13 16:22:44 +03:00

has_table_privilege functions from Joe Conway (with some kibitzing from

Tom Lane).  For the moment, only the OID/name variants are provided.
I didn't force initdb, but the additions to the 'privileges' regress
test won't pass until you do one.
This commit is contained in:
Tom Lane
2001-06-14 01:09:22 +00:00
parent d7763c1f9c
commit c9499e68da
10 changed files with 850 additions and 89 deletions

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.63 2001/06/12 16:34:26 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.64 2001/06/14 01:09:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -25,14 +25,25 @@
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
#define ACL_IDTYPE_GID_KEYWORD "group"
#define ACL_IDTYPE_UID_KEYWORD "user"
static const char *getid(const char *s, char *n);
static bool aclitemeq(const AclItem *a1, const AclItem *a2);
static bool aclitemgt(const AclItem *a1, const AclItem *a2);
#define ACL_IDTYPE_GID_KEYWORD "group"
#define ACL_IDTYPE_UID_KEYWORD "user"
static AclMode convert_priv_string(text *priv_type_text);
static bool has_table_privilege_cname_cname(char *username, char *relname,
text *priv_type_text);
static bool has_table_privilege_cname_id(char *username, Oid reloid,
text *priv_type_text);
static bool has_table_privilege_id_cname(int32 usesysid, char *relname,
text *priv_type_text);
/*
* getid
@@ -106,7 +117,6 @@ getid(const char *s, char *n)
const char *
aclparse(const char *s, AclItem *aip, unsigned *modechg)
{
HeapTuple htup;
char name[NAMEDATALEN];
Assert(s && aip && modechg);
@@ -183,13 +193,7 @@ aclparse(const char *s, AclItem *aip, unsigned *modechg)
switch (aip->ai_idtype)
{
case ACL_IDTYPE_UID:
htup = SearchSysCache(SHADOWNAME,
PointerGetDatum(name),
0, 0, 0);
if (!HeapTupleIsValid(htup))
elog(ERROR, "aclparse: non-existent user \"%s\"", name);
aip->ai_id = ((Form_pg_shadow) GETSTRUCT(htup))->usesysid;
ReleaseSysCache(htup);
aip->ai_id = get_usesysid(name);
break;
case ACL_IDTYPE_GID:
aip->ai_id = get_grosysid(name);
@@ -710,3 +714,367 @@ makeAclString(const char *privileges, const char *grantee, char grant_or_revoke)
pfree(str.data);
return ret;
}
/*
* has_table_privilege_name_name
* Check user privileges on a relation given
* name usename, name relname, and text priv name.
*
* RETURNS
* a boolean value
* 't' indicating user has the privilege
* 'f' indicating user does not have the privilege
*/
Datum
has_table_privilege_name_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
Name relname = PG_GETARG_NAME(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
bool result;
result = has_table_privilege_cname_cname(NameStr(*username),
NameStr(*relname),
priv_type_text);
PG_RETURN_BOOL(result);
}
/*
* has_table_privilege_name
* Check user privileges on a relation given
* name relname and text priv name.
* current_user is assumed
*
* RETURNS
* a boolean value
* 't' indicating user has the privilege
* 'f' indicating user does not have the privilege
*/
Datum
has_table_privilege_name(PG_FUNCTION_ARGS)
{
Name relname = PG_GETARG_NAME(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
int32 usesysid;
bool result;
usesysid = GetUserId();
result = has_table_privilege_id_cname(usesysid,
NameStr(*relname),
priv_type_text);
PG_RETURN_BOOL(result);
}
/*
* has_table_privilege_name_id
* Check user privileges on a relation given
* name usename, rel oid, and text priv name.
*
* RETURNS
* a boolean value
* 't' indicating user has the privilege
* 'f' indicating user does not have the privilege
*/
Datum
has_table_privilege_name_id(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
Oid reloid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
bool result;
result = has_table_privilege_cname_id(NameStr(*username),
reloid,
priv_type_text);
PG_RETURN_BOOL(result);
}
/*
* has_table_privilege_id
* Check user privileges on a relation given
* rel oid, and text priv name.
* current_user is assumed
*
* RETURNS
* a boolean value
* 't' indicating user has the privilege
* 'f' indicating user does not have the privilege
*/
Datum
has_table_privilege_id(PG_FUNCTION_ARGS)
{
Oid reloid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
char *relname;
int32 usesysid;
AclMode mode;
int32 result;
usesysid = GetUserId();
/*
* Lookup relname based on rel oid
*/
relname = get_rel_name(reloid);
if (relname == NULL)
elog(ERROR, "has_table_privilege: invalid relation oid %u",
reloid);
/*
* Convert priv_type_text to an AclMode
*/
mode = convert_priv_string(priv_type_text);
/*
* Finally, check for the privilege
*/
result = pg_aclcheck(relname, usesysid, mode);
if (result == ACLCHECK_OK)
PG_RETURN_BOOL(true);
else
PG_RETURN_BOOL(false);
}
/*
* has_table_privilege_id_name
* Check user privileges on a relation given
* usesysid, name relname, and priv name.
*
* RETURNS
* a boolean value
* 't' indicating user has the privilege
* 'f' indicating user does not have the privilege
*/
Datum
has_table_privilege_id_name(PG_FUNCTION_ARGS)
{
int32 usesysid = PG_GETARG_INT32(0);
Name relname = PG_GETARG_NAME(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
bool result;
result = has_table_privilege_id_cname(usesysid,
NameStr(*relname),
priv_type_text);
PG_RETURN_BOOL(result);
}
/*
* has_table_privilege_id_id
* Check user privileges on a relation given
* usesysid, rel oid, and priv name.
*
* RETURNS
* a boolean value
* 't' indicating user has the privilege
* 'f' indicating user does not have the privilege
*/
Datum
has_table_privilege_id_id(PG_FUNCTION_ARGS)
{
int32 usesysid = PG_GETARG_INT32(0);
Oid reloid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
char *relname;
AclMode mode;
int32 result;
/*
* Lookup relname based on rel oid
*/
relname = get_rel_name(reloid);
if (relname == NULL)
elog(ERROR, "has_table_privilege: invalid relation oid %u",
reloid);
/*
* Convert priv_type_text to an AclMode
*/
mode = convert_priv_string(priv_type_text);
/*
* Finally, check for the privilege
*/
result = pg_aclcheck(relname, usesysid, mode);
if (result == ACLCHECK_OK)
PG_RETURN_BOOL(true);
else
PG_RETURN_BOOL(false);
}
/*
* Internal functions.
*/
/*
* convert_priv_string
* Internal function.
* Return mode from priv_type string
*
* RETURNS
* AclMode
*/
static AclMode
convert_priv_string(text *priv_type_text)
{
char *priv_type = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(priv_type_text)));
/*
* Return mode from priv_type string
*/
if (strcasecmp(priv_type, "SELECT") == 0)
return ACL_SELECT;
if (strcasecmp(priv_type, "INSERT") == 0)
return ACL_INSERT;
if (strcasecmp(priv_type, "UPDATE") == 0)
return ACL_UPDATE;
if (strcasecmp(priv_type, "DELETE") == 0)
return ACL_DELETE;
if (strcasecmp(priv_type, "RULE") == 0)
return ACL_RULE;
if (strcasecmp(priv_type, "REFERENCES") == 0)
return ACL_REFERENCES;
if (strcasecmp(priv_type, "TRIGGER") == 0)
return ACL_TRIGGER;
elog(ERROR, "has_table_privilege: invalid privilege type %s", priv_type);
/*
* We should never get here, but stop the compiler from complaining
*/
return ACL_NO;
}
/*
* has_table_privilege_cname_cname
* Check user privileges on a relation given
* char *usename, char *relname, and text priv name.
*
* RETURNS
* a boolean value
* 't' indicating user has the privilege
* 'f' indicating user does not have the privilege
*/
static bool
has_table_privilege_cname_cname(char *username, char *relname,
text *priv_type_text)
{
int32 usesysid;
/*
* Lookup userid based on username
*/
usesysid = get_usesysid(username);
/*
* Make use of has_table_privilege_id_cname.
* It accepts the arguments we now have.
*/
return has_table_privilege_id_cname(usesysid, relname, priv_type_text);
}
/*
* has_table_privilege_cname_id
* Check user privileges on a relation given
* char *usename, rel oid, and text priv name.
*
* RETURNS
* a boolean value
* 't' indicating user has the privilege
* 'f' indicating user does not have the privilege
*/
static bool
has_table_privilege_cname_id(char *username, Oid reloid,
text *priv_type_text)
{
int32 usesysid;
char *relname;
/*
* Lookup userid based on username
*/
usesysid = get_usesysid(username);
/*
* Lookup relname based on rel oid
*/
relname = get_rel_name(reloid);
if (relname == NULL)
elog(ERROR, "has_table_privilege: invalid relation oid %u",
reloid);
/*
* Make use of has_table_privilege_id_cname.
* It accepts the arguments we now have.
*/
return has_table_privilege_id_cname(usesysid, relname, priv_type_text);
}
/*
* has_table_privilege_id_cname
* Check user privileges on a relation given
* usesysid, char *relname, and text priv name.
*
* RETURNS
* a boolean value
* 't' indicating user has the privilege
* 'f' indicating user does not have the privilege
*/
static bool
has_table_privilege_id_cname(int32 usesysid, char *relname,
text *priv_type_text)
{
HeapTuple tuple;
AclMode mode;
int32 result;
/*
* Check relname is valid.
* This is needed to deal with the case when usename is a superuser
* in which case pg_aclcheck simply returns ACLCHECK_OK
* without validating relname
*/
tuple = SearchSysCache(RELNAME,
PointerGetDatum(relname),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "has_table_privilege: relation \"%s\" does not exist",
relname);
ReleaseSysCache(tuple);
/*
* Convert priv_type_text to an AclMode
*/
mode = convert_priv_string(priv_type_text);
/*
* Finally, check for the privilege
*/
result = pg_aclcheck(relname, usesysid, mode);
if (result == ACLCHECK_OK)
return true;
else
return false;
}

View File

@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.55 2001/05/09 23:13:35 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.56 2001/06/14 01:09:22 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -18,6 +18,7 @@
#include "access/tupmacs.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_shadow.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
#include "utils/array.h"
@@ -25,6 +26,7 @@
#include "utils/lsyscache.h"
#include "utils/syscache.h"
/* ---------- AMOP CACHES ---------- */
/*
@@ -537,7 +539,7 @@ get_relnatts(Oid relid)
*
* Returns the name of a given relation.
*
* Note: returns a palloc'd copy of the string, or NULL if no such operator.
* Note: returns a palloc'd copy of the string, or NULL if no such relation.
*/
char *
get_rel_name(Oid relid)
@@ -1039,3 +1041,35 @@ free_attstatsslot(Oid atttype,
if (numbers)
pfree(numbers);
}
/* ---------- PG_SHADOW CACHE ---------- */
/*
* get_usesysid
*
* Given a user name, look up the user's sysid.
* Raises an error if no such user (rather than returning zero,
* which might possibly be a valid usesysid).
*
* Note: the type of usesysid is currently int4, but may change to Oid
* someday. It'd be reasonable to return zero on failure if we were
* using Oid ...
*/
int32
get_usesysid(const char *username)
{
int32 result;
HeapTuple userTup;
userTup = SearchSysCache(SHADOWNAME,
PointerGetDatum(username),
0, 0, 0);
if (!HeapTupleIsValid(userTup))
elog(ERROR, "user \"%s\" does not exist", username);
result = ((Form_pg_shadow) GETSTRUCT(userTup))->usesysid;
ReleaseSysCache(userTup);
return result;
}

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.70 2001/06/13 19:52:33 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.71 2001/06/14 01:09:22 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -30,6 +30,7 @@
#include "catalog/pg_shadow.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
@@ -442,24 +443,20 @@ InitializeSessionUserId(const char *username)
}
/*
* Change session auth ID while running
*/
void SetSessionAuthorization(const char * username)
{
HeapTuple userTup;
int32 userid;
if (!AuthenticatedUserIsSuperuser)
elog(ERROR, "permission denied");
userTup = SearchSysCache(SHADOWNAME,
PointerGetDatum(username),
0, 0, 0);
if (!HeapTupleIsValid(userTup))
elog(ERROR, "user \"%s\" does not exist", username);
userid = get_usesysid(username);
SetSessionUserId(((Form_pg_shadow) GETSTRUCT(userTup))->usesysid);
SetUserId(((Form_pg_shadow) GETSTRUCT(userTup))->usesysid);
ReleaseSysCache(userTup);
SetSessionUserId(userid);
SetUserId(userid);
}