*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.66 2002/04/21 00:26:42 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/aclchk.c,v 1.67 2002/04/27 03:45:00 tgl Exp $
*
* NOTES
* See acl.h.
static const char *privilege_to_string(AclMode privilege);
-static int32 aclcheck(Acl *acl, AclId id, uint32 idtype, AclMode mode);
-
-/* warning messages, now more explicit. */
-/* MUST correspond to the order of the ACLCHECK_* result codes in acl.h. */
-const char * const aclcheck_error_strings[] = {
- "No error.",
- "Permission denied.",
- "Table does not exist.",
- "Must be table owner."
-};
+static AclResult aclcheck(Acl *acl, AclId id, uint32 idtype, AclMode mode);
#ifdef ACLDEBUG
pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
if (!pg_class_ownercheck(relOid, GetUserId()))
- elog(ERROR, "%s: permission denied",
- relvar->relname);
+ aclcheck_error(ACLCHECK_NOT_OWNER, relvar->relname);
if (pg_class_tuple->relkind == RELKIND_INDEX)
elog(ERROR, "\"%s\" is an index",
pg_proc_tuple = (Form_pg_proc) GETSTRUCT(tuple);
if (!pg_proc_ownercheck(oid, GetUserId()))
- elog(ERROR, "permission denied");
+ aclcheck_error(ACLCHECK_NOT_OWNER,
+ NameStr(pg_proc_tuple->proname));
/*
* If there's no ACL, create a default using the pg_proc.proowner
pg_namespace_tuple = (Form_pg_namespace) GETSTRUCT(tuple);
if (!pg_namespace_ownercheck(tuple->t_data->t_oid, GetUserId()))
- elog(ERROR, "permission denied");
+ aclcheck_error(ACLCHECK_NOT_OWNER, nspname);
/*
* If there's no ACL, create a default using the pg_namespace.nspowner
return result;
}
+
/*
* aclcheck
*
*
* The ACL list is expected to be sorted in standard order.
*/
-static int32
+static AclResult
aclcheck(Acl *acl, AclId id, uint32 idtype, AclMode mode)
{
AclItem *aip,
}
+/*
+ * Standardized reporting of aclcheck permissions failures.
+ */
+void
+aclcheck_error(AclResult errcode, const char *objectname)
+{
+ switch (errcode)
+ {
+ case ACLCHECK_OK:
+ /* no error, so return to caller */
+ break;
+ case ACLCHECK_NO_PRIV:
+ elog(ERROR, "%s: permission denied", objectname);
+ break;
+ case ACLCHECK_NOT_OWNER:
+ elog(ERROR, "%s: must be owner", objectname);
+ break;
+ default:
+ elog(ERROR, "%s: unexpected AclResult %d",
+ objectname, (int) errcode);
+ break;
+ }
+}
+
+
/*
* Exported routine for checking a user's access privileges to a table
- *
- * Returns an ACLCHECK_* result code.
*/
-int32
+AclResult
pg_class_aclcheck(Oid table_oid, Oid userid, AclMode mode)
{
- int32 result;
+ AclResult result;
bool usesuper,
usecatupd;
HeapTuple tuple;
/*
* Exported routine for checking a user's access privileges to a database
- *
- * Returns an ACLCHECK_* result code.
*/
-int32
+AclResult
pg_database_aclcheck(Oid db_oid, Oid userid, AclMode mode)
{
- int32 result;
+ AclResult result;
Relation pg_database;
ScanKeyData entry[1];
HeapScanDesc scan;
/*
* Exported routine for checking a user's access privileges to a function
- *
- * Returns an ACLCHECK_* result code.
*/
-int32
+AclResult
pg_proc_aclcheck(Oid proc_oid, Oid userid, AclMode mode)
{
- int32 result;
+ AclResult result;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
/*
* Exported routine for checking a user's access privileges to a language
- *
- * Returns an ACLCHECK_* result code.
*/
-int32
+AclResult
pg_language_aclcheck(Oid lang_oid, Oid userid, AclMode mode)
{
- int32 result;
+ AclResult result;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
/*
* Exported routine for checking a user's access privileges to a namespace
- *
- * Returns an ACLCHECK_* result code.
*/
-int32
+AclResult
pg_namespace_aclcheck(Oid nsp_oid, Oid userid, AclMode mode)
{
- int32 result;
+ AclResult result;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.13 2002/04/26 01:24:08 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.14 2002/04/27 03:45:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "storage/backendid.h"
+#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/guc.h"
char namespaceName[NAMEDATALEN];
Oid namespaceId;
+ /*
+ * First, do permission check to see if we are authorized to make
+ * temp tables. We use a nonstandard error message here since
+ * "databasename: permission denied" might be a tad cryptic.
+ */
+ if (pg_database_aclcheck(MyDatabaseId, GetUserId(),
+ ACL_CREATE_TEMP) != ACLCHECK_OK)
+ elog(ERROR, "%s: not authorized to create temp tables",
+ DatabaseName);
+
snprintf(namespaceName, NAMEDATALEN, "pg_temp_%d", MyBackendId);
namespaceId = GetSysCacheOid(NAMESPACENAME,
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.67 2002/04/25 02:56:55 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.68 2002/04/27 03:45:00 tgl Exp $
*
* NOTES
* these routines moved here from commands/define.c and somewhat cleaned up.
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "parser/parse_oper.h"
+#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
bool otherDefined;
char *otherName;
Oid otherNamespace;
+ AclResult aclresult;
other_oid = OperatorLookup(otherOp,
otherLeftTypeId,
}
/* not in catalogs, different from operator, so make shell */
+
+ aclresult = pg_namespace_aclcheck(otherNamespace, GetUserId(),
+ ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, get_namespace_name(otherNamespace));
+
other_oid = OperatorShellMake(otherName,
otherNamespace,
otherLeftTypeId,
*
*
* 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
#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"
{
char *aggName;
Oid aggNamespace;
+ AclResult aclresult;
List *transfuncName = NIL;
List *finalfuncName = NIL;
TypeName *baseType = NULL;
/* 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);
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,
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);
* 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 $
*
*-------------------------------------------------------------------------
*/
/* 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 */
/* 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 */
Oid reloid;
Oid ruleoid;
Oid classoid;
- int32 aclcheck;
+ AclResult aclcheck;
/* Separate relname and trig name */
nnames = length(qualname);
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 */
/* 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 */
/* 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 */
/* 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 */
/* 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 */
/* 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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
{
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.
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 "
*
*
* 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
else
{
Oid namespaceId;
+ AclResult aclresult;
char *typname;
if (languageOid == SQLlanguageId)
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);
Oid languageOid;
char *funcname;
Oid namespaceId;
+ AclResult aclresult;
int parameterCount;
Oid parameterTypes[FUNC_MAX_ARGS];
int32 byte_pct,
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);
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);
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"
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
Oid *classObjectId;
Oid accessMethodId;
Oid relationId;
+ Oid namespaceId;
Relation rel;
HeapTuple tuple;
Form_pg_am accessMethodForm;
heapRelation->relname);
relationId = RelationGetRelid(rel);
+ namespaceId = RelationGetNamespace(rel);
if (!IsBootstrapProcessingMode() &&
IsSystemRelation(rel) &&
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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#include "commands/lockcmds.h"
#include "miscadmin.h"
#include "utils/acl.h"
+#include "utils/lsyscache.h"
/*
{
RangeVar *relation = lfirst(p);
Oid reloid;
- int32 aclresult;
+ AclResult aclresult;
Relation rel;
/*
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);
*
*
* 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
#include "parser/parse_oper.h"
#include "parser/parse_type.h"
#include "utils/acl.h"
+#include "utils/lsyscache.h"
#include "utils/syscache.h"
{
char *oprName;
Oid oprNamespace;
+ AclResult aclresult;
uint16 precedence = 0; /* operator precedence */
bool canHash = false; /* operator hashes */
bool canMerge = false; /* operator merges */
/* 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.
*/
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));
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#include "miscadmin.h"
#include "parser/analyze.h"
#include "tcop/utility.h"
+#include "utils/acl.h"
#include "utils/lsyscache.h"
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;
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);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* 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
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);
* 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.
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
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.
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
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
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
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
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)
{
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
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?)
* 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 $
*
*-------------------------------------------------------------------------
*/
Datum values[Natts_pg_trigger];
char nulls[Natts_pg_trigger];
Relation rel;
+ AclResult aclresult;
Relation tgrel;
SysScanDesc tgscan;
ScanKeyData key;
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
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
*
*
* 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
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
#include "utils/syscache.h"
{
char *typeName;
Oid typeNamespace;
+ AclResult aclresult;
int16 internalLength = -1; /* int2 */
int16 externalLength = -1; /* int2 */
Oid elemType = InvalidOid;
/* 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
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));
{
char *domainName;
Oid domainNamespace;
+ AclResult aclresult;
int16 internalLength;
int16 externalLength;
Oid inputProcedure;
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.
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;
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.158 2002/04/15 05:22:04 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.159 2002/04/27 03:45:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
{
Oid relOid;
Oid userid;
- int32 aclcheck_result;
+ AclResult aclcheck_result;
/*
* If it's a subquery RTE, ignore it --- it will be checked when
{
aclcheck_result = CHECK(ACL_SELECT);
if (aclcheck_result != ACLCHECK_OK)
- elog(ERROR, "%s: %s",
- get_rel_name(relOid),
- aclcheck_error_strings[aclcheck_result]);
+ aclcheck_error(aclcheck_result, get_rel_name(relOid));
}
if (rte->checkForWrite)
break;
}
if (aclcheck_result != ACLCHECK_OK)
- elog(ERROR, "%s: %s",
- get_rel_name(relOid),
- aclcheck_error_strings[aclcheck_result]);
+ aclcheck_error(aclcheck_result, get_rel_name(relOid));
}
}
if (!parseTree->isPortal)
{
/*
- * a select into table
+ * a select into table --- need to create the "into" table
*/
if (parseTree->into != NULL)
{
TupleDesc tupdesc;
/*
- * create the "into" relation
+ * find namespace to create in, check permissions
*/
intoName = parseTree->into->relname;
namespaceId = RangeVarGetCreationNamespace(parseTree->into);
+ if (!isTempNamespace(namespaceId))
+ {
+ AclResult aclresult;
+
+ aclresult = pg_namespace_aclcheck(namespaceId, GetUserId(),
+ ACL_CREATE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult,
+ get_namespace_name(namespaceId));
+ }
+
/*
* have to copy tupType to get rid of constraints
*/
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.90 2002/02/18 23:11:13 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.91 2002/04/27 03:45:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
bool hasSetArg;
int i;
- if (!fcache->permission_ok)
- elog(ERROR, "permission denied");
-
/*
* arguments is a list of expressions to evaluate before passing to
* the function manager. We skip the evaluation if it was already
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.68 2002/04/19 23:13:54 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.69 2002/04/27 03:45:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*event_qualP;
List *l;
Query *query;
- int32 aclcheck_result;
+ AclResult aclresult;
bool RelisBecomingView = false;
/*
/*
* 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]);
+ aclresult = pg_class_aclcheck(ev_relid, GetUserId(), ACL_RULE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, RelationGetRelationName(event_relation));
/*
* No rule actions that modify OLD or NEW
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.48 2002/04/18 20:01:09 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.49 2002/04/27 03:45:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
Oid ruleId;
Oid eventRelationOid;
bool hasMoreRules;
- int32 aclcheck_result;
+ AclResult aclresult;
/*
* Open the pg_rewrite relation.
/*
* 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]);
+ aclresult = pg_class_aclcheck(eventRelationOid, GetUserId(), ACL_RULE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, RelationGetRelationName(event_relation));
/* do not allow the removal of a view's SELECT rule */
if (event_relation->rd_rel->relkind == RELKIND_VIEW &&
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.151 2002/04/24 02:48:55 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.152 2002/04/27 03:45:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
if (classform->relkind != rightkind)
DropErrorMsg(rel->relname, classform->relkind, rightkind);
- if (!pg_class_ownercheck(relOid, GetUserId()))
- elog(ERROR, "you do not own %s \"%s\"",
- rentry->name, rel->relname);
+ /* Allow DROP to either table owner or schema owner */
+ if (!pg_class_ownercheck(relOid, GetUserId()) &&
+ !pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, rel->relname);
if (!allowSystemTableMods && IsSystemClass(classform))
elog(ERROR, "%s \"%s\" is a system %s",
elog(ERROR, "Relation \"%s\" does not exist", rel->relname);
if (!pg_class_ownercheck(relOid, GetUserId()))
- elog(ERROR, "%s: %s", rel->relname,
- aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
+ aclcheck_error(ACLCHECK_NOT_OWNER, rel->relname);
if (noCatalogs)
{
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.72 2002/04/26 01:24:08 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.73 2002/04/27 03:45:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
int32 usesysid;
Oid reloid;
AclMode mode;
- int32 aclresult;
+ AclResult aclresult;
/*
* Lookup userid based on username
int32 usesysid;
Oid reloid;
AclMode mode;
- int32 aclresult;
+ AclResult aclresult;
usesysid = GetUserId();
text *priv_type_text = PG_GETARG_TEXT_P(2);
int32 usesysid;
AclMode mode;
- int32 aclresult;
+ AclResult aclresult;
/*
* Lookup userid based on username
text *priv_type_text = PG_GETARG_TEXT_P(1);
int32 usesysid;
AclMode mode;
- int32 aclresult;
+ AclResult aclresult;
usesysid = GetUserId();
text *priv_type_text = PG_GETARG_TEXT_P(2);
Oid reloid;
AclMode mode;
- int32 aclresult;
+ AclResult aclresult;
/*
* Lookup rel OID based on relname
Oid reloid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
AclMode mode;
- int32 aclresult;
+ AclResult aclresult;
/*
* Convert priv_type_text to an AclMode
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.43 2002/04/21 00:26:43 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.44 2002/04/27 03:45:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "miscadmin.h"
#include "utils/acl.h"
#include "utils/fcache.h"
+#include "utils/lsyscache.h"
/*
init_fcache(Oid foid, int nargs, MemoryContext fcacheCxt)
{
FunctionCachePtr retval;
+ AclResult aclresult;
+
+ /* Check permission to call function */
+ aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, get_func_name(foid));
/* Safety check (should never fail, as parser should check sooner) */
if (nargs > FUNC_MAX_ARGS)
/* Initialize additional info */
retval->setArgsValid = false;
- retval->permission_ok = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE) == ACLCHECK_OK;
-
return retval;
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.70 2002/04/16 23:08:11 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.71 2002/04/27 03:45:03 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
/* ---------- FUNCTION CACHE ---------- */
+/*
+ * get_func_name
+ * returns the name of the function with the given funcid
+ *
+ * Note: returns a palloc'd copy of the string, or NULL if no such function.
+ */
+char *
+get_func_name(Oid funcid)
+{
+ HeapTuple tp;
+
+ tp = SearchSysCache(PROCOID,
+ ObjectIdGetDatum(funcid),
+ 0, 0, 0);
+ if (HeapTupleIsValid(tp))
+ {
+ Form_pg_proc functup = (Form_pg_proc) GETSTRUCT(tp);
+ char *result;
+
+ result = pstrdup(NameStr(functup->proname));
+ ReleaseSysCache(tp);
+ return result;
+ }
+ else
+ return NULL;
+}
+
/*
* get_func_rettype
* Given procedure id, return the function's result type.
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: acl.h,v 1.43 2002/04/21 00:26:44 tgl Exp $
+ * $Id: acl.h,v 1.44 2002/04/27 03:45:03 tgl Exp $
*
* NOTES
* For backward-compatibility purposes we have to allow there
/* result codes for pg_*_aclcheck */
-#define ACLCHECK_OK 0
-#define ACLCHECK_NO_PRIV 1
-#define ACLCHECK_NO_CLASS 2
-#define ACLCHECK_NOT_OWNER 3
-
-/* error messages (index by ACLCHECK_* result code). set in aclchk.c. */
-extern const char * const aclcheck_error_strings[];
+typedef enum
+{
+ ACLCHECK_OK = 0,
+ ACLCHECK_NO_PRIV,
+ ACLCHECK_NOT_OWNER
+} AclResult;
/*
* routines used internally
unsigned modechg);
/*
- * exported routines (from acl.c)
+ * SQL functions (from acl.c)
*/
extern Datum aclitemin(PG_FUNCTION_ARGS);
extern Datum aclitemout(PG_FUNCTION_ARGS);
extern AclId get_grosysid(char *groname);
extern char *get_groname(AclId grosysid);
-/* these return ACLCHECK_* result codes */
-extern int32 pg_class_aclcheck(Oid table_oid, Oid userid, AclMode mode);
-extern int32 pg_database_aclcheck(Oid db_oid, Oid userid, AclMode mode);
-extern int32 pg_proc_aclcheck(Oid proc_oid, Oid userid, AclMode mode);
-extern int32 pg_language_aclcheck(Oid lang_oid, Oid userid, AclMode mode);
-extern int32 pg_namespace_aclcheck(Oid nsp_oid, Oid userid, AclMode mode);
+extern AclResult pg_class_aclcheck(Oid table_oid, Oid userid, AclMode mode);
+extern AclResult pg_database_aclcheck(Oid db_oid, Oid userid, AclMode mode);
+extern AclResult pg_proc_aclcheck(Oid proc_oid, Oid userid, AclMode mode);
+extern AclResult pg_language_aclcheck(Oid lang_oid, Oid userid, AclMode mode);
+extern AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid userid, AclMode mode);
+
+extern void aclcheck_error(AclResult errcode, const char *objectname);
/* ownercheck routines just return true (owner) or false (not) */
extern bool pg_class_ownercheck(Oid class_oid, Oid userid);
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: fcache.h,v 1.21 2002/02/18 23:11:46 petere Exp $
+ * $Id: fcache.h,v 1.22 2002/04/27 03:45:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
*/
FmgrInfo func;
- bool permission_ok;
-
/*
* setArgsValid is true when we are evaluating a set-valued function
* and we are in the middle of a call series; we want to pass the same
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: lsyscache.h,v 1.49 2002/04/05 00:31:35 tgl Exp $
+ * $Id: lsyscache.h,v 1.50 2002/04/27 03:45:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern Oid get_negator(Oid opno);
extern RegProcedure get_oprrest(Oid opno);
extern RegProcedure get_oprjoin(Oid opno);
+extern char *get_func_name(Oid funcid);
extern Oid get_func_rettype(Oid funcid);
extern char func_volatile(Oid funcid);
extern Oid get_relname_relid(const char *relname, Oid relnamespace);
INSERT INTO atest1 VALUES (2, 'two'); -- ok
INSERT INTO atest2 VALUES ('foo', true); -- fail
-ERROR: atest2: Permission denied.
+ERROR: atest2: permission denied
INSERT INTO atest1 SELECT 1, b FROM atest1; -- ok
UPDATE atest1 SET a = 1 WHERE a = 2; -- ok
UPDATE atest2 SET col2 = NOT col2; -- fail
-ERROR: atest2: Permission denied.
+ERROR: atest2: permission denied
SELECT * FROM atest1 FOR UPDATE; -- ok
a | b
---+-----
(2 rows)
SELECT * FROM atest2 FOR UPDATE; -- fail
-ERROR: atest2: Permission denied.
+ERROR: atest2: permission denied
DELETE FROM atest2; -- fail
-ERROR: atest2: Permission denied.
+ERROR: atest2: permission denied
LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- fail
-ERROR: LOCK TABLE: permission denied
+ERROR: atest2: permission denied
COPY atest2 FROM stdin; -- fail
-ERROR: atest2: Permission denied.
+ERROR: atest2: permission denied
GRANT ALL ON atest1 TO PUBLIC; -- fail
-ERROR: atest1: permission denied
+ERROR: atest1: must be owner
-- checks in subquery, both ok
SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) );
a | b
(2 rows)
SELECT * FROM atest2; -- fail
-ERROR: atest2: Permission denied.
+ERROR: atest2: permission denied
INSERT INTO atest1 VALUES (2, 'two'); -- fail
-ERROR: atest1: Permission denied.
+ERROR: atest1: permission denied
INSERT INTO atest2 VALUES ('foo', true); -- fail
-ERROR: atest2: Permission denied.
+ERROR: atest2: permission denied
INSERT INTO atest1 SELECT 1, b FROM atest1; -- fail
-ERROR: atest1: Permission denied.
+ERROR: atest1: permission denied
UPDATE atest1 SET a = 1 WHERE a = 2; -- fail
-ERROR: atest1: Permission denied.
+ERROR: atest1: permission denied
UPDATE atest2 SET col2 = NULL; -- ok
UPDATE atest2 SET col2 = NOT col2; -- fails; requires SELECT on atest2
-ERROR: atest2: Permission denied.
+ERROR: atest2: permission denied
UPDATE atest2 SET col2 = true WHERE atest1.a = 5; -- ok
SELECT * FROM atest1 FOR UPDATE; -- fail
-ERROR: atest1: Permission denied.
+ERROR: atest1: permission denied
SELECT * FROM atest2 FOR UPDATE; -- fail
-ERROR: atest2: Permission denied.
+ERROR: atest2: permission denied
DELETE FROM atest2; -- fail
-ERROR: atest2: Permission denied.
+ERROR: atest2: permission denied
LOCK atest2 IN ACCESS EXCLUSIVE MODE; -- ok
COPY atest2 FROM stdin; -- fail
-ERROR: atest2: Permission denied.
+ERROR: atest2: permission denied
-- checks in subquery, both fail
SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) );
-ERROR: atest2: Permission denied.
+ERROR: atest2: permission denied
SELECT * FROM atest2 WHERE ( col1 IN ( SELECT b FROM atest1 ) );
-ERROR: atest2: Permission denied.
+ERROR: atest2: permission denied
SET SESSION AUTHORIZATION regressuser4;
COPY atest2 FROM stdin; -- ok
SELECT * FROM atest1; -- ok
GRANT DELETE ON atest3 TO GROUP regressgroup2;
SET SESSION AUTHORIZATION regressuser1;
SELECT * FROM atest3; -- fail
-ERROR: atest3: Permission denied.
+ERROR: atest3: permission denied
DELETE FROM atest3; -- ok
-- views
SET SESSION AUTHORIZATION regressuser3;
(1 row)
CREATE FUNCTION testfunc3(int) RETURNS int AS 'select 2 * $1;' LANGUAGE sql; -- fail
-ERROR: permission denied
+ERROR: sql: permission denied
SET SESSION AUTHORIZATION regressuser3;
SELECT testfunc1(5); -- fail
-ERROR: permission denied
+ERROR: testfunc1: permission denied
SET SESSION AUTHORIZATION regressuser4;
SELECT testfunc1(5); -- ok
testfunc1
(1 row)
DROP FUNCTION testfunc1(int); -- fail
-ERROR: RemoveFunction: function 'testfunc1': permission denied
+ERROR: testfunc1: must be owner
\c -
DROP FUNCTION testfunc1(int); -- ok
-- restore to sanity