Commit 56c9b73c authored by Tom Lane's avatar Tom Lane

Change the aclchk.c routines to uniformly use OIDs to identify the

objects to be privilege-checked.  Some change in their APIs would be
necessary no matter what in the schema environment, and simply getting
rid of the name-based interface entirely seems like the best way.
parent 6137ed1b
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.57 2002/03/21 16:00:29 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.58 2002/03/21 23:27:19 tgl Exp $
* *
* NOTES * NOTES
* See acl.h. * See acl.h.
...@@ -50,8 +50,8 @@ static const char *privilege_token_string(int token); ...@@ -50,8 +50,8 @@ static const char *privilege_token_string(int token);
static int32 aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode); static int32 aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode);
/* warning messages, now more explicit. */ /* warning messages, now more explicit. */
/* MUST correspond to the order of the ACLCHK_* result codes in acl.h. */ /* MUST correspond to the order of the ACLCHECK_* result codes in acl.h. */
char *aclcheck_error_strings[] = { const char * const aclcheck_error_strings[] = {
"No error.", "No error.",
"Permission denied.", "Permission denied.",
"Table does not exist.", "Table does not exist.",
...@@ -66,11 +66,11 @@ dumpacl(Acl *acl) ...@@ -66,11 +66,11 @@ dumpacl(Acl *acl)
int i; int i;
AclItem *aip; AclItem *aip;
elog(LOG, "acl size = %d, # acls = %d", elog(DEBUG1, "acl size = %d, # acls = %d",
ACL_SIZE(acl), ACL_NUM(acl)); ACL_SIZE(acl), ACL_NUM(acl));
aip = ACL_DAT(acl); aip = ACL_DAT(acl);
for (i = 0; i < ACL_NUM(acl); ++i) for (i = 0; i < ACL_NUM(acl); ++i)
elog(LOG, " acl[%d]: %s", i, elog(DEBUG1, " acl[%d]: %s", i,
DatumGetCString(DirectFunctionCall1(aclitemout, DatumGetCString(DirectFunctionCall1(aclitemout,
PointerGetDatum(aip + i)))); PointerGetDatum(aip + i))));
} }
...@@ -214,23 +214,20 @@ ExecuteGrantStmt_Table(GrantStmt *stmt) ...@@ -214,23 +214,20 @@ ExecuteGrantStmt_Table(GrantStmt *stmt)
char nulls[Natts_pg_class]; char nulls[Natts_pg_class];
char replaces[Natts_pg_class]; char replaces[Natts_pg_class];
if (!pg_ownercheck(GetUserId(), relname, RELNAME))
elog(ERROR, "permission denied");
/* open pg_class */ /* open pg_class */
relation = heap_openr(RelationRelationName, RowExclusiveLock); relation = heap_openr(RelationRelationName, RowExclusiveLock);
tuple = SearchSysCache(RELNAME, tuple = SearchSysCache(RELNAME,
PointerGetDatum(relname), PointerGetDatum(relname),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
{
heap_close(relation, RowExclusiveLock);
elog(ERROR, "relation \"%s\" not found", elog(ERROR, "relation \"%s\" not found",
relname); relname);
}
pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple); pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
if (!pg_class_ownercheck(tuple->t_data->t_oid, GetUserId()))
elog(ERROR, "%s: permission denied",
relname);
if (pg_class_tuple->relkind == RELKIND_INDEX) if (pg_class_tuple->relkind == RELKIND_INDEX)
elog(ERROR, "\"%s\" is an index", elog(ERROR, "\"%s\" is an index",
relname); relname);
...@@ -658,7 +655,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode) ...@@ -658,7 +655,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
*/ */
if (!acl) if (!acl)
{ {
elog(LOG, "aclcheck: null ACL, returning OK"); elog(DEBUG1, "aclcheck: null ACL, returning OK");
return ACLCHECK_OK; return ACLCHECK_OK;
} }
...@@ -673,7 +670,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode) ...@@ -673,7 +670,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
*/ */
if (num < 1) if (num < 1)
{ {
elog(LOG, "aclcheck: zero-length ACL, returning OK"); elog(DEBUG1, "aclcheck: zero-length ACL, returning OK");
return ACLCHECK_OK; return ACLCHECK_OK;
} }
...@@ -686,7 +683,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode) ...@@ -686,7 +683,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
if (aidat->ai_mode & mode) if (aidat->ai_mode & mode)
{ {
#ifdef ACLDEBUG #ifdef ACLDEBUG
elog(LOG, "aclcheck: using world=%d", aidat->ai_mode); elog(DEBUG1, "aclcheck: using world=%d", aidat->ai_mode);
#endif #endif
return ACLCHECK_OK; return ACLCHECK_OK;
} }
...@@ -702,7 +699,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode) ...@@ -702,7 +699,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
if (aip->ai_id == id) if (aip->ai_id == id)
{ {
#ifdef ACLDEBUG #ifdef ACLDEBUG
elog(LOG, "aclcheck: found user %u/%d", elog(DEBUG1, "aclcheck: found user %u/%d",
aip->ai_id, aip->ai_mode); aip->ai_id, aip->ai_mode);
#endif #endif
if (aip->ai_mode & mode) if (aip->ai_mode & mode)
...@@ -719,7 +716,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode) ...@@ -719,7 +716,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
if (in_group(id, aip->ai_id)) if (in_group(id, aip->ai_id))
{ {
#ifdef ACLDEBUG #ifdef ACLDEBUG
elog(LOG, "aclcheck: found group %u/%d", elog(DEBUG1, "aclcheck: found group %u/%d",
aip->ai_id, aip->ai_mode); aip->ai_id, aip->ai_mode);
#endif #endif
return ACLCHECK_OK; return ACLCHECK_OK;
...@@ -740,7 +737,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode) ...@@ -740,7 +737,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
if (aip->ai_id == id) if (aip->ai_id == id)
{ {
#ifdef ACLDEBUG #ifdef ACLDEBUG
elog(LOG, "aclcheck: found group %u/%d", elog(DEBUG1, "aclcheck: found group %u/%d",
aip->ai_id, aip->ai_mode); aip->ai_id, aip->ai_mode);
#endif #endif
if (aip->ai_mode & mode) if (aip->ai_mode & mode)
...@@ -760,46 +757,63 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode) ...@@ -760,46 +757,63 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
return ACLCHECK_NO_PRIV; return ACLCHECK_NO_PRIV;
} }
/* /*
* Exported routine for checking a user's access privileges to a table * Exported routine for checking a user's access privileges to a table
* *
* Returns an ACLCHECK_* result code. * Returns an ACLCHECK_* result code.
*/ */
int32 int32
pg_aclcheck(char *relname, Oid userid, AclMode mode) pg_class_aclcheck(Oid table_oid, Oid userid, AclMode mode)
{ {
int32 result; int32 result;
bool usesuper,
usecatupd;
char *relname;
HeapTuple tuple; HeapTuple tuple;
char *usename;
Datum aclDatum; Datum aclDatum;
bool isNull; bool isNull;
Acl *acl; Acl *acl;
/* /*
* Validate userid, find out if he is superuser * Validate userid, find out if he is superuser
*
* We do not use superuser_arg() here because we also need to check
* usecatupd.
*/ */
tuple = SearchSysCache(SHADOWSYSID, tuple = SearchSysCache(SHADOWSYSID,
ObjectIdGetDatum(userid), ObjectIdGetDatum(userid),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_aclcheck: invalid user id %u", elog(ERROR, "pg_class_aclcheck: invalid user id %u", userid);
(unsigned) userid);
usename = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename); usesuper = ((Form_pg_shadow) GETSTRUCT(tuple))->usesuper;
usecatupd = ((Form_pg_shadow) GETSTRUCT(tuple))->usecatupd;
ReleaseSysCache(tuple);
/*
* Now get the relation's tuple from pg_class
*/
tuple = SearchSysCache(RELOID,
ObjectIdGetDatum(table_oid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_class_aclcheck: relation %u not found", table_oid);
/* /*
* Deny anyone permission to update a system catalog unless * Deny anyone permission to update a system catalog unless
* pg_shadow.usecatupd is set. (This is to let superusers protect * pg_shadow.usecatupd is set. (This is to let superusers protect
* themselves from themselves.) * themselves from themselves.)
*/ */
relname = NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname);
if ((mode & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) && if ((mode & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
!allowSystemTableMods && IsSystemRelationName(relname) && !allowSystemTableMods && IsSystemRelationName(relname) &&
!is_temp_relname(relname) && !is_temp_relname(relname) &&
!((Form_pg_shadow) GETSTRUCT(tuple))->usecatupd) !usecatupd)
{ {
#ifdef ACLDEBUG #ifdef ACLDEBUG
elog(LOG, "pg_aclcheck: catalog update to \"%s\": permission denied", elog(DEBUG1, "pg_class_aclcheck: catalog update: permission denied");
relname);
#endif #endif
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
return ACLCHECK_NO_PRIV; return ACLCHECK_NO_PRIV;
...@@ -808,29 +822,19 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode) ...@@ -808,29 +822,19 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode)
/* /*
* Otherwise, superusers bypass all permission-checking. * Otherwise, superusers bypass all permission-checking.
*/ */
if (((Form_pg_shadow) GETSTRUCT(tuple))->usesuper) if (usesuper)
{ {
#ifdef ACLDEBUG #ifdef ACLDEBUG
elog(LOG, "pg_aclcheck: \"%s\" is superuser", elog(DEBUG1, "pg_class_aclcheck: %u is superuser", userid);
usename);
#endif #endif
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
return ACLCHECK_OK; return ACLCHECK_OK;
} }
ReleaseSysCache(tuple);
/* caution: usename is inaccessible beyond this point... */
/* /*
* Normal case: get the relation's ACL from pg_class * Normal case: get the relation's ACL from pg_class
*/ */
tuple = SearchSysCache(RELNAME, aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
PointerGetDatum(relname),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_aclcheck: class \"%s\" not found", relname);
aclDatum = SysCacheGetAttr(RELNAME, tuple, Anum_pg_class_relacl,
&isNull); &isNull);
if (isNull) if (isNull)
{ {
...@@ -858,227 +862,6 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode) ...@@ -858,227 +862,6 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode)
return result; return result;
} }
/*
* Check ownership of an object identified by name (which will be looked
* up in the system cache identified by cacheid).
*
* Returns true if userid owns the item, or should be allowed to modify
* the item as if he owned it.
*/
bool
pg_ownercheck(Oid userid,
const char *name,
int cacheid)
{
HeapTuple tuple;
AclId owner_id;
char *usename;
tuple = SearchSysCache(SHADOWSYSID,
ObjectIdGetDatum(userid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_ownercheck: invalid user id %u",
(unsigned) userid);
usename = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
/*
* Superusers bypass all permission-checking.
*/
if (((Form_pg_shadow) GETSTRUCT(tuple))->usesuper)
{
#ifdef ACLDEBUG
elog(LOG, "pg_ownercheck: user \"%s\" is superuser",
usename);
#endif
ReleaseSysCache(tuple);
return true;
}
ReleaseSysCache(tuple);
/* caution: usename is inaccessible beyond this point... */
tuple = SearchSysCache(cacheid,
PointerGetDatum(name),
0, 0, 0);
switch (cacheid)
{
case RELNAME:
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_ownercheck: class \"%s\" not found",
name);
owner_id = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
break;
case TYPENAME:
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_ownercheck: type \"%s\" not found",
name);
owner_id = ((Form_pg_type) GETSTRUCT(tuple))->typowner;
break;
default:
elog(ERROR, "pg_ownercheck: invalid cache id: %d", cacheid);
owner_id = 0; /* keep compiler quiet */
break;
}
ReleaseSysCache(tuple);
return userid == owner_id;
}
/*
* Ownership check for an operator (specified by OID).
*/
bool
pg_oper_ownercheck(Oid userid, Oid oprid)
{
HeapTuple tuple;
AclId owner_id;
char *usename;
tuple = SearchSysCache(SHADOWSYSID,
ObjectIdGetDatum(userid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_oper_ownercheck: invalid user id %u",
(unsigned) userid);
usename = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
/*
* Superusers bypass all permission-checking.
*/
if (((Form_pg_shadow) GETSTRUCT(tuple))->usesuper)
{
#ifdef ACLDEBUG
elog(LOG, "pg_ownercheck: user \"%s\" is superuser",
usename);
#endif
ReleaseSysCache(tuple);
return true;
}
ReleaseSysCache(tuple);
/* caution: usename is inaccessible beyond this point... */
tuple = SearchSysCache(OPEROID,
ObjectIdGetDatum(oprid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_ownercheck: operator %u not found",
oprid);
owner_id = ((Form_pg_operator) GETSTRUCT(tuple))->oprowner;
ReleaseSysCache(tuple);
return userid == owner_id;
}
/*
* Ownership check for a function (specified by name and argument types).
*/
bool
pg_func_ownercheck(Oid userid,
char *funcname,
int nargs,
Oid *arglist)
{
HeapTuple tuple;
AclId owner_id;
char *usename;
tuple = SearchSysCache(SHADOWSYSID,
ObjectIdGetDatum(userid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_func_ownercheck: invalid user id %u",
(unsigned) userid);
usename = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
/*
* Superusers bypass all permission-checking.
*/
if (((Form_pg_shadow) GETSTRUCT(tuple))->usesuper)
{
#ifdef ACLDEBUG
elog(LOG, "pg_ownercheck: user \"%s\" is superuser",
usename);
#endif
ReleaseSysCache(tuple);
return true;
}
ReleaseSysCache(tuple);
/* caution: usename is inaccessible beyond this point... */
tuple = SearchSysCache(PROCNAME,
PointerGetDatum(funcname),
Int32GetDatum(nargs),
PointerGetDatum(arglist),
0);
if (!HeapTupleIsValid(tuple))
func_error("pg_func_ownercheck", funcname, nargs, arglist, NULL);
owner_id = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
ReleaseSysCache(tuple);
return userid == owner_id;
}
/*
* Ownership check for an aggregate function (specified by name and
* argument type).
*/
bool
pg_aggr_ownercheck(Oid userid,
char *aggname,
Oid basetypeID)
{
HeapTuple tuple;
AclId owner_id;
char *usename;
tuple = SearchSysCache(SHADOWSYSID,
PointerGetDatum(userid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_aggr_ownercheck: invalid user id %u",
(unsigned) userid);
usename = NameStr(((Form_pg_shadow) GETSTRUCT(tuple))->usename);
/*
* Superusers bypass all permission-checking.
*/
if (((Form_pg_shadow) GETSTRUCT(tuple))->usesuper)
{
#ifdef ACLDEBUG
elog(LOG, "pg_aggr_ownercheck: user \"%s\" is superuser",
usename);
#endif
ReleaseSysCache(tuple);
return true;
}
ReleaseSysCache(tuple);
/* caution: usename is inaccessible beyond this point... */
tuple = SearchSysCache(AGGNAME,
PointerGetDatum(aggname),
ObjectIdGetDatum(basetypeID),
0, 0);
if (!HeapTupleIsValid(tuple))
agg_error("pg_aggr_ownercheck", aggname, basetypeID);
owner_id = ((Form_pg_aggregate) GETSTRUCT(tuple))->aggowner;
ReleaseSysCache(tuple);
return userid == owner_id;
}
/* /*
* Exported routine for checking a user's access privileges to a function * Exported routine for checking a user's access privileges to a function
* *
...@@ -1093,22 +876,12 @@ pg_proc_aclcheck(Oid proc_oid, Oid userid) ...@@ -1093,22 +876,12 @@ pg_proc_aclcheck(Oid proc_oid, Oid userid)
bool isNull; bool isNull;
Acl *acl; Acl *acl;
/* Superusers bypass all permission checking. */
if (superuser_arg(userid)) if (superuser_arg(userid))
return ACLCHECK_OK; return ACLCHECK_OK;
/* /*
* Validate userid * Get the function's ACL from pg_proc
*/
tuple = SearchSysCache(SHADOWSYSID,
ObjectIdGetDatum(userid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_proc_aclcheck: invalid user id %u",
(unsigned) userid);
ReleaseSysCache(tuple);
/*
* Normal case: get the function's ACL from pg_proc
*/ */
tuple = SearchSysCache(PROCOID, tuple = SearchSysCache(PROCOID,
ObjectIdGetDatum(proc_oid), ObjectIdGetDatum(proc_oid),
...@@ -1148,8 +921,6 @@ pg_proc_aclcheck(Oid proc_oid, Oid userid) ...@@ -1148,8 +921,6 @@ pg_proc_aclcheck(Oid proc_oid, Oid userid)
return result; return result;
} }
/* /*
* Exported routine for checking a user's access privileges to a language * Exported routine for checking a user's access privileges to a language
* *
...@@ -1164,22 +935,12 @@ pg_language_aclcheck(Oid lang_oid, Oid userid) ...@@ -1164,22 +935,12 @@ pg_language_aclcheck(Oid lang_oid, Oid userid)
bool isNull; bool isNull;
Acl *acl; Acl *acl;
/* Superusers bypass all permission checking. */
if (superuser_arg(userid)) if (superuser_arg(userid))
return ACLCHECK_OK; return ACLCHECK_OK;
/* /*
* Validate userid * Get the function's ACL from pg_language
*/
tuple = SearchSysCache(SHADOWSYSID,
ObjectIdGetDatum(userid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_language_aclcheck: invalid user id %u",
(unsigned) userid);
ReleaseSysCache(tuple);
/*
* Normal case: get the function's ACL from pg_language
*/ */
tuple = SearchSysCache(LANGOID, tuple = SearchSysCache(LANGOID,
ObjectIdGetDatum(lang_oid), ObjectIdGetDatum(lang_oid),
...@@ -1215,3 +976,134 @@ pg_language_aclcheck(Oid lang_oid, Oid userid) ...@@ -1215,3 +976,134 @@ pg_language_aclcheck(Oid lang_oid, Oid userid)
return result; return result;
} }
/*
* Ownership check for a relation (specified by OID).
*/
bool
pg_class_ownercheck(Oid class_oid, Oid userid)
{
HeapTuple tuple;
AclId owner_id;
/* Superusers bypass all permission checking. */
if (superuser_arg(userid))
return true;
tuple = SearchSysCache(RELOID,
ObjectIdGetDatum(class_oid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_class_ownercheck: relation %u not found", class_oid);
owner_id = ((Form_pg_class) GETSTRUCT(tuple))->relowner;
ReleaseSysCache(tuple);
return userid == owner_id;
}
/*
* Ownership check for a type (specified by OID).
*/
bool
pg_type_ownercheck(Oid type_oid, Oid userid)
{
HeapTuple tuple;
AclId owner_id;
/* Superusers bypass all permission checking. */
if (superuser_arg(userid))
return true;
tuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(type_oid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_type_ownercheck: type %u not found", type_oid);
owner_id = ((Form_pg_type) GETSTRUCT(tuple))->typowner;
ReleaseSysCache(tuple);
return userid == owner_id;
}
/*
* Ownership check for an operator (specified by OID).
*/
bool
pg_oper_ownercheck(Oid oper_oid, Oid userid)
{
HeapTuple tuple;
AclId owner_id;
/* Superusers bypass all permission checking. */
if (superuser_arg(userid))
return true;
tuple = SearchSysCache(OPEROID,
ObjectIdGetDatum(oper_oid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_oper_ownercheck: operator %u not found", oper_oid);
owner_id = ((Form_pg_operator) GETSTRUCT(tuple))->oprowner;
ReleaseSysCache(tuple);
return userid == owner_id;
}
/*
* Ownership check for a function (specified by OID).
*/
bool
pg_proc_ownercheck(Oid proc_oid, Oid userid)
{
HeapTuple tuple;
AclId owner_id;
/* Superusers bypass all permission checking. */
if (superuser_arg(userid))
return true;
tuple = SearchSysCache(PROCOID,
ObjectIdGetDatum(proc_oid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_proc_ownercheck: function %u not found", proc_oid);
owner_id = ((Form_pg_proc) GETSTRUCT(tuple))->proowner;
ReleaseSysCache(tuple);
return userid == owner_id;
}
/*
* Ownership check for an aggregate function (specified by OID).
*/
bool
pg_aggr_ownercheck(Oid aggr_oid, Oid userid)
{
HeapTuple tuple;
AclId owner_id;
/* Superusers bypass all permission checking. */
if (superuser_arg(userid))
return true;
tuple = SearchSysCache(AGGOID,
ObjectIdGetDatum(aggr_oid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "pg_aggr_ownercheck: aggregate %u not found", aggr_oid);
owner_id = ((Form_pg_aggregate) GETSTRUCT(tuple))->aggowner;
ReleaseSysCache(tuple);
return userid == owner_id;
}
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.28 2002/03/06 06:09:28 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.29 2002/03/21 23:27:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -200,8 +200,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt) ...@@ -200,8 +200,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
*/ */
onerel = heap_open(relid, AccessShareLock); onerel = heap_open(relid, AccessShareLock);
if (!(pg_ownercheck(GetUserId(), RelationGetRelationName(onerel), if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) ||
RELNAME) ||
(is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared))) (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared)))
{ {
/* No need for a WARNING if we already complained during VACUUM */ /* No need for a WARNING if we already complained during VACUUM */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.162 2002/03/21 16:00:31 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.163 2002/03/21 23:27:20 tgl Exp $
* *
* NOTES * NOTES
* The PerformAddAttribute() code, like most of the relation * The PerformAddAttribute() code, like most of the relation
...@@ -327,6 +327,17 @@ AlterTableAddColumn(const char *relationName, ...@@ -327,6 +327,17 @@ AlterTableAddColumn(const char *relationName,
char *typename; char *typename;
int attndims; int attndims;
/*
* Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction.
*/
rel = heap_openr(relationName, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName);
/* /*
* permissions checking. this would normally be done in utility.c, * permissions checking. this would normally be done in utility.c,
* but this particular routine is recursive. * but this particular routine is recursive.
...@@ -336,20 +347,9 @@ AlterTableAddColumn(const char *relationName, ...@@ -336,20 +347,9 @@ AlterTableAddColumn(const char *relationName,
if (!allowSystemTableMods && IsSystemRelationName(relationName)) if (!allowSystemTableMods && IsSystemRelationName(relationName))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog", elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName); relationName);
if (!pg_ownercheck(GetUserId(), relationName, RELNAME)) if (!pg_class_ownercheck(myrelid, GetUserId()))
elog(ERROR, "ALTER TABLE: permission denied"); elog(ERROR, "ALTER TABLE: permission denied");
/*
* Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction.
*/
rel = heap_openr(relationName, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName);
myrelid = RelationGetRelid(rel);
heap_close(rel, NoLock); /* close rel but keep lock! */ heap_close(rel, NoLock); /* close rel but keep lock! */
/* /*
...@@ -556,21 +556,19 @@ AlterTableAlterColumnDefault(const char *relationName, ...@@ -556,21 +556,19 @@ AlterTableAlterColumnDefault(const char *relationName,
int16 attnum; int16 attnum;
Oid myrelid; Oid myrelid;
if (!allowSystemTableMods && IsSystemRelationName(relationName))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
#ifndef NO_SECURITY
if (!pg_ownercheck(GetUserId(), relationName, RELNAME))
elog(ERROR, "ALTER TABLE: permission denied");
#endif
rel = heap_openr(relationName, AccessExclusiveLock); rel = heap_openr(relationName, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
if (rel->rd_rel->relkind != RELKIND_RELATION) if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table", elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName); relationName);
myrelid = RelationGetRelid(rel); if (!allowSystemTableMods && IsSystemRelationName(relationName))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
if (!pg_class_ownercheck(myrelid, GetUserId()))
elog(ERROR, "ALTER TABLE: permission denied");
heap_close(rel, NoLock); heap_close(rel, NoLock);
/* /*
...@@ -730,24 +728,21 @@ AlterTableAlterColumnFlags(const char *relationName, ...@@ -730,24 +728,21 @@ AlterTableAlterColumnFlags(const char *relationName,
Relation attrelation; Relation attrelation;
HeapTuple tuple; HeapTuple tuple;
/* we allow statistics case for system tables */
if (*flagType =='M' && !allowSystemTableMods && IsSystemRelationName(relationName))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
#ifndef NO_SECURITY
if (!pg_ownercheck(GetUserId(), relationName, RELNAME))
elog(ERROR, "ALTER TABLE: permission denied");
#endif
rel = heap_openr(relationName, AccessExclusiveLock); rel = heap_openr(relationName, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
if (rel->rd_rel->relkind != RELKIND_RELATION) if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table", elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName); relationName);
myrelid = RelationGetRelid(rel); /* we allow statistics case for system tables */
if (*flagType == 'M' &&
!allowSystemTableMods && IsSystemRelationName(relationName))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
if (!pg_class_ownercheck(myrelid, GetUserId()))
elog(ERROR, "ALTER TABLE: permission denied");
heap_close(rel, NoLock); /* close rel, but keep lock! */ heap_close(rel, NoLock); /* close rel, but keep lock! */
...@@ -1034,6 +1029,17 @@ AlterTableDropColumn(const char *relationName, ...@@ -1034,6 +1029,17 @@ AlterTableDropColumn(const char *relationName,
if (inh) if (inh)
elog(ERROR, "ALTER TABLE / DROP COLUMN with inherit option is not supported yet"); elog(ERROR, "ALTER TABLE / DROP COLUMN with inherit option is not supported yet");
/*
* Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction.
*/
rel = heap_openr(relationName, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName);
/* /*
* permissions checking. this would normally be done in utility.c, * permissions checking. this would normally be done in utility.c,
* but this particular routine is recursive. * but this particular routine is recursive.
...@@ -1043,22 +1049,9 @@ AlterTableDropColumn(const char *relationName, ...@@ -1043,22 +1049,9 @@ AlterTableDropColumn(const char *relationName,
if (!allowSystemTableMods && IsSystemRelationName(relationName)) if (!allowSystemTableMods && IsSystemRelationName(relationName))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog", elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName); relationName);
#ifndef NO_SECURITY if (!pg_class_ownercheck(myrelid, GetUserId()))
if (!pg_ownercheck(GetUserId(), relationName, RELNAME))
elog(ERROR, "ALTER TABLE: permission denied"); elog(ERROR, "ALTER TABLE: permission denied");
#endif
/*
* Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction.
*/
rel = heap_openr(relationName, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName);
myrelid = RelationGetRelid(rel);
heap_close(rel, NoLock); /* close rel but keep lock! */ heap_close(rel, NoLock); /* close rel but keep lock! */
/* /*
...@@ -1180,25 +1173,22 @@ AlterTableAddConstraint(char *relationName, ...@@ -1180,25 +1173,22 @@ AlterTableAddConstraint(char *relationName,
Oid myrelid; Oid myrelid;
List *listptr; List *listptr;
if (!allowSystemTableMods && IsSystemRelationName(relationName))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
#ifndef NO_SECURITY
if (!pg_ownercheck(GetUserId(), relationName, RELNAME))
elog(ERROR, "ALTER TABLE: permission denied");
#endif
/* /*
* Grab an exclusive lock on the target table, which we will NOT * Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction. * release until end of transaction.
*/ */
rel = heap_openr(relationName, AccessExclusiveLock); rel = heap_openr(relationName, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
if (rel->rd_rel->relkind != RELKIND_RELATION) if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table", elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName); relationName);
myrelid = RelationGetRelid(rel); if (!allowSystemTableMods && IsSystemRelationName(relationName))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
if (!pg_class_ownercheck(myrelid, GetUserId()))
elog(ERROR, "ALTER TABLE: permission denied");
if (inh) if (inh)
{ {
...@@ -1496,16 +1486,9 @@ AlterTableDropConstraint(const char *relationName, ...@@ -1496,16 +1486,9 @@ AlterTableDropConstraint(const char *relationName,
int behavior) int behavior)
{ {
Relation rel; Relation rel;
Oid myrelid;
int deleted; int deleted;
if (!allowSystemTableMods && IsSystemRelationName(relationName))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
#ifndef NO_SECURITY
if (!pg_ownercheck(GetUserId(), relationName, RELNAME))
elog(ERROR, "ALTER TABLE: permission denied");
#endif
/* /*
* We don't support CASCADE yet - in fact, RESTRICT doesn't work to * We don't support CASCADE yet - in fact, RESTRICT doesn't work to
* the spec either! * the spec either!
...@@ -1517,14 +1500,20 @@ AlterTableDropConstraint(const char *relationName, ...@@ -1517,14 +1500,20 @@ AlterTableDropConstraint(const char *relationName,
* Acquire an exclusive lock on the target relation for the duration * Acquire an exclusive lock on the target relation for the duration
* of the operation. * of the operation.
*/ */
rel = heap_openr(relationName, AccessExclusiveLock); rel = heap_openr(relationName, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
/* Disallow DROP CONSTRAINT on views, indexes, sequences, etc */ /* Disallow DROP CONSTRAINT on views, indexes, sequences, etc */
if (rel->rd_rel->relkind != RELKIND_RELATION) if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table", elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName); relationName);
if (!allowSystemTableMods && IsSystemRelationName(relationName))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
if (!pg_class_ownercheck(myrelid, GetUserId()))
elog(ERROR, "ALTER TABLE: permission denied");
/* /*
* Since all we have is the name of the constraint, we have to look * Since all we have is the name of the constraint, we have to look
* through all catalogs that could possibly contain a constraint for * through all catalogs that could possibly contain a constraint for
...@@ -1692,25 +1681,19 @@ AlterTableCreateToastTable(const char *relationName, bool silent) ...@@ -1692,25 +1681,19 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
IndexInfo *indexInfo; IndexInfo *indexInfo;
Oid classObjectId[2]; Oid classObjectId[2];
/*
* permissions checking. XXX exactly what is appropriate here?
*/
#ifndef NO_SECURITY
if (!pg_ownercheck(GetUserId(), relationName, RELNAME))
elog(ERROR, "ALTER TABLE: permission denied");
#endif
/* /*
* Grab an exclusive lock on the target table, which we will NOT * Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction. * release until end of transaction.
*/ */
rel = heap_openr(relationName, AccessExclusiveLock); rel = heap_openr(relationName, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
if (rel->rd_rel->relkind != RELKIND_RELATION) if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table", elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName); relationName);
myrelid = RelationGetRelid(rel); if (!pg_class_ownercheck(myrelid, GetUserId()))
elog(ERROR, "ALTER TABLE: permission denied");
/* /*
* lock the pg_class tuple for update (is that really needed?) * lock the pg_class tuple for update (is that really needed?)
...@@ -1940,20 +1923,32 @@ LockTableCommand(LockStmt *lockstmt) ...@@ -1940,20 +1923,32 @@ LockTableCommand(LockStmt *lockstmt)
{ {
RangeVar *relation = lfirst(p); RangeVar *relation = lfirst(p);
char *relname = relation->relname; char *relname = relation->relname;
Oid reloid;
int aclresult; int aclresult;
Relation rel; Relation rel;
/*
* We don't want to open the relation until we've checked privilege.
* So, manually get the relation OID.
*/
reloid = GetSysCacheOid(RELNAME,
PointerGetDatum(relname),
0, 0, 0);
if (!OidIsValid(reloid))
elog(ERROR, "LOCK TABLE: relation \"%s\" does not exist",
relname);
if (lockstmt->mode == AccessShareLock) if (lockstmt->mode == AccessShareLock)
aclresult = pg_aclcheck(relname, GetUserId(), aclresult = pg_class_aclcheck(reloid, GetUserId(),
ACL_SELECT); ACL_SELECT);
else else
aclresult = pg_aclcheck(relname, GetUserId(), aclresult = pg_class_aclcheck(reloid, GetUserId(),
ACL_UPDATE | ACL_DELETE); ACL_UPDATE | ACL_DELETE);
if (aclresult != ACLCHECK_OK) if (aclresult != ACLCHECK_OK)
elog(ERROR, "LOCK TABLE: permission denied"); elog(ERROR, "LOCK TABLE: permission denied");
rel = relation_openr(relname, lockstmt->mode); rel = relation_open(reloid, lockstmt->mode);
/* Currently, we only allow plain tables to be locked */ /* Currently, we only allow plain tables to be locked */
if (rel->rd_rel->relkind != RELKIND_RELATION) if (rel->rd_rel->relkind != RELKIND_RELATION)
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Copyright (c) 1999-2001, PostgreSQL Global Development Group * Copyright (c) 1999-2001, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.35 2001/11/02 16:30:29 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.36 2002/03/21 23:27:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "catalog/pg_database.h" #include "catalog/pg_database.h"
#include "catalog/pg_description.h" #include "catalog/pg_description.h"
#include "catalog/pg_operator.h" #include "catalog/pg_operator.h"
#include "catalog/pg_rewrite.h"
#include "catalog/pg_trigger.h" #include "catalog/pg_trigger.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "commands/comment.h" #include "commands/comment.h"
...@@ -326,11 +327,6 @@ CommentRelation(int reltype, char *relname, char *comment) ...@@ -326,11 +327,6 @@ CommentRelation(int reltype, char *relname, char *comment)
{ {
Relation relation; Relation relation;
/* First, check object security */
if (!pg_ownercheck(GetUserId(), relname, RELNAME))
elog(ERROR, "you are not permitted to comment on class '%s'", relname);
/* /*
* Open the relation. We do this mainly to acquire a lock that * Open the relation. We do this mainly to acquire a lock that
* ensures no one else drops the relation before we commit. (If they * ensures no one else drops the relation before we commit. (If they
...@@ -339,6 +335,10 @@ CommentRelation(int reltype, char *relname, char *comment) ...@@ -339,6 +335,10 @@ CommentRelation(int reltype, char *relname, char *comment)
*/ */
relation = relation_openr(relname, AccessShareLock); relation = relation_openr(relname, AccessShareLock);
/* Check object security */
if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
elog(ERROR, "you are not permitted to comment on class '%s'", relname);
/* Next, verify that the relation type matches the intent */ /* Next, verify that the relation type matches the intent */
switch (reltype) switch (reltype)
...@@ -387,15 +387,15 @@ CommentAttribute(char *relname, char *attrname, char *comment) ...@@ -387,15 +387,15 @@ CommentAttribute(char *relname, char *attrname, char *comment)
Relation relation; Relation relation;
AttrNumber attnum; AttrNumber attnum;
/* First, check object security */
if (!pg_ownercheck(GetUserId(), relname, RELNAME))
elog(ERROR, "you are not permitted to comment on class '%s'", relname);
/* Open the containing relation to ensure it won't go away meanwhile */ /* Open the containing relation to ensure it won't go away meanwhile */
relation = heap_openr(relname, AccessShareLock); relation = heap_openr(relname, AccessShareLock);
/* Check object security */
if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
elog(ERROR, "you are not permitted to comment on class '%s'", relname);
/* Now, fetch the attribute number from the system cache */ /* Now, fetch the attribute number from the system cache */
attnum = get_attnum(RelationGetRelid(relation), attrname); attnum = get_attnum(RelationGetRelid(relation), attrname);
...@@ -476,27 +476,32 @@ CommentDatabase(char *database, char *comment) ...@@ -476,27 +476,32 @@ CommentDatabase(char *database, char *comment)
static void static void
CommentRewrite(char *rule, char *comment) CommentRewrite(char *rule, char *comment)
{ {
Oid oid; HeapTuple tuple;
Oid reloid;
Oid ruleoid;
Oid classoid; Oid classoid;
char *relation; int32 aclcheck;
int aclcheck;
/* Find the rule's pg_rewrite tuple, get its OID and its table's OID */
tuple = SearchSysCache(RULENAME,
PointerGetDatum(rule),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "rule '%s' does not exist", rule);
reloid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
ruleoid = tuple->t_data->t_oid;
/* First, validate user */ ReleaseSysCache(tuple);
relation = RewriteGetRuleEventRel(rule); /* Check object security */
aclcheck = pg_aclcheck(relation, GetUserId(), ACL_RULE);
aclcheck = pg_class_aclcheck(reloid, GetUserId(), ACL_RULE);
if (aclcheck != ACLCHECK_OK) if (aclcheck != ACLCHECK_OK)
elog(ERROR, "you are not permitted to comment on rule '%s'", elog(ERROR, "you are not permitted to comment on rule '%s'",
rule); rule);
/* Next, find the rule's oid */
oid = GetSysCacheOid(RULENAME,
PointerGetDatum(rule),
0, 0, 0);
if (!OidIsValid(oid))
elog(ERROR, "rule '%s' does not exist", rule);
/* pg_rewrite doesn't have a hard-coded OID, so must look it up */ /* pg_rewrite doesn't have a hard-coded OID, so must look it up */
classoid = GetSysCacheOid(RELNAME, classoid = GetSysCacheOid(RELNAME,
...@@ -506,7 +511,7 @@ CommentRewrite(char *rule, char *comment) ...@@ -506,7 +511,7 @@ CommentRewrite(char *rule, char *comment)
/* Call CreateComments() to create/drop the comments */ /* Call CreateComments() to create/drop the comments */
CreateComments(oid, classoid, 0, comment); CreateComments(ruleoid, classoid, 0, comment);
} }
/*------------------------------------------------------------------ /*------------------------------------------------------------------
...@@ -525,13 +530,7 @@ CommentType(char *type, char *comment) ...@@ -525,13 +530,7 @@ CommentType(char *type, char *comment)
{ {
Oid oid; Oid oid;
/* First, validate user */ /* Find the type's oid */
if (!pg_ownercheck(GetUserId(), type, TYPENAME))
elog(ERROR, "you are not permitted to comment on type '%s'",
type);
/* Next, find the type's oid */
oid = GetSysCacheOid(TYPENAME, oid = GetSysCacheOid(TYPENAME,
PointerGetDatum(type), PointerGetDatum(type),
...@@ -539,6 +538,12 @@ CommentType(char *type, char *comment) ...@@ -539,6 +538,12 @@ CommentType(char *type, char *comment)
if (!OidIsValid(oid)) if (!OidIsValid(oid))
elog(ERROR, "type '%s' does not exist", type); elog(ERROR, "type '%s' does not exist", type);
/* Check object security */
if (!pg_type_ownercheck(oid, GetUserId()))
elog(ERROR, "you are not permitted to comment on type '%s'",
type);
/* Call CreateComments() to create/drop the comments */ /* Call CreateComments() to create/drop the comments */
CreateComments(oid, RelOid_pg_type, 0, comment); CreateComments(oid, RelOid_pg_type, 0, comment);
...@@ -576,9 +581,18 @@ CommentAggregate(char *aggregate, List *arguments, char *comment) ...@@ -576,9 +581,18 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
else else
baseoid = InvalidOid; baseoid = InvalidOid;
/* Now, attempt to find the actual tuple in pg_aggregate */
oid = GetSysCacheOid(AGGNAME,
PointerGetDatum(aggregate),
ObjectIdGetDatum(baseoid),
0, 0);
if (!OidIsValid(oid))
agg_error("CommentAggregate", aggregate, baseoid);
/* Next, validate the user's attempt to comment */ /* Next, validate the user's attempt to comment */
if (!pg_aggr_ownercheck(GetUserId(), aggregate, baseoid)) if (!pg_aggr_ownercheck(oid, GetUserId()))
{ {
if (baseoid == InvalidOid) if (baseoid == InvalidOid)
elog(ERROR, "you are not permitted to comment on aggregate '%s' for all types", elog(ERROR, "you are not permitted to comment on aggregate '%s' for all types",
...@@ -588,15 +602,6 @@ CommentAggregate(char *aggregate, List *arguments, char *comment) ...@@ -588,15 +602,6 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
aggregate, format_type_be(baseoid)); aggregate, format_type_be(baseoid));
} }
/* Now, attempt to find the actual tuple in pg_aggregate */
oid = GetSysCacheOid(AGGNAME,
PointerGetDatum(aggregate),
ObjectIdGetDatum(baseoid),
0, 0);
if (!OidIsValid(oid))
agg_error("CommentAggregate", aggregate, baseoid);
/* pg_aggregate doesn't have a hard-coded OID, so must look it up */ /* pg_aggregate doesn't have a hard-coded OID, so must look it up */
classoid = GetSysCacheOid(RELNAME, classoid = GetSysCacheOid(RELNAME,
...@@ -654,12 +659,6 @@ CommentProc(char *function, List *arguments, char *comment) ...@@ -654,12 +659,6 @@ CommentProc(char *function, List *arguments, char *comment)
} }
} }
/* Now, validate the user's ability to comment on this function */
if (!pg_func_ownercheck(GetUserId(), function, argcount, argoids))
elog(ERROR, "you are not permitted to comment on function '%s'",
function);
/* Now, find the corresponding oid for this procedure */ /* Now, find the corresponding oid for this procedure */
oid = GetSysCacheOid(PROCNAME, oid = GetSysCacheOid(PROCNAME,
...@@ -670,6 +669,12 @@ CommentProc(char *function, List *arguments, char *comment) ...@@ -670,6 +669,12 @@ CommentProc(char *function, List *arguments, char *comment)
if (!OidIsValid(oid)) if (!OidIsValid(oid))
func_error("CommentProc", function, argcount, argoids, NULL); func_error("CommentProc", function, argcount, argoids, NULL);
/* Now, validate the user's ability to comment on this function */
if (!pg_proc_ownercheck(oid, GetUserId()))
elog(ERROR, "you are not permitted to comment on function '%s'",
function);
/* Call CreateComments() to create/drop the comments */ /* Call CreateComments() to create/drop the comments */
CreateComments(oid, RelOid_pg_proc, 0, comment); CreateComments(oid, RelOid_pg_proc, 0, comment);
...@@ -757,7 +762,7 @@ CommentOperator(char *opername, List *arguments, char *comment) ...@@ -757,7 +762,7 @@ CommentOperator(char *opername, List *arguments, char *comment)
/* Valid user's ability to comment on this operator */ /* Valid user's ability to comment on this operator */
if (!pg_oper_ownercheck(GetUserId(), oid)) if (!pg_oper_ownercheck(oid, GetUserId()))
elog(ERROR, "you are not permitted to comment on operator '%s'", elog(ERROR, "you are not permitted to comment on operator '%s'",
opername); opername);
...@@ -798,13 +803,14 @@ CommentTrigger(char *trigger, char *relname, char *comment) ...@@ -798,13 +803,14 @@ CommentTrigger(char *trigger, char *relname, char *comment)
/* First, validate the user's action */ /* First, validate the user's action */
if (!pg_ownercheck(GetUserId(), relname, RELNAME)) relation = heap_openr(relname, AccessShareLock);
if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
elog(ERROR, "you are not permitted to comment on trigger '%s' %s '%s'", elog(ERROR, "you are not permitted to comment on trigger '%s' %s '%s'",
trigger, "defined for relation", relname); trigger, "defined for relation", relname);
/* Now, fetch the trigger oid from pg_trigger */ /* Fetch the trigger oid from pg_trigger */
relation = heap_openr(relname, AccessShareLock);
pg_trigger = heap_openr(TriggerRelationName, AccessShareLock); pg_trigger = heap_openr(TriggerRelationName, AccessShareLock);
ScanKeyEntryInitialize(&entry[0], 0x0, Anum_pg_trigger_tgrelid, ScanKeyEntryInitialize(&entry[0], 0x0, Anum_pg_trigger_tgrelid,
F_OIDEQ, F_OIDEQ,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.150 2002/03/06 06:09:30 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.151 2002/03/21 23:27:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -266,16 +266,20 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe, ...@@ -266,16 +266,20 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
FILE *fp; FILE *fp;
Relation rel; Relation rel;
const AclMode required_access = (from ? ACL_INSERT : ACL_SELECT); const AclMode required_access = (from ? ACL_INSERT : ACL_SELECT);
int result; int32 aclresult;
/* /*
* Open and lock the relation, using the appropriate lock type. * Open and lock the relation, using the appropriate lock type.
*/ */
rel = heap_openr(relname, (from ? RowExclusiveLock : AccessShareLock)); rel = heap_openr(relname, (from ? RowExclusiveLock : AccessShareLock));
result = pg_aclcheck(relname, GetUserId(), required_access); /* Check permissions. */
if (result != ACLCHECK_OK) aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
elog(ERROR, "%s: %s", relname, aclcheck_error_strings[result]); required_access);
if (aclresult != ACLCHECK_OK)
elog(ERROR, "%s: %s",
RelationGetRelationName(rel),
aclcheck_error_strings[aclresult]);
if (!pipe && !superuser()) if (!pipe && !superuser())
elog(ERROR, "You must have Postgres superuser privilege to do a COPY " elog(ERROR, "You must have Postgres superuser privilege to do a COPY "
"directly to or from a file. Anyone can COPY to stdout or " "directly to or from a file. Anyone can COPY to stdout or "
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.89 2002/03/21 16:00:31 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.90 2002/03/21 23:27:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -247,13 +247,6 @@ TruncateRelation(const char *relname) ...@@ -247,13 +247,6 @@ TruncateRelation(const char *relname)
AssertArg(relname); AssertArg(relname);
if (!allowSystemTableMods && IsSystemRelationName(relname))
elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table",
relname);
if (!pg_ownercheck(GetUserId(), relname, RELNAME))
elog(ERROR, "you do not own relation \"%s\"", relname);
/* Grab exclusive lock in preparation for truncate */ /* Grab exclusive lock in preparation for truncate */
rel = heap_openr(relname, AccessExclusiveLock); rel = heap_openr(relname, AccessExclusiveLock);
...@@ -265,6 +258,13 @@ TruncateRelation(const char *relname) ...@@ -265,6 +258,13 @@ TruncateRelation(const char *relname)
elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a view", elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a view",
relname); relname);
if (!allowSystemTableMods && IsSystemRelationName(relname))
elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table",
relname);
if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
elog(ERROR, "you do not own relation \"%s\"", relname);
/* Keep the lock until transaction commit */ /* Keep the lock until transaction commit */
heap_close(rel, NoLock); heap_close(rel, NoLock);
...@@ -458,7 +458,7 @@ MergeAttributes(List *schema, List *supers, bool istemp, ...@@ -458,7 +458,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
* We should have an UNDER permission flag for this, but for now, * We should have an UNDER permission flag for this, but for now,
* demand that creator of a child table own the parent. * demand that creator of a child table own the parent.
*/ */
if (!pg_ownercheck(GetUserId(), name, RELNAME)) if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
elog(ERROR, "you do not own table \"%s\"", name); elog(ERROR, "you do not own table \"%s\"", name);
parentOids = lappendi(parentOids, relation->rd_id); parentOids = lappendi(parentOids, relation->rd_id);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.70 2002/03/20 19:43:49 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.71 2002/03/21 23:27:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -84,7 +84,7 @@ RemoveOperator(char *operatorName, /* operator name */ ...@@ -84,7 +84,7 @@ RemoveOperator(char *operatorName, /* operator name */
if (HeapTupleIsValid(tup)) if (HeapTupleIsValid(tup))
{ {
if (!pg_oper_ownercheck(GetUserId(), tup->t_data->t_oid)) if (!pg_oper_ownercheck(tup->t_data->t_oid, GetUserId()))
elog(ERROR, "RemoveOperator: operator '%s': permission denied", elog(ERROR, "RemoveOperator: operator '%s': permission denied",
operatorName); operatorName);
...@@ -92,7 +92,6 @@ RemoveOperator(char *operatorName, /* operator name */ ...@@ -92,7 +92,6 @@ RemoveOperator(char *operatorName, /* operator name */
DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation)); DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
simple_heap_delete(relation, &tup->t_self); simple_heap_delete(relation, &tup->t_self);
} }
else else
{ {
...@@ -242,10 +241,6 @@ RemoveType(char *typeName) /* type name to be removed */ ...@@ -242,10 +241,6 @@ RemoveType(char *typeName) /* type name to be removed */
HeapTuple tup; HeapTuple tup;
char *shadow_type; char *shadow_type;
if (!pg_ownercheck(GetUserId(), typeName, TYPENAME))
elog(ERROR, "RemoveType: type '%s': permission denied",
typeName);
relation = heap_openr(TypeRelationName, RowExclusiveLock); relation = heap_openr(TypeRelationName, RowExclusiveLock);
tup = SearchSysCache(TYPENAME, tup = SearchSysCache(TYPENAME,
...@@ -254,6 +249,10 @@ RemoveType(char *typeName) /* type name to be removed */ ...@@ -254,6 +249,10 @@ RemoveType(char *typeName) /* type name to be removed */
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
elog(ERROR, "RemoveType: type '%s' does not exist", typeName); elog(ERROR, "RemoveType: type '%s' does not exist", typeName);
if (!pg_type_ownercheck(tup->t_data->t_oid, GetUserId()))
elog(ERROR, "RemoveType: type '%s': permission denied",
typeName);
/* Delete any comments associated with this type */ /* Delete any comments associated with this type */
DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation)); DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
...@@ -288,10 +287,9 @@ RemoveDomain(char *domainName, int behavior) ...@@ -288,10 +287,9 @@ RemoveDomain(char *domainName, int behavior)
HeapTuple tup; HeapTuple tup;
char typtype; char typtype;
/* Domains are stored as types. Check for permissions on the type */ /* CASCADE unsupported */
if (!pg_ownercheck(GetUserId(), domainName, TYPENAME)) if (behavior == CASCADE)
elog(ERROR, "RemoveDomain: type '%s': permission denied", elog(ERROR, "DROP DOMAIN does not support the CASCADE keyword");
domainName);
relation = heap_openr(TypeRelationName, RowExclusiveLock); relation = heap_openr(TypeRelationName, RowExclusiveLock);
...@@ -301,17 +299,16 @@ RemoveDomain(char *domainName, int behavior) ...@@ -301,17 +299,16 @@ RemoveDomain(char *domainName, int behavior)
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
elog(ERROR, "RemoveType: type '%s' does not exist", domainName); elog(ERROR, "RemoveType: type '%s' does not exist", domainName);
if (!pg_type_ownercheck(tup->t_data->t_oid, GetUserId()))
elog(ERROR, "RemoveDomain: type '%s': permission denied",
domainName);
/* Check that this is actually a domain */ /* Check that this is actually a domain */
typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype; typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype;
if (typtype != 'd') if (typtype != 'd')
elog(ERROR, "%s is not a domain", domainName); elog(ERROR, "%s is not a domain", domainName);
/* CASCADE unsupported */
if (behavior == CASCADE) {
elog(ERROR, "DROP DOMAIN does not support the CASCADE keyword");
}
/* Delete any comments associated with this type */ /* Delete any comments associated with this type */
DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation)); DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
...@@ -364,12 +361,6 @@ RemoveFunction(char *functionName, /* function name to be removed */ ...@@ -364,12 +361,6 @@ RemoveFunction(char *functionName, /* function name to be removed */
} }
} }
if (!pg_func_ownercheck(GetUserId(), functionName, nargs, argList))
{
elog(ERROR, "RemoveFunction: function '%s': permission denied",
functionName);
}
relation = heap_openr(ProcedureRelationName, RowExclusiveLock); relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
tup = SearchSysCache(PROCNAME, tup = SearchSysCache(PROCNAME,
...@@ -381,6 +372,10 @@ RemoveFunction(char *functionName, /* function name to be removed */ ...@@ -381,6 +372,10 @@ RemoveFunction(char *functionName, /* function name to be removed */
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
func_error("RemoveFunction", functionName, nargs, argList, NULL); func_error("RemoveFunction", functionName, nargs, argList, NULL);
if (!pg_proc_ownercheck(tup->t_data->t_oid, GetUserId()))
elog(ERROR, "RemoveFunction: function '%s': permission denied",
functionName);
if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId) if (((Form_pg_proc) GETSTRUCT(tup))->prolang == INTERNALlanguageId)
{ {
/* "Helpful" WARNING when removing a builtin function ... */ /* "Helpful" WARNING when removing a builtin function ... */
...@@ -423,16 +418,6 @@ RemoveAggregate(char *aggName, char *aggType) ...@@ -423,16 +418,6 @@ RemoveAggregate(char *aggName, char *aggType)
else else
basetypeID = InvalidOid; basetypeID = InvalidOid;
if (!pg_aggr_ownercheck(GetUserId(), aggName, basetypeID))
{
if (basetypeID == InvalidOid)
elog(ERROR, "RemoveAggregate: aggregate '%s' for all types: permission denied",
aggName);
else
elog(ERROR, "RemoveAggregate: aggregate '%s' for type %s: permission denied",
aggName, format_type_be(basetypeID));
}
relation = heap_openr(AggregateRelationName, RowExclusiveLock); relation = heap_openr(AggregateRelationName, RowExclusiveLock);
tup = SearchSysCache(AGGNAME, tup = SearchSysCache(AGGNAME,
...@@ -443,6 +428,16 @@ RemoveAggregate(char *aggName, char *aggType) ...@@ -443,6 +428,16 @@ RemoveAggregate(char *aggName, char *aggType)
if (!HeapTupleIsValid(tup)) if (!HeapTupleIsValid(tup))
agg_error("RemoveAggregate", aggName, basetypeID); agg_error("RemoveAggregate", aggName, basetypeID);
if (!pg_aggr_ownercheck(tup->t_data->t_oid, GetUserId()))
{
if (basetypeID == InvalidOid)
elog(ERROR, "RemoveAggregate: aggregate '%s' for all types: permission denied",
aggName);
else
elog(ERROR, "RemoveAggregate: aggregate '%s' for type %s: permission denied",
aggName, format_type_be(basetypeID));
}
/* Remove any comments related to this aggregate */ /* Remove any comments related to this aggregate */
DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation)); DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.63 2001/11/12 01:34:50 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.64 2002/03/21 23:27:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -81,6 +81,13 @@ renameatt(char *relname, ...@@ -81,6 +81,13 @@ renameatt(char *relname,
List *indexoidlist; List *indexoidlist;
List *indexoidscan; List *indexoidscan;
/*
* Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction.
*/
targetrelation = heap_openr(relname, AccessExclusiveLock);
relid = RelationGetRelid(targetrelation);
/* /*
* permissions checking. this would normally be done in utility.c, * permissions checking. this would normally be done in utility.c,
* but this particular routine is recursive. * but this particular routine is recursive.
...@@ -90,18 +97,10 @@ renameatt(char *relname, ...@@ -90,18 +97,10 @@ renameatt(char *relname,
if (!allowSystemTableMods && IsSystemRelationName(relname)) if (!allowSystemTableMods && IsSystemRelationName(relname))
elog(ERROR, "renameatt: class \"%s\" is a system catalog", elog(ERROR, "renameatt: class \"%s\" is a system catalog",
relname); relname);
if (!IsBootstrapProcessingMode() && if (!pg_class_ownercheck(relid, GetUserId()))
!pg_ownercheck(GetUserId(), relname, RELNAME))
elog(ERROR, "renameatt: you do not own class \"%s\"", elog(ERROR, "renameatt: you do not own class \"%s\"",
relname); relname);
/*
* Grab an exclusive lock on the target table, which we will NOT
* release until end of transaction.
*/
targetrelation = heap_openr(relname, AccessExclusiveLock);
relid = RelationGetRelid(targetrelation);
/* /*
* if the 'recurse' flag is set then we are supposed to rename this * if the 'recurse' flag is set then we are supposed to rename this
* attribute in all classes that inherit from 'relname' (as well as in * attribute in all classes that inherit from 'relname' (as well as in
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.72 2002/03/21 16:00:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.73 2002/03/21 23:27:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -299,13 +299,13 @@ nextval(PG_FUNCTION_ARGS) ...@@ -299,13 +299,13 @@ nextval(PG_FUNCTION_ARGS)
rescnt = 0; rescnt = 0;
bool logit = false; bool logit = false;
if (pg_aclcheck(seqname, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)
elog(ERROR, "%s.nextval: you don't have permissions to set sequence %s",
seqname, seqname);
/* open and AccessShareLock sequence */ /* open and AccessShareLock sequence */
elm = init_sequence("nextval", seqname); elm = init_sequence("nextval", seqname);
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)
elog(ERROR, "%s.nextval: you don't have permissions to set sequence %s",
seqname, seqname);
pfree(seqname); pfree(seqname);
if (elm->last != elm->cached) /* some numbers were cached */ if (elm->last != elm->cached) /* some numbers were cached */
...@@ -466,13 +466,13 @@ currval(PG_FUNCTION_ARGS) ...@@ -466,13 +466,13 @@ currval(PG_FUNCTION_ARGS)
SeqTable elm; SeqTable elm;
int64 result; int64 result;
if (pg_aclcheck(seqname, GetUserId(), ACL_SELECT) != ACLCHECK_OK)
elog(ERROR, "%s.currval: you don't have permissions to read sequence %s",
seqname, seqname);
/* open and AccessShareLock sequence */ /* open and AccessShareLock sequence */
elm = init_sequence("currval", seqname); elm = init_sequence("currval", seqname);
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK)
elog(ERROR, "%s.currval: you don't have permissions to read sequence %s",
seqname, seqname);
if (elm->increment == 0) /* nextval/read_info were not called */ if (elm->increment == 0) /* nextval/read_info were not called */
elog(ERROR, "%s.currval is not yet defined in this session", elog(ERROR, "%s.currval is not yet defined in this session",
seqname); seqname);
...@@ -504,14 +504,15 @@ do_setval(char *seqname, int64 next, bool iscalled) ...@@ -504,14 +504,15 @@ do_setval(char *seqname, int64 next, bool iscalled)
Buffer buf; Buffer buf;
Form_pg_sequence seq; Form_pg_sequence seq;
if (pg_aclcheck(seqname, GetUserId(), ACL_UPDATE) != ACLCHECK_OK) /* open and AccessShareLock sequence */
elm = init_sequence("setval", seqname);
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)
elog(ERROR, "%s.setval: you don't have permissions to set sequence %s", elog(ERROR, "%s.setval: you don't have permissions to set sequence %s",
seqname, seqname); seqname, seqname);
/* open and AccessShareLock sequence */ /* lock page' buffer and read tuple */
elm = init_sequence("setval", seqname); seq = read_info("setval", elm, &buf);
seq = read_info("setval", elm, &buf); /* lock page' buffer and
* read tuple */
if ((next < seq->min_value) || (next > seq->max_value)) if ((next < seq->min_value) || (next > seq->max_value))
elog(ERROR, "%s.setval: value " INT64_FORMAT " is out of bounds (" INT64_FORMAT "," INT64_FORMAT ")", elog(ERROR, "%s.setval: value " INT64_FORMAT " is out of bounds (" INT64_FORMAT "," INT64_FORMAT ")",
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.106 2002/03/21 16:00:34 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.107 2002/03/21 23:27:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -71,12 +71,18 @@ CreateTrigger(CreateTrigStmt *stmt) ...@@ -71,12 +71,18 @@ CreateTrigger(CreateTrigStmt *stmt)
char *constrname = ""; char *constrname = "";
Oid constrrelid = InvalidOid; Oid constrrelid = InvalidOid;
rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "CreateTrigger: relation \"%s\" is not a table",
stmt->relation->relname);
if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->relname)) if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->relname))
elog(ERROR, "CreateTrigger: can't create trigger for system relation %s", elog(ERROR, "CreateTrigger: can't create trigger for system relation %s",
stmt->relation->relname); stmt->relation->relname);
if (pg_aclcheck(stmt->relation->relname, GetUserId(), if (pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
stmt->isconstraint ? ACL_REFERENCES : ACL_TRIGGER) stmt->isconstraint ? ACL_REFERENCES : ACL_TRIGGER)
!= ACLCHECK_OK) != ACLCHECK_OK)
elog(ERROR, "permission denied"); elog(ERROR, "permission denied");
...@@ -98,18 +104,14 @@ CreateTrigger(CreateTrigStmt *stmt) ...@@ -98,18 +104,14 @@ CreateTrigger(CreateTrigStmt *stmt)
* NoLock is probably sufficient here, since we're only * NoLock is probably sufficient here, since we're only
* interested in getting the relation's OID... * interested in getting the relation's OID...
*/ */
rel = heap_openr(stmt->constrrel->relname, NoLock); Relation conrel;
constrrelid = rel->rd_id;
heap_close(rel, NoLock); conrel = heap_openr(stmt->constrrel->relname, NoLock);
constrrelid = conrel->rd_id;
heap_close(conrel, NoLock);
} }
} }
rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "CreateTrigger: relation \"%s\" is not a table",
stmt->relation->relname);
TRIGGER_CLEAR_TYPE(tgtype); TRIGGER_CLEAR_TYPE(tgtype);
if (stmt->before) if (stmt->before)
TRIGGER_SETT_BEFORE(tgtype); TRIGGER_SETT_BEFORE(tgtype);
...@@ -321,20 +323,20 @@ DropTrigger(DropTrigStmt *stmt) ...@@ -321,20 +323,20 @@ DropTrigger(DropTrigStmt *stmt)
int found = 0; int found = 0;
int tgfound = 0; int tgfound = 0;
rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "DropTrigger: relation \"%s\" is not a table",
stmt->relation->relname);
if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->relname)) if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->relname))
elog(ERROR, "DropTrigger: can't drop trigger for system relation %s", elog(ERROR, "DropTrigger: can't drop trigger for system relation %s",
stmt->relation->relname); stmt->relation->relname);
if (!pg_ownercheck(GetUserId(), stmt->relation->relname, RELNAME)) if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
elog(ERROR, "%s: %s", stmt->relation->relname, elog(ERROR, "%s: %s", stmt->relation->relname,
aclcheck_error_strings[ACLCHECK_NOT_OWNER]); aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
if (rel->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "DropTrigger: relation \"%s\" is not a table",
stmt->relation->relname);
/* /*
* Search pg_trigger, delete target trigger, count remaining triggers * Search pg_trigger, delete target trigger, count remaining triggers
* for relation. Note this is OK only because we have * for relation. Note this is OK only because we have
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.218 2002/03/21 16:00:35 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.219 2002/03/21 23:27:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -714,15 +714,14 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt) ...@@ -714,15 +714,14 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt)
* *
* We allow the user to vacuum a table if he is superuser, the table * We allow the user to vacuum a table if he is superuser, the table
* owner, or the database owner (but in the latter case, only if it's * owner, or the database owner (but in the latter case, only if it's
* not a shared relation). pg_ownercheck includes the superuser case. * not a shared relation). pg_class_ownercheck includes the superuser case.
* *
* Note we choose to treat permissions failure as a WARNING and keep * Note we choose to treat permissions failure as a WARNING and keep
* trying to vacuum the rest of the DB --- is this appropriate? * trying to vacuum the rest of the DB --- is this appropriate?
*/ */
onerel = heap_open(relid, lmode); onerel = heap_open(relid, lmode);
if (!(pg_ownercheck(GetUserId(), RelationGetRelationName(onerel), if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) ||
RELNAME) ||
(is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared))) (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared)))
{ {
elog(WARNING, "Skipping \"%s\" --- only table or database owner can VACUUM it", elog(WARNING, "Skipping \"%s\" --- only table or database owner can VACUUM it",
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.153 2002/03/21 16:00:37 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.154 2002/03/21 23:27:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "optimizer/var.h" #include "optimizer/var.h"
#include "parser/parsetree.h" #include "parser/parsetree.h"
#include "utils/acl.h" #include "utils/acl.h"
#include "utils/lsyscache.h"
/* decls for local routines only used within this module */ /* decls for local routines only used within this module */
...@@ -355,7 +356,7 @@ ExecCheckRTPerms(List *rangeTable, CmdType operation) ...@@ -355,7 +356,7 @@ ExecCheckRTPerms(List *rangeTable, CmdType operation)
static void static void
ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation) ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
{ {
char *relName; Oid relOid;
Oid userid; Oid userid;
int32 aclcheck_result; int32 aclcheck_result;
...@@ -363,10 +364,10 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation) ...@@ -363,10 +364,10 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
* If it's a subquery RTE, ignore it --- it will be checked when * If it's a subquery RTE, ignore it --- it will be checked when
* ExecCheckPlanPerms finds the SubqueryScan node for it. * ExecCheckPlanPerms finds the SubqueryScan node for it.
*/ */
if (rte->subquery) if (rte->rtekind != RTE_RELATION)
return; return;
relName = rte->relname; relOid = rte->relid;
/* /*
* userid to check as: current user unless we have a setuid * userid to check as: current user unless we have a setuid
...@@ -379,14 +380,15 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation) ...@@ -379,14 +380,15 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
*/ */
userid = rte->checkAsUser ? rte->checkAsUser : GetUserId(); userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
#define CHECK(MODE) pg_aclcheck(relName, userid, MODE) #define CHECK(MODE) pg_class_aclcheck(relOid, userid, MODE)
if (rte->checkForRead) if (rte->checkForRead)
{ {
aclcheck_result = CHECK(ACL_SELECT); aclcheck_result = CHECK(ACL_SELECT);
if (aclcheck_result != ACLCHECK_OK) if (aclcheck_result != ACLCHECK_OK)
elog(ERROR, "%s: %s", elog(ERROR, "%s: %s",
relName, aclcheck_error_strings[aclcheck_result]); get_rel_name(relOid),
aclcheck_error_strings[aclcheck_result]);
} }
if (rte->checkForWrite) if (rte->checkForWrite)
...@@ -416,7 +418,8 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation) ...@@ -416,7 +418,8 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
} }
if (aclcheck_result != ACLCHECK_OK) if (aclcheck_result != ACLCHECK_OK)
elog(ERROR, "%s: %s", elog(ERROR, "%s: %s",
relName, aclcheck_error_strings[aclcheck_result]); get_rel_name(relOid),
aclcheck_error_strings[aclcheck_result]);
} }
} }
......
...@@ -8,11 +8,10 @@ ...@@ -8,11 +8,10 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.64 2002/03/21 16:01:16 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.65 2002/03/21 23:27:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
#include "access/heapam.h" #include "access/heapam.h"
...@@ -27,6 +26,7 @@ ...@@ -27,6 +26,7 @@
#include "rewrite/rewriteManip.h" #include "rewrite/rewriteManip.h"
#include "rewrite/rewriteSupport.h" #include "rewrite/rewriteSupport.h"
#include "storage/smgr.h" #include "storage/smgr.h"
#include "utils/acl.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/syscache.h" #include "utils/syscache.h"
...@@ -127,6 +127,7 @@ DefineQueryRewrite(RuleStmt *stmt) ...@@ -127,6 +127,7 @@ DefineQueryRewrite(RuleStmt *stmt)
*event_qualP; *event_qualP;
List *l; List *l;
Query *query; Query *query;
int32 aclcheck_result;
bool RelisBecomingView = false; bool RelisBecomingView = false;
/* /*
...@@ -140,6 +141,15 @@ DefineQueryRewrite(RuleStmt *stmt) ...@@ -140,6 +141,15 @@ DefineQueryRewrite(RuleStmt *stmt)
event_relation = heap_openr(event_obj->relname, AccessExclusiveLock); event_relation = heap_openr(event_obj->relname, AccessExclusiveLock);
ev_relid = RelationGetRelid(event_relation); ev_relid = RelationGetRelid(event_relation);
/*
* Check user has permission to apply rules to this relation.
*/
aclcheck_result = pg_class_aclcheck(ev_relid, GetUserId(), ACL_RULE);
if (aclcheck_result != ACLCHECK_OK)
elog(ERROR, "%s: %s",
RelationGetRelationName(event_relation),
aclcheck_error_strings[aclcheck_result]);
/* /*
* No rule actions that modify OLD or NEW * No rule actions that modify OLD or NEW
*/ */
......
...@@ -8,12 +8,10 @@ ...@@ -8,12 +8,10 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.45 2001/08/10 18:57:37 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.46 2002/03/21 23:27:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
#include "utils/builtins.h" #include "utils/builtins.h"
...@@ -21,41 +19,13 @@ ...@@ -21,41 +19,13 @@
#include "catalog/catname.h" #include "catalog/catname.h"
#include "catalog/pg_rewrite.h" #include "catalog/pg_rewrite.h"
#include "commands/comment.h" #include "commands/comment.h"
#include "miscadmin.h"
#include "rewrite/rewriteRemove.h" #include "rewrite/rewriteRemove.h"
#include "rewrite/rewriteSupport.h" #include "rewrite/rewriteSupport.h"
#include "utils/acl.h"
#include "utils/fmgroids.h" #include "utils/fmgroids.h"
#include "utils/syscache.h" #include "utils/syscache.h"
/*-----------------------------------------------------------------------
* RewriteGetRuleEventRel
*-----------------------------------------------------------------------
*/
char *
RewriteGetRuleEventRel(char *rulename)
{
HeapTuple htup;
Oid eventrel;
char *result;
htup = SearchSysCache(RULENAME,
PointerGetDatum(rulename),
0, 0, 0);
if (!HeapTupleIsValid(htup))
elog(ERROR, "Rule or view \"%s\" not found",
((strncmp(rulename, "_RET", 4) == 0) ? (rulename + 4) : rulename));
eventrel = ((Form_pg_rewrite) GETSTRUCT(htup))->ev_class;
ReleaseSysCache(htup);
htup = SearchSysCache(RELOID,
PointerGetDatum(eventrel),
0, 0, 0);
if (!HeapTupleIsValid(htup))
elog(ERROR, "Relation %u not found", eventrel);
result = pstrdup(NameStr(((Form_pg_class) GETSTRUCT(htup))->relname));
ReleaseSysCache(htup);
return result;
}
/* /*
* RemoveRewriteRule * RemoveRewriteRule
...@@ -71,6 +41,7 @@ RemoveRewriteRule(char *ruleName) ...@@ -71,6 +41,7 @@ RemoveRewriteRule(char *ruleName)
Oid ruleId; Oid ruleId;
Oid eventRelationOid; Oid eventRelationOid;
bool hasMoreRules; bool hasMoreRules;
int32 aclcheck_result;
/* /*
* Open the pg_rewrite relation. * Open the pg_rewrite relation.
...@@ -88,10 +59,7 @@ RemoveRewriteRule(char *ruleName) ...@@ -88,10 +59,7 @@ RemoveRewriteRule(char *ruleName)
* complain if no rule with such name existed * complain if no rule with such name existed
*/ */
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
{
heap_close(RewriteRelation, RowExclusiveLock);
elog(ERROR, "Rule \"%s\" not found", ruleName); elog(ERROR, "Rule \"%s\" not found", ruleName);
}
/* /*
* Save the OID of the rule (i.e. the tuple's OID) and the event * Save the OID of the rule (i.e. the tuple's OID) and the event
...@@ -108,6 +76,16 @@ RemoveRewriteRule(char *ruleName) ...@@ -108,6 +76,16 @@ RemoveRewriteRule(char *ruleName)
*/ */
event_relation = heap_open(eventRelationOid, AccessExclusiveLock); event_relation = heap_open(eventRelationOid, AccessExclusiveLock);
/*
* Verify user has appropriate permissions.
*/
aclcheck_result = pg_class_aclcheck(eventRelationOid, GetUserId(),
ACL_RULE);
if (aclcheck_result != ACLCHECK_OK)
elog(ERROR, "%s: %s",
RelationGetRelationName(event_relation),
aclcheck_error_strings[aclcheck_result]);
/* do not allow the removal of a view's SELECT rule */ /* do not allow the removal of a view's SELECT rule */
if (event_relation->rd_rel->relkind == RELKIND_VIEW && if (event_relation->rd_rel->relkind == RELKIND_VIEW &&
((Form_pg_rewrite) GETSTRUCT(tuple))->ev_type == '1') ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_type == '1')
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.136 2002/03/21 16:01:30 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.137 2002/03/21 23:27:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -116,7 +116,7 @@ CheckDropPermissions(char *name, char rightkind) ...@@ -116,7 +116,7 @@ CheckDropPermissions(char *name, char rightkind)
if (classform->relkind != rightkind) if (classform->relkind != rightkind)
DropErrorMsg(name, classform->relkind, rightkind); DropErrorMsg(name, classform->relkind, rightkind);
if (!pg_ownercheck(GetUserId(), name, RELNAME)) if (!pg_class_ownercheck(tuple->t_data->t_oid, GetUserId()))
elog(ERROR, "you do not own %s \"%s\"", elog(ERROR, "you do not own %s \"%s\"",
rentry->name, name); rentry->name, name);
...@@ -128,6 +128,31 @@ CheckDropPermissions(char *name, char rightkind) ...@@ -128,6 +128,31 @@ CheckDropPermissions(char *name, char rightkind)
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
} }
static void
CheckOwnership(char *relname, bool noCatalogs)
{
HeapTuple tuple;
tuple = SearchSysCache(RELNAME,
PointerGetDatum(relname),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "Relation \"%s\" does not exist", relname);
if (!pg_class_ownercheck(tuple->t_data->t_oid, GetUserId()))
elog(ERROR, "%s: %s", relname,
aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
if (noCatalogs)
{
if (!allowSystemTableMods && IsSystemRelationName(relname))
elog(ERROR, "relation \"%s\" is a system catalog",
relname);
}
ReleaseSysCache(tuple);
}
/* /*
* ProcessUtility * ProcessUtility
...@@ -149,7 +174,6 @@ ProcessUtility(Node *parsetree, ...@@ -149,7 +174,6 @@ ProcessUtility(Node *parsetree,
char *completionTag) char *completionTag)
{ {
char *relname; char *relname;
char *relationName;
if (completionTag) if (completionTag)
completionTag[0] = '\0'; completionTag[0] = '\0';
...@@ -271,17 +295,8 @@ ProcessUtility(Node *parsetree, ...@@ -271,17 +295,8 @@ ProcessUtility(Node *parsetree,
break; break;
case DROP_RULE: case DROP_RULE:
{ /* RemoveRewriteRule checks permissions */
char *rulename = relname; RemoveRewriteRule(relname);
int aclcheck_result;
relationName = RewriteGetRuleEventRel(rulename);
aclcheck_result = pg_aclcheck(relationName, GetUserId(), ACL_RULE);
if (aclcheck_result != ACLCHECK_OK)
elog(ERROR, "%s: %s", relationName,
aclcheck_error_strings[aclcheck_result]);
RemoveRewriteRule(rulename);
}
break; break;
case DROP_TYPE: case DROP_TYPE:
...@@ -355,11 +370,7 @@ ProcessUtility(Node *parsetree, ...@@ -355,11 +370,7 @@ ProcessUtility(Node *parsetree,
RenameStmt *stmt = (RenameStmt *) parsetree; RenameStmt *stmt = (RenameStmt *) parsetree;
relname = stmt->relation->relname; relname = stmt->relation->relname;
if (!allowSystemTableMods && IsSystemRelationName(relname)) CheckOwnership(relname, true);
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relname);
if (!pg_ownercheck(GetUserId(), relname, RELNAME))
elog(ERROR, "permission denied");
/* ---------------- /* ----------------
* XXX using len == 3 to tell the difference * XXX using len == 3 to tell the difference
...@@ -509,11 +520,7 @@ ProcessUtility(Node *parsetree, ...@@ -509,11 +520,7 @@ ProcessUtility(Node *parsetree,
IndexStmt *stmt = (IndexStmt *) parsetree; IndexStmt *stmt = (IndexStmt *) parsetree;
relname = stmt->relation->relname; relname = stmt->relation->relname;
if (!allowSystemTableMods && IsSystemRelationName(relname)) CheckOwnership(relname, true);
elog(ERROR, "CREATE INDEX: relation \"%s\" is a system catalog",
relname);
if (!pg_ownercheck(GetUserId(), relname, RELNAME))
elog(ERROR, "permission denied");
DefineIndex(stmt->relation->relname, /* relation */ DefineIndex(stmt->relation->relname, /* relation */
stmt->idxname, /* index name */ stmt->idxname, /* index name */
...@@ -527,17 +534,7 @@ ProcessUtility(Node *parsetree, ...@@ -527,17 +534,7 @@ ProcessUtility(Node *parsetree,
break; break;
case T_RuleStmt: /* CREATE RULE */ case T_RuleStmt: /* CREATE RULE */
{ DefineQueryRewrite((RuleStmt *) parsetree);
RuleStmt *stmt = (RuleStmt *) parsetree;
int aclcheck_result;
relname = stmt->relation->relname;
aclcheck_result = pg_aclcheck(relname, GetUserId(), ACL_RULE);
if (aclcheck_result != ACLCHECK_OK)
elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]);
DefineQueryRewrite(stmt);
}
break; break;
case T_CreateSeqStmt: case T_CreateSeqStmt:
...@@ -646,11 +643,7 @@ ProcessUtility(Node *parsetree, ...@@ -646,11 +643,7 @@ ProcessUtility(Node *parsetree,
ClusterStmt *stmt = (ClusterStmt *) parsetree; ClusterStmt *stmt = (ClusterStmt *) parsetree;
relname = stmt->relation->relname; relname = stmt->relation->relname;
if (IsSystemRelationName(relname)) CheckOwnership(relname, true);
elog(ERROR, "CLUSTER: relation \"%s\" is a system catalog",
relname);
if (!pg_ownercheck(GetUserId(), relname, RELNAME))
elog(ERROR, "permission denied");
cluster(relname, stmt->indexname); cluster(relname, stmt->indexname);
} }
...@@ -790,14 +783,12 @@ ProcessUtility(Node *parsetree, ...@@ -790,14 +783,12 @@ ProcessUtility(Node *parsetree,
elog(ERROR, "\"%s\" is a system index. call REINDEX under standalone postgres with -P -O options", elog(ERROR, "\"%s\" is a system index. call REINDEX under standalone postgres with -P -O options",
relname); relname);
} }
if (!pg_ownercheck(GetUserId(), relname, RELNAME)) CheckOwnership(relname, false);
elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
ReindexIndex(relname, stmt->force); ReindexIndex(relname, stmt->force);
break; break;
case TABLE: case TABLE:
relname = (char *) stmt->relation->relname; relname = (char *) stmt->relation->relname;
if (!pg_ownercheck(GetUserId(), relname, RELNAME)) CheckOwnership(relname, false);
elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
ReindexTable(relname, stmt->force); ReindexTable(relname, stmt->force);
break; break;
case DATABASE: case DATABASE:
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.68 2002/03/02 21:39:32 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.69 2002/03/21 23:27:24 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -817,30 +817,21 @@ has_table_privilege_id(PG_FUNCTION_ARGS) ...@@ -817,30 +817,21 @@ has_table_privilege_id(PG_FUNCTION_ARGS)
{ {
Oid reloid = PG_GETARG_OID(0); Oid reloid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1); text *priv_type_text = PG_GETARG_TEXT_P(1);
char *relname;
int32 usesysid; int32 usesysid;
AclMode mode; AclMode mode;
int32 result; int32 result;
usesysid = GetUserId(); 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 * Convert priv_type_text to an AclMode
*/ */
mode = convert_priv_string(priv_type_text); mode = convert_priv_string(priv_type_text);
/* /*
* Finally, check for the privilege * Check for the privilege
*/ */
result = pg_aclcheck(relname, usesysid, mode); result = pg_class_aclcheck(reloid, usesysid, mode);
if (result == ACLCHECK_OK) if (result == ACLCHECK_OK)
PG_RETURN_BOOL(true); PG_RETURN_BOOL(true);
...@@ -891,27 +882,18 @@ has_table_privilege_id_id(PG_FUNCTION_ARGS) ...@@ -891,27 +882,18 @@ has_table_privilege_id_id(PG_FUNCTION_ARGS)
int32 usesysid = PG_GETARG_INT32(0); int32 usesysid = PG_GETARG_INT32(0);
Oid reloid = PG_GETARG_OID(1); Oid reloid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2); text *priv_type_text = PG_GETARG_TEXT_P(2);
char *relname;
AclMode mode; AclMode mode;
int32 result; 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 * Convert priv_type_text to an AclMode
*/ */
mode = convert_priv_string(priv_type_text); mode = convert_priv_string(priv_type_text);
/* /*
* Finally, check for the privilege * Check for the privilege
*/ */
result = pg_aclcheck(relname, usesysid, mode); result = pg_class_aclcheck(reloid, usesysid, mode);
if (result == ACLCHECK_OK) if (result == ACLCHECK_OK)
PG_RETURN_BOOL(true); PG_RETURN_BOOL(true);
...@@ -1050,22 +1032,19 @@ static bool ...@@ -1050,22 +1032,19 @@ static bool
has_table_privilege_id_cname(int32 usesysid, char *relname, has_table_privilege_id_cname(int32 usesysid, char *relname,
text *priv_type_text) text *priv_type_text)
{ {
HeapTuple tuple; Oid reloid;
AclMode mode; AclMode mode;
int32 result; int32 result;
/* /*
* Check relname is valid. This is needed to deal with the case when * Convert relname to rel OID.
* usename is a superuser in which case pg_aclcheck simply returns
* ACLCHECK_OK without validating relname
*/ */
tuple = SearchSysCache(RELNAME, reloid = GetSysCacheOid(RELNAME,
PointerGetDatum(relname), PointerGetDatum(relname),
0, 0, 0); 0, 0, 0);
if (!HeapTupleIsValid(tuple)) if (!OidIsValid(reloid))
elog(ERROR, "has_table_privilege: relation \"%s\" does not exist", elog(ERROR, "has_table_privilege: relation \"%s\" does not exist",
relname); relname);
ReleaseSysCache(tuple);
/* /*
* Convert priv_type_text to an AclMode * Convert priv_type_text to an AclMode
...@@ -1075,7 +1054,7 @@ has_table_privilege_id_cname(int32 usesysid, char *relname, ...@@ -1075,7 +1054,7 @@ has_table_privilege_id_cname(int32 usesysid, char *relname,
/* /*
* Finally, check for the privilege * Finally, check for the privilege
*/ */
result = pg_aclcheck(relname, usesysid, mode); result = pg_class_aclcheck(reloid, usesysid, mode);
if (result == ACLCHECK_OK) if (result == ACLCHECK_OK)
return true; return true;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.67 2002/02/19 20:11:18 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.68 2002/03/21 23:27:24 tgl Exp $
* *
* NOTES * NOTES
* These routines allow the parser/planner/executor to perform * These routines allow the parser/planner/executor to perform
...@@ -103,6 +103,16 @@ static struct cachedesc cacheinfo[] = { ...@@ -103,6 +103,16 @@ static struct cachedesc cacheinfo[] = {
0, 0,
0 0
}}, }},
{AggregateRelationName, /* AGGOID */
AggregateOidIndex,
0,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
}},
{AccessMethodRelationName, /* AMNAME */ {AccessMethodRelationName, /* AMNAME */
AmNameIndex, AmNameIndex,
0, 0,
......
...@@ -7,14 +7,13 @@ ...@@ -7,14 +7,13 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: rewriteRemove.h,v 1.10 2001/11/05 17:46:35 momjian Exp $ * $Id: rewriteRemove.h,v 1.11 2002/03/21 23:27:24 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef REWRITEREMOVE_H #ifndef REWRITEREMOVE_H
#define REWRITEREMOVE_H #define REWRITEREMOVE_H
extern char *RewriteGetRuleEventRel(char *rulename);
extern void RemoveRewriteRule(char *ruleName); extern void RemoveRewriteRule(char *ruleName);
extern void RelationRemoveRules(Oid relid); extern void RelationRemoveRules(Oid relid);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: acl.h,v 1.40 2002/02/18 23:11:45 petere Exp $ * $Id: acl.h,v 1.41 2002/03/21 23:27:25 tgl Exp $
* *
* NOTES * NOTES
* For backward-compatibility purposes we have to allow there * For backward-compatibility purposes we have to allow there
...@@ -24,11 +24,11 @@ ...@@ -24,11 +24,11 @@
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "utils/array.h" #include "utils/array.h"
#include "utils/memutils.h"
/* /*
* AclId system identifier for the user, group, etc. * AclId system identifier for the user, group, etc.
* XXX currently UNIX uid for users... * XXX Perhaps replace this type by OID?
*/ */
typedef uint32 AclId; typedef uint32 AclId;
...@@ -159,14 +159,14 @@ typedef ArrayType IdList; ...@@ -159,14 +159,14 @@ typedef ArrayType IdList;
#define ACL_MODE_REFERENCES_CHR 'x' #define ACL_MODE_REFERENCES_CHR 'x'
#define ACL_MODE_TRIGGER_CHR 't' #define ACL_MODE_TRIGGER_CHR 't'
/* result codes for pg_aclcheck */ /* result codes for pg_*_aclcheck */
#define ACLCHECK_OK 0 #define ACLCHECK_OK 0
#define ACLCHECK_NO_PRIV 1 #define ACLCHECK_NO_PRIV 1
#define ACLCHECK_NO_CLASS 2 #define ACLCHECK_NO_CLASS 2
#define ACLCHECK_NOT_OWNER 3 #define ACLCHECK_NOT_OWNER 3
/* error messages (index by ACL_CHECK_* result code). set in aclchk.c. */ /* error messages (index by ACLCHECK_* result code). set in aclchk.c. */
extern char *aclcheck_error_strings[]; extern const char * const aclcheck_error_strings[];
/* /*
* routines used internally * routines used internally
...@@ -199,16 +199,16 @@ extern void ExecuteGrantStmt(GrantStmt *stmt); ...@@ -199,16 +199,16 @@ extern void ExecuteGrantStmt(GrantStmt *stmt);
extern AclId get_grosysid(char *groname); extern AclId get_grosysid(char *groname);
extern char *get_groname(AclId grosysid); extern char *get_groname(AclId grosysid);
extern int32 pg_aclcheck(char *relname, Oid userid, AclMode mode); /* these return ACLCHECK_* result codes */
extern int32 pg_class_aclcheck(Oid table_oid, Oid userid, AclMode mode);
extern bool pg_ownercheck(Oid userid, const char *name, int cacheid);
extern bool pg_oper_ownercheck(Oid userid, Oid oprid);
extern bool pg_func_ownercheck(Oid userid, char *funcname,
int nargs, Oid *arglist);
extern bool pg_aggr_ownercheck(Oid userid, char *aggname,
Oid basetypeID);
extern int32 pg_proc_aclcheck(Oid proc_oid, Oid userid); extern int32 pg_proc_aclcheck(Oid proc_oid, Oid userid);
extern int32 pg_language_aclcheck(Oid lang_oid, Oid userid); extern int32 pg_language_aclcheck(Oid lang_oid, Oid userid);
/* ownercheck routines just return true (owner) or false (not) */
extern bool pg_class_ownercheck(Oid class_oid, Oid userid);
extern bool pg_type_ownercheck(Oid type_oid, Oid userid);
extern bool pg_oper_ownercheck(Oid oper_oid, Oid userid);
extern bool pg_proc_ownercheck(Oid proc_oid, Oid userid);
extern bool pg_aggr_ownercheck(Oid aggr_oid, Oid userid);
#endif /* ACL_H */ #endif /* ACL_H */
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: syscache.h,v 1.37 2002/02/19 20:11:20 tgl Exp $ * $Id: syscache.h,v 1.38 2002/03/21 23:27:25 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -29,33 +29,35 @@ ...@@ -29,33 +29,35 @@
*/ */
#define AGGNAME 0 #define AGGNAME 0
#define AMNAME 1 #define AGGOID 1
#define AMOID 2 #define AMNAME 2
#define AMOPOPID 3 #define AMOID 3
#define AMOPSTRATEGY 4 #define AMOPOPID 4
#define AMPROCNUM 5 #define AMOPSTRATEGY 5
#define ATTNAME 6 #define AMPROCNUM 6
#define ATTNUM 7 #define ATTNAME 7
#define CLAAMNAME 8 #define ATTNUM 8
#define CLAOID 9 #define CLAAMNAME 9
#define GRONAME 10 #define CLAOID 10
#define GROSYSID 11 #define GRONAME 11
#define INDEXRELID 12 #define GROSYSID 12
#define INHRELID 13 #define INDEXRELID 13
#define LANGNAME 14 #define INHRELID 14
#define LANGOID 15 #define LANGNAME 15
#define OPERNAME 16 #define LANGOID 16
#define OPEROID 17 #define OPERNAME 17
#define PROCNAME 18 #define OPEROID 18
#define PROCOID 19 #define PROCNAME 19
#define RELNAME 20 #define PROCOID 20
#define RELOID 21 #define RELNAME 21
#define RULENAME 22 #define RELOID 22
#define SHADOWNAME 23 #define RULENAME 23
#define SHADOWSYSID 24 #define SHADOWNAME 24
#define STATRELATT 25 #define SHADOWSYSID 25
#define TYPENAME 26 #define STATRELATT 26
#define TYPEOID 27 #define TYPENAME 27
#define TYPEOID 28
extern void InitCatalogCache(void); extern void InitCatalogCache(void);
extern void InitCatalogCachePhase2(void); extern void InitCatalogCachePhase2(void);
......
...@@ -221,7 +221,7 @@ drop rule 314159; ...@@ -221,7 +221,7 @@ drop rule 314159;
ERROR: parser: parse error at or near "314159" ERROR: parser: parse error at or near "314159"
-- no such rule -- no such rule
drop rule nonesuch; drop rule nonesuch;
ERROR: Rule or view "nonesuch" not found ERROR: Rule "nonesuch" not found
-- bad keyword -- bad keyword
drop tuple rule nonesuch; drop tuple rule nonesuch;
ERROR: parser: parse error at or near "tuple" ERROR: parser: parse error at or near "tuple"
......
...@@ -90,7 +90,7 @@ ERROR: LOCK TABLE: permission denied ...@@ -90,7 +90,7 @@ ERROR: LOCK TABLE: permission denied
COPY atest2 FROM stdin; -- fail COPY atest2 FROM stdin; -- fail
ERROR: atest2: Permission denied. ERROR: atest2: Permission denied.
GRANT ALL ON atest1 TO PUBLIC; -- fail GRANT ALL ON atest1 TO PUBLIC; -- fail
ERROR: permission denied ERROR: atest1: permission denied
-- checks in subquery, both ok -- checks in subquery, both ok
SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) ); SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) );
a | b a | b
...@@ -246,9 +246,9 @@ ERROR: user "nosuchuser" does not exist ...@@ -246,9 +246,9 @@ ERROR: user "nosuchuser" does not exist
select has_table_privilege('pg_shadow','sel'); select has_table_privilege('pg_shadow','sel');
ERROR: has_table_privilege: invalid privilege type sel ERROR: has_table_privilege: invalid privilege type sel
select has_table_privilege(-999999,'pg_shadow','update'); select has_table_privilege(-999999,'pg_shadow','update');
ERROR: pg_aclcheck: invalid user id 4293967297 ERROR: pg_class_aclcheck: invalid user id 4293967297
select has_table_privilege(1,'rule'); select has_table_privilege(1,'rule');
ERROR: has_table_privilege: invalid relation oid 1 ERROR: pg_class_aclcheck: relation 1 not found
-- superuser -- superuser
\c - \c -
select has_table_privilege(current_user,'pg_shadow','select'); select has_table_privilege(current_user,'pg_shadow','select');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment