mirror of
https://github.com/postgres/postgres.git
synced 2025-07-18 17:42:25 +03:00
Restructure aclcheck error reporting to make permission-failure
messages more uniform and internationalizable: the global array aclcheck_error_strings[] is gone in favor of a subroutine aclcheck_error(). Partial implementation of namespace-related permission checks --- not all done yet.
This commit is contained in:
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/aggregatecmds.c,v 1.2 2002/04/27 03:45:00 tgl Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@ -26,6 +26,7 @@
|
||||
#include "catalog/catname.h"
|
||||
#include "catalog/namespace.h"
|
||||
#include "catalog/pg_aggregate.h"
|
||||
#include "catalog/pg_proc.h"
|
||||
#include "commands/comment.h"
|
||||
#include "commands/defrem.h"
|
||||
#include "miscadmin.h"
|
||||
@ -45,6 +46,7 @@ DefineAggregate(List *names, List *parameters)
|
||||
{
|
||||
char *aggName;
|
||||
Oid aggNamespace;
|
||||
AclResult aclresult;
|
||||
List *transfuncName = NIL;
|
||||
List *finalfuncName = NIL;
|
||||
TypeName *baseType = NULL;
|
||||
@ -57,6 +59,11 @@ DefineAggregate(List *names, List *parameters)
|
||||
/* Convert list of names to a name and namespace */
|
||||
aggNamespace = QualifiedNameGetCreationNamespace(names, &aggName);
|
||||
|
||||
/* Check we have creation rights in target namespace */
|
||||
aclresult = pg_namespace_aclcheck(aggNamespace, GetUserId(), ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_namespace_name(aggNamespace));
|
||||
|
||||
foreach(pl, parameters)
|
||||
{
|
||||
DefElem *defel = (DefElem *) lfirst(pl);
|
||||
@ -157,20 +164,6 @@ RemoveAggregate(List *aggName, TypeName *aggType)
|
||||
|
||||
procOid = find_aggregate_func("RemoveAggregate", aggName, basetypeID);
|
||||
|
||||
/* Permission check */
|
||||
|
||||
if (!pg_proc_ownercheck(procOid, GetUserId()))
|
||||
{
|
||||
if (basetypeID == InvalidOid)
|
||||
elog(ERROR, "RemoveAggregate: aggregate %s for all types: permission denied",
|
||||
NameListToString(aggName));
|
||||
else
|
||||
elog(ERROR, "RemoveAggregate: aggregate %s for type %s: permission denied",
|
||||
NameListToString(aggName), format_type_be(basetypeID));
|
||||
}
|
||||
|
||||
/* Remove the pg_proc tuple */
|
||||
|
||||
relation = heap_openr(ProcedureRelationName, RowExclusiveLock);
|
||||
|
||||
tup = SearchSysCache(PROCOID,
|
||||
@ -180,9 +173,16 @@ RemoveAggregate(List *aggName, TypeName *aggType)
|
||||
elog(ERROR, "RemoveAggregate: couldn't find pg_proc tuple for %s",
|
||||
NameListToString(aggName));
|
||||
|
||||
/* Permission check: must own agg or its namespace */
|
||||
if (!pg_proc_ownercheck(procOid, GetUserId()) &&
|
||||
!pg_namespace_ownercheck(((Form_pg_proc) GETSTRUCT(tup))->pronamespace,
|
||||
GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(aggName));
|
||||
|
||||
/* Delete any comments associated with this function */
|
||||
DeleteComments(procOid, RelationGetRelid(relation));
|
||||
|
||||
/* Remove the pg_proc tuple */
|
||||
simple_heap_delete(relation, &tup->t_self);
|
||||
|
||||
ReleaseSysCache(tup);
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Copyright (c) 1999-2001, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.44 2002/04/24 02:50:30 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.45 2002/04/27 03:45:00 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -324,8 +324,7 @@ CommentRelation(int objtype, List *relname, char *comment)
|
||||
|
||||
/* Check object security */
|
||||
if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
|
||||
elog(ERROR, "you are not permitted to comment on class '%s'",
|
||||
RelationGetRelationName(relation));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(relation));
|
||||
|
||||
/* Next, verify that the relation type matches the intent */
|
||||
|
||||
@ -395,8 +394,7 @@ CommentAttribute(List *qualname, char *comment)
|
||||
/* Check object security */
|
||||
|
||||
if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
|
||||
elog(ERROR, "you are not permitted to comment on class '%s'",
|
||||
RelationGetRelationName(relation));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(relation));
|
||||
|
||||
/* Now, fetch the attribute number from the system cache */
|
||||
|
||||
@ -498,7 +496,7 @@ CommentRule(List *qualname, char *comment)
|
||||
Oid reloid;
|
||||
Oid ruleoid;
|
||||
Oid classoid;
|
||||
int32 aclcheck;
|
||||
AclResult aclcheck;
|
||||
|
||||
/* Separate relname and trig name */
|
||||
nnames = length(qualname);
|
||||
@ -573,8 +571,7 @@ CommentRule(List *qualname, char *comment)
|
||||
|
||||
aclcheck = pg_class_aclcheck(reloid, GetUserId(), ACL_RULE);
|
||||
if (aclcheck != ACLCHECK_OK)
|
||||
elog(ERROR, "you are not permitted to comment on rule '%s'",
|
||||
rulename);
|
||||
aclcheck_error(aclcheck, rulename);
|
||||
|
||||
/* pg_rewrite doesn't have a hard-coded OID, so must look it up */
|
||||
|
||||
@ -613,8 +610,7 @@ CommentType(List *typename, char *comment)
|
||||
/* Check object security */
|
||||
|
||||
if (!pg_type_ownercheck(oid, GetUserId()))
|
||||
elog(ERROR, "you are not permitted to comment on type %s",
|
||||
TypeNameToString(tname));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, TypeNameToString(tname));
|
||||
|
||||
/* Call CreateComments() to create/drop the comments */
|
||||
|
||||
@ -649,14 +645,7 @@ CommentAggregate(List *aggregate, List *arguments, char *comment)
|
||||
/* Next, validate the user's attempt to comment */
|
||||
|
||||
if (!pg_proc_ownercheck(oid, GetUserId()))
|
||||
{
|
||||
if (baseoid == InvalidOid)
|
||||
elog(ERROR, "you are not permitted to comment on aggregate %s for all types",
|
||||
NameListToString(aggregate));
|
||||
else
|
||||
elog(ERROR, "you are not permitted to comment on aggregate %s for type %s",
|
||||
NameListToString(aggregate), format_type_be(baseoid));
|
||||
}
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(aggregate));
|
||||
|
||||
/* Call CreateComments() to create/drop the comments */
|
||||
|
||||
@ -685,8 +674,7 @@ CommentProc(List *function, List *arguments, char *comment)
|
||||
/* 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",
|
||||
NameListToString(function));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(function));
|
||||
|
||||
/* Call CreateComments() to create/drop the comments */
|
||||
|
||||
@ -723,8 +711,7 @@ CommentOperator(List *opername, List *arguments, char *comment)
|
||||
/* Valid user's ability to comment on this operator */
|
||||
|
||||
if (!pg_oper_ownercheck(oid, GetUserId()))
|
||||
elog(ERROR, "you are not permitted to comment on operator '%s'",
|
||||
NameListToString(opername));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(opername));
|
||||
|
||||
/* Get the procedure associated with the operator */
|
||||
|
||||
@ -775,8 +762,7 @@ CommentTrigger(List *qualname, char *comment)
|
||||
/* Check object security */
|
||||
|
||||
if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
|
||||
elog(ERROR, "you are not permitted to comment on trigger '%s' for relation '%s'",
|
||||
trigname, RelationGetRelationName(relation));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(relation));
|
||||
|
||||
/*
|
||||
* Fetch the trigger tuple from pg_trigger. There can be only one
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.152 2002/03/29 19:06:05 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.153 2002/04/27 03:45:00 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -266,8 +266,8 @@ DoCopy(const RangeVar *relation, bool binary, bool oids, bool from, bool pipe,
|
||||
{
|
||||
FILE *fp;
|
||||
Relation rel;
|
||||
const AclMode required_access = (from ? ACL_INSERT : ACL_SELECT);
|
||||
int32 aclresult;
|
||||
AclMode required_access = (from ? ACL_INSERT : ACL_SELECT);
|
||||
AclResult aclresult;
|
||||
|
||||
/*
|
||||
* Open and lock the relation, using the appropriate lock type.
|
||||
@ -278,9 +278,7 @@ DoCopy(const RangeVar *relation, bool binary, bool oids, bool from, bool pipe,
|
||||
aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
|
||||
required_access);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
elog(ERROR, "%s: %s",
|
||||
RelationGetRelationName(rel),
|
||||
aclcheck_error_strings[aclresult]);
|
||||
aclcheck_error(aclresult, RelationGetRelationName(rel));
|
||||
if (!pipe && !superuser())
|
||||
elog(ERROR, "You must have Postgres superuser privilege to do a COPY "
|
||||
"directly to or from a file. Anyone can COPY to stdout or "
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.2 2002/04/21 00:26:42 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.3 2002/04/27 03:45:01 tgl Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* These routines take the parse tree and pick out the
|
||||
@ -86,6 +86,7 @@ compute_return_type(TypeName *returnType, Oid languageOid,
|
||||
else
|
||||
{
|
||||
Oid namespaceId;
|
||||
AclResult aclresult;
|
||||
char *typname;
|
||||
|
||||
if (languageOid == SQLlanguageId)
|
||||
@ -94,6 +95,10 @@ compute_return_type(TypeName *returnType, Oid languageOid,
|
||||
typnam);
|
||||
namespaceId = QualifiedNameGetCreationNamespace(returnType->names,
|
||||
&typname);
|
||||
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
|
||||
ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_namespace_name(namespaceId));
|
||||
rettype = TypeShellMake(typname, namespaceId);
|
||||
if (!OidIsValid(rettype))
|
||||
elog(ERROR, "could not create type %s", typnam);
|
||||
@ -295,6 +300,7 @@ CreateFunction(ProcedureStmt *stmt)
|
||||
Oid languageOid;
|
||||
char *funcname;
|
||||
Oid namespaceId;
|
||||
AclResult aclresult;
|
||||
int parameterCount;
|
||||
Oid parameterTypes[FUNC_MAX_ARGS];
|
||||
int32 byte_pct,
|
||||
@ -311,6 +317,11 @@ CreateFunction(ProcedureStmt *stmt)
|
||||
namespaceId = QualifiedNameGetCreationNamespace(stmt->funcname,
|
||||
&funcname);
|
||||
|
||||
/* Check we have creation rights in target namespace */
|
||||
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_namespace_name(namespaceId));
|
||||
|
||||
/* Convert language name to canonical case */
|
||||
case_translate_language_name(stmt->language, languageName);
|
||||
|
||||
@ -324,10 +335,21 @@ CreateFunction(ProcedureStmt *stmt)
|
||||
languageOid = languageTuple->t_data->t_oid;
|
||||
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
|
||||
|
||||
if (!((languageStruct->lanpltrusted
|
||||
&& pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE) == ACLCHECK_OK)
|
||||
|| superuser()))
|
||||
elog(ERROR, "permission denied");
|
||||
if (languageStruct->lanpltrusted)
|
||||
{
|
||||
/* if trusted language, need USAGE privilege */
|
||||
AclResult aclresult;
|
||||
|
||||
aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, NameStr(languageStruct->lanname));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if untrusted language, must be superuser */
|
||||
if (!superuser())
|
||||
aclcheck_error(ACLCHECK_NO_PRIV, NameStr(languageStruct->lanname));
|
||||
}
|
||||
|
||||
ReleaseSysCache(languageTuple);
|
||||
|
||||
@ -404,9 +426,11 @@ RemoveFunction(List *functionName, /* function name to be removed */
|
||||
elog(ERROR, "RemoveFunction: couldn't find tuple for function %s",
|
||||
NameListToString(functionName));
|
||||
|
||||
if (!pg_proc_ownercheck(funcOid, GetUserId()))
|
||||
elog(ERROR, "RemoveFunction: function '%s': permission denied",
|
||||
NameListToString(functionName));
|
||||
/* Permission check: must own func or its namespace */
|
||||
if (!pg_proc_ownercheck(funcOid, GetUserId()) &&
|
||||
!pg_namespace_ownercheck(((Form_pg_proc) GETSTRUCT(tup))->pronamespace,
|
||||
GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(functionName));
|
||||
|
||||
if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
|
||||
elog(ERROR, "RemoveFunction: function '%s' is an aggregate"
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.71 2002/04/17 20:57:56 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.72 2002/04/27 03:45:01 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -30,6 +30,7 @@
|
||||
#include "parser/parsetree.h"
|
||||
#include "parser/parse_coerce.h"
|
||||
#include "parser/parse_func.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
@ -73,6 +74,7 @@ DefineIndex(RangeVar *heapRelation,
|
||||
Oid *classObjectId;
|
||||
Oid accessMethodId;
|
||||
Oid relationId;
|
||||
Oid namespaceId;
|
||||
Relation rel;
|
||||
HeapTuple tuple;
|
||||
Form_pg_am accessMethodForm;
|
||||
@ -102,6 +104,7 @@ DefineIndex(RangeVar *heapRelation,
|
||||
heapRelation->relname);
|
||||
|
||||
relationId = RelationGetRelid(rel);
|
||||
namespaceId = RelationGetNamespace(rel);
|
||||
|
||||
if (!IsBootstrapProcessingMode() &&
|
||||
IsSystemRelation(rel) &&
|
||||
@ -110,6 +113,22 @@ DefineIndex(RangeVar *heapRelation,
|
||||
|
||||
heap_close(rel, NoLock);
|
||||
|
||||
/*
|
||||
* Verify we (still) have CREATE rights in the rel's namespace.
|
||||
* (Presumably we did when the rel was created, but maybe not anymore.)
|
||||
* Skip check if bootstrapping, since permissions machinery may not
|
||||
* be working yet; also, always allow if it's a temp table.
|
||||
*/
|
||||
if (!IsBootstrapProcessingMode() && !isTempNamespace(namespaceId))
|
||||
{
|
||||
AclResult aclresult;
|
||||
|
||||
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
|
||||
ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_namespace_name(namespaceId));
|
||||
}
|
||||
|
||||
/*
|
||||
* look up the access method, verify it can handle the requested
|
||||
* features
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/lockcmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/lockcmds.c,v 1.2 2002/04/27 03:45:01 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -19,6 +19,7 @@
|
||||
#include "commands/lockcmds.h"
|
||||
#include "miscadmin.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/lsyscache.h"
|
||||
|
||||
|
||||
/*
|
||||
@ -38,7 +39,7 @@ LockTableCommand(LockStmt *lockstmt)
|
||||
{
|
||||
RangeVar *relation = lfirst(p);
|
||||
Oid reloid;
|
||||
int32 aclresult;
|
||||
AclResult aclresult;
|
||||
Relation rel;
|
||||
|
||||
/*
|
||||
@ -55,7 +56,7 @@ LockTableCommand(LockStmt *lockstmt)
|
||||
ACL_UPDATE | ACL_DELETE);
|
||||
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
elog(ERROR, "LOCK TABLE: permission denied");
|
||||
aclcheck_error(aclresult, get_rel_name(reloid));
|
||||
|
||||
rel = relation_open(reloid, lockstmt->mode);
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/operatorcmds.c,v 1.2 2002/04/16 23:08:10 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/operatorcmds.c,v 1.3 2002/04/27 03:45:01 tgl Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@ -44,6 +44,7 @@
|
||||
#include "parser/parse_oper.h"
|
||||
#include "parser/parse_type.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
|
||||
@ -60,6 +61,7 @@ DefineOperator(List *names, List *parameters)
|
||||
{
|
||||
char *oprName;
|
||||
Oid oprNamespace;
|
||||
AclResult aclresult;
|
||||
uint16 precedence = 0; /* operator precedence */
|
||||
bool canHash = false; /* operator hashes */
|
||||
bool canMerge = false; /* operator merges */
|
||||
@ -85,6 +87,11 @@ DefineOperator(List *names, List *parameters)
|
||||
/* Convert list of names to a name and namespace */
|
||||
oprNamespace = QualifiedNameGetCreationNamespace(names, &oprName);
|
||||
|
||||
/* Check we have creation rights in target namespace */
|
||||
aclresult = pg_namespace_aclcheck(oprNamespace, GetUserId(), ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_namespace_name(oprNamespace));
|
||||
|
||||
/*
|
||||
* loop over the definition list and extract the information we need.
|
||||
*/
|
||||
@ -226,14 +233,15 @@ RemoveOperator(List *operatorName, /* operator name */
|
||||
tup = SearchSysCacheCopy(OPEROID,
|
||||
ObjectIdGetDatum(operOid),
|
||||
0, 0, 0);
|
||||
|
||||
if (!HeapTupleIsValid(tup)) /* should not happen */
|
||||
elog(ERROR, "RemoveOperator: failed to find tuple for operator '%s'",
|
||||
NameListToString(operatorName));
|
||||
|
||||
if (!pg_oper_ownercheck(operOid, GetUserId()))
|
||||
elog(ERROR, "RemoveOperator: operator '%s': permission denied",
|
||||
NameListToString(operatorName));
|
||||
/* Permission check: must own operator or its namespace */
|
||||
if (!pg_oper_ownercheck(operOid, GetUserId()) &&
|
||||
!pg_namespace_ownercheck(((Form_pg_operator) GETSTRUCT(tup))->oprnamespace,
|
||||
GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, NameListToString(operatorName));
|
||||
|
||||
/* Delete any comments associated with this operator */
|
||||
DeleteComments(operOid, RelationGetRelid(relation));
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/schemacmds.c,v 1.2 2002/04/27 03:45:01 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -20,6 +20,7 @@
|
||||
#include "miscadmin.h"
|
||||
#include "parser/analyze.h"
|
||||
#include "tcop/utility.h"
|
||||
#include "utils/acl.h"
|
||||
#include "utils/lsyscache.h"
|
||||
|
||||
|
||||
@ -36,9 +37,14 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
|
||||
const char *owner_name;
|
||||
Oid owner_userid;
|
||||
Oid saved_userid;
|
||||
AclResult aclresult;
|
||||
|
||||
saved_userid = GetUserId();
|
||||
|
||||
/*
|
||||
* Figure out user identities.
|
||||
*/
|
||||
|
||||
if (!authId)
|
||||
{
|
||||
owner_userid = saved_userid;
|
||||
@ -67,6 +73,13 @@ CreateSchemaCommand(CreateSchemaStmt *stmt)
|
||||
owner_name, authId);
|
||||
}
|
||||
|
||||
/*
|
||||
* Permissions checks.
|
||||
*/
|
||||
aclresult = pg_database_aclcheck(MyDatabaseId, saved_userid, ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, DatabaseName);
|
||||
|
||||
if (!allowSystemTableMods && IsReservedName(schemaName))
|
||||
elog(ERROR, "CREATE SCHEMA: Illegal schema name: \"%s\" -- pg_ is reserved for system schemas",
|
||||
schemaName);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.10 2002/04/26 19:29:47 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.11 2002/04/27 03:45:01 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -106,10 +106,22 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
||||
|
||||
/*
|
||||
* Look up the namespace in which we are supposed to create the
|
||||
* relation.
|
||||
* relation. Check we have permission to create there.
|
||||
* Skip check if bootstrapping, since permissions machinery may not
|
||||
* be working yet; also, always allow if it's a temp table.
|
||||
*/
|
||||
namespaceId = RangeVarGetCreationNamespace(stmt->relation);
|
||||
|
||||
if (!IsBootstrapProcessingMode() && !isTempNamespace(namespaceId))
|
||||
{
|
||||
AclResult aclresult;
|
||||
|
||||
aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
|
||||
ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_namespace_name(namespaceId));
|
||||
}
|
||||
|
||||
/*
|
||||
* Merge domain attributes into the known columns before processing table
|
||||
* inheritance. Otherwise we risk adding double constraints to a
|
||||
@ -307,8 +319,7 @@ TruncateRelation(const RangeVar *relation)
|
||||
RelationGetRelationName(rel));
|
||||
|
||||
if (!pg_class_ownercheck(relid, GetUserId()))
|
||||
elog(ERROR, "you do not own relation \"%s\"",
|
||||
RelationGetRelationName(rel));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
|
||||
|
||||
/* Keep the lock until transaction commit */
|
||||
heap_close(rel, NoLock);
|
||||
@ -483,8 +494,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
||||
* demand that creator of a child table own the parent.
|
||||
*/
|
||||
if (!pg_class_ownercheck(RelationGetRelid(relation), GetUserId()))
|
||||
elog(ERROR, "you do not own table \"%s\"",
|
||||
parent->relname);
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER,
|
||||
RelationGetRelationName(relation));
|
||||
|
||||
/*
|
||||
* Reject duplications in the list of parents.
|
||||
@ -1003,8 +1014,8 @@ renameatt(Oid relid,
|
||||
elog(ERROR, "renameatt: class \"%s\" is a system catalog",
|
||||
RelationGetRelationName(targetrelation));
|
||||
if (!pg_class_ownercheck(relid, GetUserId()))
|
||||
elog(ERROR, "renameatt: you do not own class \"%s\"",
|
||||
RelationGetRelationName(targetrelation));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER,
|
||||
RelationGetRelationName(targetrelation));
|
||||
|
||||
/*
|
||||
* if the 'recurse' flag is set then we are supposed to rename this
|
||||
@ -1558,8 +1569,7 @@ AlterTableAddColumn(Oid myrelid,
|
||||
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
|
||||
RelationGetRelationName(rel));
|
||||
if (!pg_class_ownercheck(myrelid, GetUserId()))
|
||||
elog(ERROR, "ALTER TABLE: \"%s\": permission denied",
|
||||
RelationGetRelationName(rel));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
|
||||
|
||||
/*
|
||||
* Recurse to add the column to child classes, if requested.
|
||||
@ -1761,8 +1771,7 @@ AlterTableAlterColumnDropNotNull(Oid myrelid,
|
||||
RelationGetRelationName(rel));
|
||||
|
||||
if (!pg_class_ownercheck(myrelid, GetUserId()))
|
||||
elog(ERROR, "ALTER TABLE: \"%s\": permission denied",
|
||||
RelationGetRelationName(rel));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
|
||||
|
||||
/*
|
||||
* Propagate to children if desired
|
||||
@ -1912,8 +1921,7 @@ AlterTableAlterColumnSetNotNull(Oid myrelid,
|
||||
RelationGetRelationName(rel));
|
||||
|
||||
if (!pg_class_ownercheck(myrelid, GetUserId()))
|
||||
elog(ERROR, "ALTER TABLE: \"%s\": permission denied",
|
||||
RelationGetRelationName(rel));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
|
||||
|
||||
/*
|
||||
* Propagate to children if desired
|
||||
@ -2048,8 +2056,7 @@ AlterTableAlterColumnDefault(Oid myrelid,
|
||||
RelationGetRelationName(rel));
|
||||
|
||||
if (!pg_class_ownercheck(myrelid, GetUserId()))
|
||||
elog(ERROR, "ALTER TABLE: \"%s\": permission denied",
|
||||
RelationGetRelationName(rel));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
|
||||
|
||||
/*
|
||||
* Propagate to children if desired
|
||||
@ -2208,8 +2215,7 @@ AlterTableAlterColumnFlags(Oid myrelid,
|
||||
RelationGetRelationName(rel));
|
||||
|
||||
if (!pg_class_ownercheck(myrelid, GetUserId()))
|
||||
elog(ERROR, "ALTER TABLE: \"%s\": permission denied",
|
||||
RelationGetRelationName(rel));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
|
||||
|
||||
/*
|
||||
* Check the supplied parameters before anything else
|
||||
@ -2370,8 +2376,7 @@ AlterTableAddConstraint(Oid myrelid,
|
||||
RelationGetRelationName(rel));
|
||||
|
||||
if (!pg_class_ownercheck(myrelid, GetUserId()))
|
||||
elog(ERROR, "ALTER TABLE: \"%s\": permission denied",
|
||||
RelationGetRelationName(rel));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
|
||||
|
||||
if (inh)
|
||||
{
|
||||
@ -2695,8 +2700,7 @@ AlterTableDropConstraint(Oid myrelid,
|
||||
RelationGetRelationName(rel));
|
||||
|
||||
if (!pg_class_ownercheck(myrelid, GetUserId()))
|
||||
elog(ERROR, "ALTER TABLE: \"%s\": permission denied",
|
||||
RelationGetRelationName(rel));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
|
||||
|
||||
/*
|
||||
* Since all we have is the name of the constraint, we have to look
|
||||
@ -2857,8 +2861,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
|
||||
RelationGetRelationName(rel));
|
||||
|
||||
if (!pg_class_ownercheck(relOid, GetUserId()))
|
||||
elog(ERROR, "ALTER TABLE: \"%s\": permission denied",
|
||||
RelationGetRelationName(rel));
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
|
||||
|
||||
/*
|
||||
* lock the pg_class tuple for update (is that really needed?)
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.115 2002/04/26 19:29:47 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.116 2002/04/27 03:45:02 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -58,6 +58,7 @@ CreateTrigger(CreateTrigStmt *stmt)
|
||||
Datum values[Natts_pg_trigger];
|
||||
char nulls[Natts_pg_trigger];
|
||||
Relation rel;
|
||||
AclResult aclresult;
|
||||
Relation tgrel;
|
||||
SysScanDesc tgscan;
|
||||
ScanKeyData key;
|
||||
@ -84,10 +85,10 @@ CreateTrigger(CreateTrigStmt *stmt)
|
||||
elog(ERROR, "CreateTrigger: can't create trigger for system relation %s",
|
||||
stmt->relation->relname);
|
||||
|
||||
if (pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
|
||||
stmt->isconstraint ? ACL_REFERENCES : ACL_TRIGGER)
|
||||
!= ACLCHECK_OK)
|
||||
elog(ERROR, "permission denied");
|
||||
aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
|
||||
stmt->isconstraint ? ACL_REFERENCES : ACL_TRIGGER);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, RelationGetRelationName(rel));
|
||||
|
||||
/*
|
||||
* If trigger is an RI constraint, use trigger name as constraint name
|
||||
@ -337,8 +338,7 @@ DropTrigger(Oid relid, const char *trigname)
|
||||
RelationGetRelationName(rel));
|
||||
|
||||
if (!pg_class_ownercheck(relid, GetUserId()))
|
||||
elog(ERROR, "%s: %s", RelationGetRelationName(rel),
|
||||
aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
|
||||
|
||||
/*
|
||||
* Search pg_trigger, delete target trigger, count remaining triggers
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.1 2002/04/15 05:22:03 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.2 2002/04/27 03:45:02 tgl Exp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The "DefineFoo" routines take the parse tree and pick out the
|
||||
@ -45,6 +45,7 @@
|
||||
#include "utils/acl.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/fmgroids.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
|
||||
@ -60,6 +61,7 @@ DefineType(List *names, List *parameters)
|
||||
{
|
||||
char *typeName;
|
||||
Oid typeNamespace;
|
||||
AclResult aclresult;
|
||||
int16 internalLength = -1; /* int2 */
|
||||
int16 externalLength = -1; /* int2 */
|
||||
Oid elemType = InvalidOid;
|
||||
@ -83,6 +85,11 @@ DefineType(List *names, List *parameters)
|
||||
/* Convert list of names to a name and namespace */
|
||||
typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName);
|
||||
|
||||
/* Check we have creation rights in target namespace */
|
||||
aclresult = pg_namespace_aclcheck(typeNamespace, GetUserId(), ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_namespace_name(typeNamespace));
|
||||
|
||||
/*
|
||||
* Type names must be one character shorter than other names, allowing
|
||||
* room to create the corresponding array type name with prepended
|
||||
@ -288,9 +295,11 @@ RemoveType(List *names)
|
||||
elog(ERROR, "Type \"%s\" does not exist",
|
||||
TypeNameToString(typename));
|
||||
|
||||
if (!pg_type_ownercheck(typeoid, GetUserId()))
|
||||
elog(ERROR, "RemoveType: type '%s': permission denied",
|
||||
TypeNameToString(typename));
|
||||
/* Permission check: must own type or its namespace */
|
||||
if (!pg_type_ownercheck(typeoid, GetUserId()) &&
|
||||
!pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace,
|
||||
GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, TypeNameToString(typename));
|
||||
|
||||
/* Delete any comments associated with this type */
|
||||
DeleteComments(typeoid, RelationGetRelid(relation));
|
||||
@ -334,6 +343,7 @@ DefineDomain(CreateDomainStmt *stmt)
|
||||
{
|
||||
char *domainName;
|
||||
Oid domainNamespace;
|
||||
AclResult aclresult;
|
||||
int16 internalLength;
|
||||
int16 externalLength;
|
||||
Oid inputProcedure;
|
||||
@ -360,6 +370,12 @@ DefineDomain(CreateDomainStmt *stmt)
|
||||
domainNamespace = QualifiedNameGetCreationNamespace(stmt->domainname,
|
||||
&domainName);
|
||||
|
||||
/* Check we have creation rights in target namespace */
|
||||
aclresult = pg_namespace_aclcheck(domainNamespace, GetUserId(),
|
||||
ACL_CREATE);
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
aclcheck_error(aclresult, get_namespace_name(domainNamespace));
|
||||
|
||||
/*
|
||||
* Domainnames, unlike typenames don't need to account for the '_'
|
||||
* prefix. So they can be one character longer.
|
||||
@ -586,9 +602,11 @@ RemoveDomain(List *names, int behavior)
|
||||
elog(ERROR, "RemoveDomain: type '%s' does not exist",
|
||||
TypeNameToString(typename));
|
||||
|
||||
if (!pg_type_ownercheck(typeoid, GetUserId()))
|
||||
elog(ERROR, "RemoveDomain: type '%s': permission denied",
|
||||
TypeNameToString(typename));
|
||||
/* Permission check: must own type or its namespace */
|
||||
if (!pg_type_ownercheck(typeoid, GetUserId()) &&
|
||||
!pg_namespace_ownercheck(((Form_pg_type) GETSTRUCT(tup))->typnamespace,
|
||||
GetUserId()))
|
||||
aclcheck_error(ACLCHECK_NOT_OWNER, TypeNameToString(typename));
|
||||
|
||||
/* Check that this is actually a domain */
|
||||
typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype;
|
||||
|
Reference in New Issue
Block a user