mirror of
https://github.com/postgres/postgres.git
synced 2025-06-16 06:01:02 +03:00
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.
This commit is contained in:
@ -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);
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
*/
|
*/
|
||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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 @@
|
|||||||
* 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 @@
|
|||||||
#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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
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)
|
|||||||
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;
|
|
||||||
|
|
||||||
/* First, validate user */
|
/* Find the rule's pg_rewrite tuple, get its OID and its table's OID */
|
||||||
|
|
||||||
relation = RewriteGetRuleEventRel(rule);
|
tuple = SearchSysCache(RULENAME,
|
||||||
aclcheck = pg_aclcheck(relation, GetUserId(), ACL_RULE);
|
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;
|
||||||
|
|
||||||
|
ReleaseSysCache(tuple);
|
||||||
|
|
||||||
|
/* Check object security */
|
||||||
|
|
||||||
|
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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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,18 +581,6 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
|
|||||||
else
|
else
|
||||||
baseoid = InvalidOid;
|
baseoid = InvalidOid;
|
||||||
|
|
||||||
/* Next, validate the user's attempt to comment */
|
|
||||||
|
|
||||||
if (!pg_aggr_ownercheck(GetUserId(), aggregate, baseoid))
|
|
||||||
{
|
|
||||||
if (baseoid == InvalidOid)
|
|
||||||
elog(ERROR, "you are not permitted to comment on aggregate '%s' for all types",
|
|
||||||
aggregate);
|
|
||||||
else
|
|
||||||
elog(ERROR, "you are not permitted to comment on aggregate '%s' for type %s",
|
|
||||||
aggregate, format_type_be(baseoid));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now, attempt to find the actual tuple in pg_aggregate */
|
/* Now, attempt to find the actual tuple in pg_aggregate */
|
||||||
|
|
||||||
oid = GetSysCacheOid(AGGNAME,
|
oid = GetSysCacheOid(AGGNAME,
|
||||||
@ -597,6 +590,18 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
|
|||||||
if (!OidIsValid(oid))
|
if (!OidIsValid(oid))
|
||||||
agg_error("CommentAggregate", aggregate, baseoid);
|
agg_error("CommentAggregate", aggregate, baseoid);
|
||||||
|
|
||||||
|
/* Next, validate the user's attempt to comment */
|
||||||
|
|
||||||
|
if (!pg_aggr_ownercheck(oid, GetUserId()))
|
||||||
|
{
|
||||||
|
if (baseoid == InvalidOid)
|
||||||
|
elog(ERROR, "you are not permitted to comment on aggregate '%s' for all types",
|
||||||
|
aggregate);
|
||||||
|
else
|
||||||
|
elog(ERROR, "you are not permitted to comment on aggregate '%s' for type %s",
|
||||||
|
aggregate, format_type_be(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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
|||||||
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)
|
|||||||
|
|
||||||
/* 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)
|
|||||||
|
|
||||||
/* 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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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,
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
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,
|
|||||||
* 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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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 */
|
|||||||
|
|
||||||
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 */
|
|||||||
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 */
|
|||||||
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 */
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 */
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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,
|
|||||||
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,
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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 @@
|
|||||||
* 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,11 +71,17 @@ 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)
|
|||||||
* 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)
|
|||||||
int found = 0;
|
int found = 0;
|
||||||
int tgfound = 0;
|
int tgfound = 0;
|
||||||
|
|
||||||
if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->relname))
|
|
||||||
elog(ERROR, "DropTrigger: can't drop trigger for system relation %s",
|
|
||||||
stmt->relation->relname);
|
|
||||||
|
|
||||||
if (!pg_ownercheck(GetUserId(), stmt->relation->relname, RELNAME))
|
|
||||||
elog(ERROR, "%s: %s", stmt->relation->relname,
|
|
||||||
aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
|
|
||||||
|
|
||||||
rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
|
rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
|
||||||
|
|
||||||
if (rel->rd_rel->relkind != RELKIND_RELATION)
|
if (rel->rd_rel->relkind != RELKIND_RELATION)
|
||||||
elog(ERROR, "DropTrigger: relation \"%s\" is not a table",
|
elog(ERROR, "DropTrigger: relation \"%s\" is not a table",
|
||||||
stmt->relation->relname);
|
stmt->relation->relname);
|
||||||
|
|
||||||
|
if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->relname))
|
||||||
|
elog(ERROR, "DropTrigger: can't drop trigger for system relation %s",
|
||||||
|
stmt->relation->relname);
|
||||||
|
|
||||||
|
if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
|
||||||
|
elog(ERROR, "%s: %s", stmt->relation->relname,
|
||||||
|
aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
*
|
*
|
||||||
* 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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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 @@
|
|||||||
#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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
}
|
}
|
||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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 @@
|
|||||||
#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)
|
|||||||
*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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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 @@
|
|||||||
#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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
*/
|
*/
|
||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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
|
|||||||
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,
|
|||||||
/*
|
/*
|
||||||
* 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;
|
||||||
|
12
src/backend/utils/cache/syscache.c
vendored
12
src/backend/utils/cache/syscache.c
vendored
@ -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[] = {
|
|||||||
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 @@
|
|||||||
* 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 @@
|
|||||||
* 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 @@
|
|||||||
|
|
||||||
#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;
|
|||||||
#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);
|
|||||||
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 @@
|
|||||||
* 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 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#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;
|
|||||||
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
|
|||||||
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
|
|||||||
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');
|
||||||
|
Reference in New Issue
Block a user