Change the aclchk.c routines to uniformly use OIDs to identify the
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 21 Mar 2002 23:27:25 +0000 (23:27 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 21 Mar 2002 23:27:25 +0000 (23:27 +0000)
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.

22 files changed:
src/backend/catalog/aclchk.c
src/backend/commands/analyze.c
src/backend/commands/command.c
src/backend/commands/comment.c
src/backend/commands/copy.c
src/backend/commands/creatinh.c
src/backend/commands/remove.c
src/backend/commands/rename.c
src/backend/commands/sequence.c
src/backend/commands/trigger.c
src/backend/commands/vacuum.c
src/backend/executor/execMain.c
src/backend/rewrite/rewriteDefine.c
src/backend/rewrite/rewriteRemove.c
src/backend/tcop/utility.c
src/backend/utils/adt/acl.c
src/backend/utils/cache/syscache.c
src/include/rewrite/rewriteRemove.h
src/include/utils/acl.h
src/include/utils/syscache.h
src/test/regress/expected/errors.out
src/test/regress/expected/privileges.out

index 2244827f7c4ec39f0e0ddeac0b944c00dfd89436..2225dc3a14ef6465dfa7e36e5087d21132092cb1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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
  *   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);
 
 /* warning messages, now more explicit. */
-/* MUST correspond to the order of the ACLCHK_* result codes in acl.h. */
-char      *aclcheck_error_strings[] = {
+/* 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.",
@@ -66,11 +66,11 @@ dumpacl(Acl *acl)
    int         i;
    AclItem    *aip;
 
-   elog(LOG, "acl size = %d, # acls = %d",
+   elog(DEBUG1, "acl size = %d, # acls = %d",
         ACL_SIZE(acl), ACL_NUM(acl));
    aip = ACL_DAT(acl);
    for (i = 0; i < ACL_NUM(acl); ++i)
-       elog(LOG, " acl[%d]: %s", i,
+       elog(DEBUG1, "  acl[%d]: %s", i,
             DatumGetCString(DirectFunctionCall1(aclitemout,
                                             PointerGetDatum(aip + i))));
 }
@@ -214,23 +214,20 @@ ExecuteGrantStmt_Table(GrantStmt *stmt)
        char        nulls[Natts_pg_class];
        char        replaces[Natts_pg_class];
 
-
-       if (!pg_ownercheck(GetUserId(), relname, RELNAME))
-           elog(ERROR, "permission denied");
-
        /* open pg_class */
        relation = heap_openr(RelationRelationName, RowExclusiveLock);
        tuple = SearchSysCache(RELNAME,
                               PointerGetDatum(relname),
                               0, 0, 0);
        if (!HeapTupleIsValid(tuple))
-       {
-           heap_close(relation, RowExclusiveLock);
            elog(ERROR, "relation \"%s\" not found",
                 relname);
-       }
        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)
            elog(ERROR, "\"%s\" is an index",
                 relname);
@@ -658,7 +655,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
     */
    if (!acl)
    {
-       elog(LOG, "aclcheck: null ACL, returning OK");
+       elog(DEBUG1, "aclcheck: null ACL, returning OK");
        return ACLCHECK_OK;
    }
 
@@ -673,7 +670,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
     */
    if (num < 1)
    {
-       elog(LOG, "aclcheck: zero-length ACL, returning OK");
+       elog(DEBUG1, "aclcheck: zero-length ACL, returning OK");
        return ACLCHECK_OK;
    }
 
@@ -686,7 +683,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
    if (aidat->ai_mode & mode)
    {
 #ifdef ACLDEBUG
-       elog(LOG, "aclcheck: using world=%d", aidat->ai_mode);
+       elog(DEBUG1, "aclcheck: using world=%d", aidat->ai_mode);
 #endif
        return ACLCHECK_OK;
    }
@@ -702,7 +699,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
                if (aip->ai_id == id)
                {
 #ifdef ACLDEBUG
-                   elog(LOG, "aclcheck: found user %u/%d",
+                   elog(DEBUG1, "aclcheck: found user %u/%d",
                         aip->ai_id, aip->ai_mode);
 #endif
                    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))
                    {
 #ifdef ACLDEBUG
-                       elog(LOG, "aclcheck: found group %u/%d",
+                       elog(DEBUG1, "aclcheck: found group %u/%d",
                             aip->ai_id, aip->ai_mode);
 #endif
                        return ACLCHECK_OK;
@@ -740,7 +737,7 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
                if (aip->ai_id == id)
                {
 #ifdef ACLDEBUG
-                   elog(LOG, "aclcheck: found group %u/%d",
+                   elog(DEBUG1, "aclcheck: found group %u/%d",
                         aip->ai_id, aip->ai_mode);
 #endif
                    if (aip->ai_mode & mode)
@@ -760,46 +757,63 @@ aclcheck(Acl *acl, AclId id, AclIdType idtype, AclMode mode)
    return ACLCHECK_NO_PRIV;
 }
 
+
 /*
  * Exported routine for checking a user's access privileges to a table
  *
  * Returns an ACLCHECK_* result code.
  */
 int32
-pg_aclcheck(char *relname, Oid userid, AclMode mode)
+pg_class_aclcheck(Oid table_oid, Oid userid, AclMode mode)
 {
    int32       result;
+   bool        usesuper,
+               usecatupd;
+   char       *relname;
    HeapTuple   tuple;
-   char       *usename;
    Datum       aclDatum;
    bool        isNull;
    Acl        *acl;
 
    /*
     * 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,
                           ObjectIdGetDatum(userid),
                           0, 0, 0);
    if (!HeapTupleIsValid(tuple))
-       elog(ERROR, "pg_aclcheck: invalid user id %u",
-            (unsigned) userid);
+       elog(ERROR, "pg_class_aclcheck: invalid user id %u", 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
     * pg_shadow.usecatupd is set.  (This is to let superusers protect
     * themselves from themselves.)
     */
+   relname = NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname);
    if ((mode & (ACL_INSERT | ACL_UPDATE | ACL_DELETE)) &&
        !allowSystemTableMods && IsSystemRelationName(relname) &&
        !is_temp_relname(relname) &&
-       !((Form_pg_shadow) GETSTRUCT(tuple))->usecatupd)
+       !usecatupd)
    {
 #ifdef ACLDEBUG
-       elog(LOG, "pg_aclcheck: catalog update to \"%s\": permission denied",
-            relname);
+       elog(DEBUG1, "pg_class_aclcheck: catalog update: permission denied");
 #endif
        ReleaseSysCache(tuple);
        return ACLCHECK_NO_PRIV;
@@ -808,29 +822,19 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode)
    /*
     * Otherwise, superusers bypass all permission-checking.
     */
-   if (((Form_pg_shadow) GETSTRUCT(tuple))->usesuper)
+   if (usesuper)
    {
 #ifdef ACLDEBUG
-       elog(LOG, "pg_aclcheck: \"%s\" is superuser",
-            usename);
+       elog(DEBUG1, "pg_class_aclcheck: %u is superuser", userid);
 #endif
        ReleaseSysCache(tuple);
        return ACLCHECK_OK;
    }
 
-   ReleaseSysCache(tuple);
-   /* caution: usename is inaccessible beyond this point... */
-
    /*
     * Normal case: get the relation's ACL from pg_class
     */
-   tuple = SearchSysCache(RELNAME,
-                          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,
+   aclDatum = SysCacheGetAttr(RELOID, tuple, Anum_pg_class_relacl,
                               &isNull);
    if (isNull)
    {
@@ -858,227 +862,6 @@ pg_aclcheck(char *relname, Oid userid, AclMode mode)
    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
  *
@@ -1093,22 +876,12 @@ pg_proc_aclcheck(Oid proc_oid, Oid userid)
    bool        isNull;
    Acl        *acl;
 
+   /* Superusers bypass all permission checking. */
    if (superuser_arg(userid))
        return ACLCHECK_OK;
 
    /*
-    * Validate userid
-    */
-   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
+    * Get the function's ACL from pg_proc
     */
    tuple = SearchSysCache(PROCOID,
                           ObjectIdGetDatum(proc_oid),
@@ -1148,8 +921,6 @@ pg_proc_aclcheck(Oid proc_oid, Oid userid)
    return result;
 }
 
-
-
 /*
  * 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;
    Acl        *acl;
 
+   /* Superusers bypass all permission checking. */
    if (superuser_arg(userid))
        return ACLCHECK_OK;
 
    /*
-    * Validate userid
-    */
-   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
+    * Get the function's ACL from pg_language
     */
    tuple = SearchSysCache(LANGOID,
                           ObjectIdGetDatum(lang_oid),
@@ -1215,3 +976,134 @@ pg_language_aclcheck(Oid lang_oid, Oid userid)
 
    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;
+}
index d033fa950542c2f7959a7504a1e42246f58a36d3..df9735089aab470a10a334753db3e7d12649c586 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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);
 
-   if (!(pg_ownercheck(GetUserId(), RelationGetRelationName(onerel),
-                       RELNAME) ||
+   if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) ||
          (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared)))
    {
        /* No need for a WARNING if we already complained during VACUUM */
index 5821e1d10366acc1ca49b77e12ea0abe1dc1ed5f..31df6cabd77ccbedabe39c3665cd0a11d3ccd3b3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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
  *   The PerformAddAttribute() code, like most of the relation
@@ -327,6 +327,17 @@ AlterTableAddColumn(const char *relationName,
    char       *typename;
    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,
     * but this particular routine is recursive.
@@ -336,20 +347,9 @@ AlterTableAddColumn(const char *relationName,
    if (!allowSystemTableMods && IsSystemRelationName(relationName))
        elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
             relationName);
-   if (!pg_ownercheck(GetUserId(), relationName, RELNAME))
+   if (!pg_class_ownercheck(myrelid, GetUserId()))
        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! */
 
    /*
@@ -556,21 +556,19 @@ AlterTableAlterColumnDefault(const char *relationName,
    int16       attnum;
    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);
+   myrelid = RelationGetRelid(rel);
 
    if (rel->rd_rel->relkind != RELKIND_RELATION)
        elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
             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);
 
    /*
@@ -730,24 +728,21 @@ AlterTableAlterColumnFlags(const char *relationName,
    Relation    attrelation;
    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);
+   myrelid = RelationGetRelid(rel);
 
    if (rel->rd_rel->relkind != RELKIND_RELATION)
        elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
             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! */
 
 
@@ -1034,6 +1029,17 @@ AlterTableDropColumn(const char *relationName,
    if (inh)
        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,
     * but this particular routine is recursive.
@@ -1043,22 +1049,9 @@ AlterTableDropColumn(const char *relationName,
    if (!allowSystemTableMods && IsSystemRelationName(relationName))
        elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
             relationName);
-#ifndef NO_SECURITY
-   if (!pg_ownercheck(GetUserId(), relationName, RELNAME))
+   if (!pg_class_ownercheck(myrelid, GetUserId()))
        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! */
 
    /*
@@ -1180,25 +1173,22 @@ AlterTableAddConstraint(char *relationName,
    Oid         myrelid;
    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
     * 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);
 
-   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)
    {
@@ -1496,16 +1486,9 @@ AlterTableDropConstraint(const char *relationName,
                         int behavior)
 {
    Relation    rel;
+   Oid         myrelid;
    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
     * the spec either!
@@ -1517,14 +1500,20 @@ AlterTableDropConstraint(const char *relationName,
     * Acquire an exclusive lock on the target relation for the duration
     * of the operation.
     */
-
    rel = heap_openr(relationName, AccessExclusiveLock);
+   myrelid = RelationGetRelid(rel);
 
    /* Disallow DROP CONSTRAINT on views, indexes, sequences, etc */
    if (rel->rd_rel->relkind != RELKIND_RELATION)
        elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
             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
     * through all catalogs that could possibly contain a constraint for
@@ -1692,25 +1681,19 @@ AlterTableCreateToastTable(const char *relationName, bool silent)
    IndexInfo  *indexInfo;
    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
     * 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);
 
-   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?)
@@ -1940,20 +1923,32 @@ LockTableCommand(LockStmt *lockstmt)
    {
        RangeVar   *relation = lfirst(p);
        char       *relname = relation->relname;
+       Oid         reloid;
        int         aclresult;
        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)
-           aclresult = pg_aclcheck(relname, GetUserId(),
-                                   ACL_SELECT);
+           aclresult = pg_class_aclcheck(reloid, GetUserId(),
+                                         ACL_SELECT);
        else
-           aclresult = pg_aclcheck(relname, GetUserId(),
-                                   ACL_UPDATE | ACL_DELETE);
+           aclresult = pg_class_aclcheck(reloid, GetUserId(),
+                                         ACL_UPDATE | ACL_DELETE);
 
        if (aclresult != ACLCHECK_OK)
            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 */
        if (rel->rd_rel->relkind != RELKIND_RELATION)
index baeff0c172d240032826b5b81f269a74ad59b8c4..4ad49581629c3acc67151959959323192a62ad81 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 1999-2001, PostgreSQL Global Development Group
  *
  * 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_description.h"
 #include "catalog/pg_operator.h"
+#include "catalog/pg_rewrite.h"
 #include "catalog/pg_trigger.h"
 #include "catalog/pg_type.h"
 #include "commands/comment.h"
@@ -326,11 +327,6 @@ CommentRelation(int reltype, char *relname, char *comment)
 {
    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
     * 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);
 
+   /* 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 */
 
    switch (reltype)
@@ -387,15 +387,15 @@ CommentAttribute(char *relname, char *attrname, char *comment)
    Relation    relation;
    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 */
 
    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 */
 
    attnum = get_attnum(RelationGetRelid(relation), attrname);
@@ -476,27 +476,32 @@ CommentDatabase(char *database, char *comment)
 static void
 CommentRewrite(char *rule, char *comment)
 {
-   Oid         oid;
+   HeapTuple   tuple;
+   Oid         reloid;
+   Oid         ruleoid;
    Oid         classoid;
-   char       *relation;
-   int         aclcheck;
+   int32       aclcheck;
+
+   /* Find the rule's pg_rewrite tuple, get its OID and its table's OID */
+
+   tuple = SearchSysCache(RULENAME,
+                          PointerGetDatum(rule),
+                          0, 0, 0);
+   if (!HeapTupleIsValid(tuple))
+       elog(ERROR, "rule '%s' does not exist", rule);
+
+   reloid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
+   ruleoid = tuple->t_data->t_oid;
 
-   /* First, validate user */
+   ReleaseSysCache(tuple);
 
-   relation = RewriteGetRuleEventRel(rule);
-   aclcheck = pg_aclcheck(relation, GetUserId(), ACL_RULE);
+   /* Check object security */
+
+   aclcheck = pg_class_aclcheck(reloid, GetUserId(), ACL_RULE);
    if (aclcheck != ACLCHECK_OK)
        elog(ERROR, "you are not permitted to comment on rule '%s'",
             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 */
 
    classoid = GetSysCacheOid(RELNAME,
@@ -506,7 +511,7 @@ CommentRewrite(char *rule, char *comment)
 
    /* 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;
 
-   /* First, validate user */
-
-   if (!pg_ownercheck(GetUserId(), type, TYPENAME))
-       elog(ERROR, "you are not permitted to comment on type '%s'",
-            type);
-
-   /* Next, find the type's oid */
+   /* Find the type's oid */
 
    oid = GetSysCacheOid(TYPENAME,
                         PointerGetDatum(type),
@@ -539,6 +538,12 @@ CommentType(char *type, char *comment)
    if (!OidIsValid(oid))
        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 */
 
    CreateComments(oid, RelOid_pg_type, 0, comment);
@@ -576,9 +581,18 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
    else
        baseoid = InvalidOid;
 
+   /* Now, attempt to find the actual tuple in pg_aggregate */
+
+   oid = GetSysCacheOid(AGGNAME,
+                        PointerGetDatum(aggregate),
+                        ObjectIdGetDatum(baseoid),
+                        0, 0);
+   if (!OidIsValid(oid))
+       agg_error("CommentAggregate", aggregate, baseoid);
+
    /* Next, validate the user's attempt to comment */
 
-   if (!pg_aggr_ownercheck(GetUserId(), aggregate, baseoid))
+   if (!pg_aggr_ownercheck(oid, GetUserId()))
    {
        if (baseoid == InvalidOid)
            elog(ERROR, "you are not permitted to comment on aggregate '%s' for all types",
@@ -588,15 +602,6 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
                 aggregate, format_type_be(baseoid));
    }
 
-   /* Now, attempt to find the actual tuple in pg_aggregate */
-
-   oid = GetSysCacheOid(AGGNAME,
-                        PointerGetDatum(aggregate),
-                        ObjectIdGetDatum(baseoid),
-                        0, 0);
-   if (!OidIsValid(oid))
-       agg_error("CommentAggregate", aggregate, baseoid);
-
    /* pg_aggregate doesn't have a hard-coded OID, so must look it up */
 
    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 */
 
    oid = GetSysCacheOid(PROCNAME,
@@ -670,6 +669,12 @@ CommentProc(char *function, List *arguments, char *comment)
    if (!OidIsValid(oid))
        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 */
 
    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 */
 
-   if (!pg_oper_ownercheck(GetUserId(), oid))
+   if (!pg_oper_ownercheck(oid, GetUserId()))
        elog(ERROR, "you are not permitted to comment on operator '%s'",
             opername);
 
@@ -798,13 +803,14 @@ CommentTrigger(char *trigger, char *relname, char *comment)
 
    /* 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'",
             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);
    ScanKeyEntryInitialize(&entry[0], 0x0, Anum_pg_trigger_tgrelid,
                           F_OIDEQ,
index 541f3d0a484d3ed1de8978d106bb46728801e372..fc4f80468cdd6db2b953c294b8e468fd9af87ddd 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * 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;
    Relation    rel;
    const AclMode required_access = (from ? ACL_INSERT : ACL_SELECT);
-   int         result;
+   int32       aclresult;
 
    /*
     * Open and lock the relation, using the appropriate lock type.
     */
    rel = heap_openr(relname, (from ? RowExclusiveLock : AccessShareLock));
 
-   result = pg_aclcheck(relname, GetUserId(), required_access);
-   if (result != ACLCHECK_OK)
-       elog(ERROR, "%s: %s", relname, aclcheck_error_strings[result]);
+   /* Check permissions. */
+   aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
+                                 required_access);
+   if (aclresult != ACLCHECK_OK)
+       elog(ERROR, "%s: %s",
+            RelationGetRelationName(rel),
+            aclcheck_error_strings[aclresult]);
    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 "
index 04854a2afa1a481bb933d1564e6d4e4e36eca0d8..91f5d14a37a591f0f1c26866dbd5acd4fb93e15b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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);
 
-   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 */
    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",
             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 */
    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,
         * 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);
 
        parentOids = lappendi(parentOids, relation->rd_id);
index 99b243ed4fdf9f2cfe8266ff5fd6f73c5d72f095..0dbadd95779e1b8257ca7eeebee26fcc226537ef 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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 (!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",
                 operatorName);
 
@@ -92,7 +92,6 @@ RemoveOperator(char *operatorName,        /* operator name */
        DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
 
        simple_heap_delete(relation, &tup->t_self);
-
    }
    else
    {
@@ -242,10 +241,6 @@ RemoveType(char *typeName)     /* type name to be removed */
    HeapTuple   tup;
    char       *shadow_type;
 
-   if (!pg_ownercheck(GetUserId(), typeName, TYPENAME))
-       elog(ERROR, "RemoveType: type '%s': permission denied",
-            typeName);
-
    relation = heap_openr(TypeRelationName, RowExclusiveLock);
 
    tup = SearchSysCache(TYPENAME,
@@ -254,6 +249,10 @@ RemoveType(char *typeName)     /* type name to be removed */
    if (!HeapTupleIsValid(tup))
        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 */
    DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
 
@@ -288,10 +287,9 @@ RemoveDomain(char *domainName, int behavior)
    HeapTuple   tup;
    char        typtype;
 
-   /* Domains are stored as types.  Check for permissions on the type */
-   if (!pg_ownercheck(GetUserId(), domainName, TYPENAME))
-       elog(ERROR, "RemoveDomain: type '%s': permission denied",
-            domainName);
+   /* CASCADE unsupported */
+   if (behavior == CASCADE)
+       elog(ERROR, "DROP DOMAIN does not support the CASCADE keyword");
 
    relation = heap_openr(TypeRelationName, RowExclusiveLock);
 
@@ -301,17 +299,16 @@ RemoveDomain(char *domainName, int behavior)
    if (!HeapTupleIsValid(tup))
        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 */
    typtype = ((Form_pg_type) GETSTRUCT(tup))->typtype;
 
    if (typtype != 'd')
        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 */
    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);
 
    tup = SearchSysCache(PROCNAME,
@@ -381,6 +372,10 @@ RemoveFunction(char *functionName,     /* function name to be removed */
    if (!HeapTupleIsValid(tup))
        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)
    {
        /* "Helpful" WARNING when removing a builtin function ... */
@@ -423,16 +418,6 @@ RemoveAggregate(char *aggName, char *aggType)
    else
        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);
 
    tup = SearchSysCache(AGGNAME,
@@ -443,6 +428,16 @@ RemoveAggregate(char *aggName, char *aggType)
    if (!HeapTupleIsValid(tup))
        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 */
    DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
 
index 308808c220232d308a32858c2d6e0f49463af3c0..0ce475303a7c0092c378fbe1339833106d814bf1 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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       *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,
     * but this particular routine is recursive.
@@ -90,18 +97,10 @@ renameatt(char *relname,
    if (!allowSystemTableMods && IsSystemRelationName(relname))
        elog(ERROR, "renameatt: class \"%s\" is a system catalog",
             relname);
-   if (!IsBootstrapProcessingMode() &&
-       !pg_ownercheck(GetUserId(), relname, RELNAME))
+   if (!pg_class_ownercheck(relid, GetUserId()))
        elog(ERROR, "renameatt: you do not own class \"%s\"",
             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
     * attribute in all classes that inherit from 'relname' (as well as in
index e9df6392bc083591565d106dd0f4c4f70f80adb4..5bcf4f8232794d1484168480f32bf7a0500084f0 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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;
    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 */
    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);
 
    if (elm->last != elm->cached)       /* some numbers were cached */
@@ -466,13 +466,13 @@ currval(PG_FUNCTION_ARGS)
    SeqTable    elm;
    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 */
    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 */
        elog(ERROR, "%s.currval is not yet defined in this session",
             seqname);
@@ -504,14 +504,15 @@ do_setval(char *seqname, int64 next, bool iscalled)
    Buffer      buf;
    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",
             seqname, seqname);
 
-   /* open and AccessShareLock sequence */
-   elm = init_sequence("setval", seqname);
-   seq = read_info("setval", elm, &buf);       /* lock page' buffer and
-                                                * read tuple */
+   /* lock page' buffer and read tuple */
+   seq = read_info("setval", elm, &buf);
 
    if ((next < seq->min_value) || (next > seq->max_value))
        elog(ERROR, "%s.setval: value " INT64_FORMAT " is out of bounds (" INT64_FORMAT "," INT64_FORMAT ")",
index 5bef86e30610ce1f69a01242c4e5cf8c63f632cc..2fa17612e37616c05a4b90720f49b7874703bd89 100644 (file)
@@ -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.106 2002/03/21 16:00:34 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.107 2002/03/21 23:27:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -71,12 +71,18 @@ CreateTrigger(CreateTrigStmt *stmt)
    char       *constrname = "";
    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))
        elog(ERROR, "CreateTrigger: can't create trigger for system relation %s",
            stmt->relation->relname);
 
-   if (pg_aclcheck(stmt->relation->relname, GetUserId(),
-                   stmt->isconstraint ? ACL_REFERENCES : ACL_TRIGGER)
+   if (pg_class_aclcheck(RelationGetRelid(rel), GetUserId(),
+                         stmt->isconstraint ? ACL_REFERENCES : ACL_TRIGGER)
        != ACLCHECK_OK)
        elog(ERROR, "permission denied");
 
@@ -98,18 +104,14 @@ CreateTrigger(CreateTrigStmt *stmt)
             * NoLock is probably sufficient here, since we're only
             * interested in getting the relation's OID...
             */
-           rel = heap_openr(stmt->constrrel->relname, NoLock);
-           constrrelid = rel->rd_id;
-           heap_close(rel, NoLock);
+           Relation    conrel;
+
+           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);
    if (stmt->before)
        TRIGGER_SETT_BEFORE(tgtype);
@@ -321,20 +323,20 @@ DropTrigger(DropTrigStmt *stmt)
    int         found = 0;
    int         tgfound = 0;
 
+   rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
+
+   if (rel->rd_rel->relkind != RELKIND_RELATION)
+       elog(ERROR, "DropTrigger: relation \"%s\" is not a table",
+            stmt->relation->relname);
+
    if (!allowSystemTableMods && IsSystemRelationName(stmt->relation->relname))
        elog(ERROR, "DropTrigger: can't drop trigger for system relation %s",
             stmt->relation->relname);
 
-   if (!pg_ownercheck(GetUserId(), stmt->relation->relname, RELNAME))
+   if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId()))
        elog(ERROR, "%s: %s", stmt->relation->relname,
             aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
 
-   rel = heap_openr(stmt->relation->relname, AccessExclusiveLock);
-
-   if (rel->rd_rel->relkind != RELKIND_RELATION)
-       elog(ERROR, "DropTrigger: relation \"%s\" is not a table",
-            stmt->relation->relname);
-
    /*
     * Search pg_trigger, delete target trigger, count remaining triggers
     * for relation.  Note this is OK only because we have
index 836091c583f45224f2834e0079ad666006e48733..41405f3654a9220c0d27f3a88d8843fdae2d9104 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * 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
     * 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
     * trying to vacuum the rest of the DB --- is this appropriate?
     */
    onerel = heap_open(relid, lmode);
 
-   if (!(pg_ownercheck(GetUserId(), RelationGetRelationName(onerel),
-                       RELNAME) ||
+   if (!(pg_class_ownercheck(RelationGetRelid(onerel), GetUserId()) ||
          (is_dbadmin(MyDatabaseId) && !onerel->rd_rel->relisshared)))
    {
        elog(WARNING, "Skipping \"%s\" --- only table or database owner can VACUUM it",
index 9b8e3586024178765e8ff7621f941193d882b713..8532da15975a3ab22f9b6a95c3ba1300b7b31046 100644 (file)
@@ -27,7 +27,7 @@
  *
  *
  * 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 "parser/parsetree.h"
 #include "utils/acl.h"
+#include "utils/lsyscache.h"
 
 
 /* decls for local routines only used within this module */
@@ -355,7 +356,7 @@ ExecCheckRTPerms(List *rangeTable, CmdType operation)
 static void
 ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
 {
-   char       *relName;
+   Oid         relOid;
    Oid         userid;
    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
     * ExecCheckPlanPerms finds the SubqueryScan node for it.
     */
-   if (rte->subquery)
+   if (rte->rtekind != RTE_RELATION)
        return;
 
-   relName = rte->relname;
+   relOid = rte->relid;
 
    /*
     * 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();
 
-#define CHECK(MODE)        pg_aclcheck(relName, userid, MODE)
+#define CHECK(MODE)        pg_class_aclcheck(relOid, userid, MODE)
 
    if (rte->checkForRead)
    {
        aclcheck_result = CHECK(ACL_SELECT);
        if (aclcheck_result != ACLCHECK_OK)
            elog(ERROR, "%s: %s",
-                relName, aclcheck_error_strings[aclcheck_result]);
+                get_rel_name(relOid),
+                aclcheck_error_strings[aclcheck_result]);
    }
 
    if (rte->checkForWrite)
@@ -416,7 +418,8 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
        }
        if (aclcheck_result != ACLCHECK_OK)
            elog(ERROR, "%s: %s",
-                relName, aclcheck_error_strings[aclcheck_result]);
+                get_rel_name(relOid),
+                aclcheck_error_strings[aclcheck_result]);
    }
 }
 
index 0b47aa9c924593f07d064566102d384c5929651e..7e9f0fcfbb350e7113f15364db23f351fab2e2df 100644 (file)
@@ -8,11 +8,10 @@
  *
  *
  * 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 "access/heapam.h"
@@ -27,6 +26,7 @@
 #include "rewrite/rewriteManip.h"
 #include "rewrite/rewriteSupport.h"
 #include "storage/smgr.h"
+#include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/syscache.h"
 
@@ -127,6 +127,7 @@ DefineQueryRewrite(RuleStmt *stmt)
               *event_qualP;
    List       *l;
    Query      *query;
+   int32       aclcheck_result;
    bool        RelisBecomingView = false;
 
    /*
@@ -140,6 +141,15 @@ DefineQueryRewrite(RuleStmt *stmt)
    event_relation = heap_openr(event_obj->relname, AccessExclusiveLock);
    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
     */
index 92326d93b6dc8ccf8e8936f12ac0f579ae51f729..6d251b78343416bcd01164c62ab0d6fb552c113a 100644 (file)
@@ -8,12 +8,10 @@
  *
  *
  * 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 "utils/builtins.h"
 #include "catalog/catname.h"
 #include "catalog/pg_rewrite.h"
 #include "commands/comment.h"
+#include "miscadmin.h"
 #include "rewrite/rewriteRemove.h"
 #include "rewrite/rewriteSupport.h"
+#include "utils/acl.h"
 #include "utils/fmgroids.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
@@ -71,6 +41,7 @@ RemoveRewriteRule(char *ruleName)
    Oid         ruleId;
    Oid         eventRelationOid;
    bool        hasMoreRules;
+   int32       aclcheck_result;
 
    /*
     * Open the pg_rewrite relation.
@@ -88,10 +59,7 @@ RemoveRewriteRule(char *ruleName)
     * complain if no rule with such name existed
     */
    if (!HeapTupleIsValid(tuple))
-   {
-       heap_close(RewriteRelation, RowExclusiveLock);
        elog(ERROR, "Rule \"%s\" not found", ruleName);
-   }
 
    /*
     * 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);
 
+   /*
+    * 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 */
    if (event_relation->rd_rel->relkind == RELKIND_VIEW &&
        ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_type == '1')
index 9a6813635cac0e1771bb920d3937ef80acfde837..1f0046887f429a3a250b46c1431cf5bb337338a9 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * 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)
        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\"",
             rentry->name, name);
 
@@ -128,6 +128,31 @@ CheckDropPermissions(char *name, char rightkind)
    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
@@ -149,7 +174,6 @@ ProcessUtility(Node *parsetree,
               char *completionTag)
 {
    char       *relname;
-   char       *relationName;
 
    if (completionTag)
        completionTag[0] = '\0';
@@ -271,17 +295,8 @@ ProcessUtility(Node *parsetree,
                            break;
 
                        case DROP_RULE:
-                           {
-                               char       *rulename = 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);
-                           }
+                           /* RemoveRewriteRule checks permissions */
+                           RemoveRewriteRule(relname);
                            break;
 
                        case DROP_TYPE:
@@ -355,11 +370,7 @@ ProcessUtility(Node *parsetree,
                RenameStmt *stmt = (RenameStmt *) parsetree;
 
                relname = stmt->relation->relname;
-               if (!allowSystemTableMods && IsSystemRelationName(relname))
-                   elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
-                        relname);
-               if (!pg_ownercheck(GetUserId(), relname, RELNAME))
-                   elog(ERROR, "permission denied");
+               CheckOwnership(relname, true);
 
                /* ----------------
                 *  XXX using len == 3 to tell the difference
@@ -509,11 +520,7 @@ ProcessUtility(Node *parsetree,
                IndexStmt  *stmt = (IndexStmt *) parsetree;
 
                relname = stmt->relation->relname;
-               if (!allowSystemTableMods && IsSystemRelationName(relname))
-                   elog(ERROR, "CREATE INDEX: relation \"%s\" is a system catalog",
-                        relname);
-               if (!pg_ownercheck(GetUserId(), relname, RELNAME))
-                   elog(ERROR, "permission denied");
+               CheckOwnership(relname, true);
 
                DefineIndex(stmt->relation->relname,    /* relation */
                            stmt->idxname,              /* index name */
@@ -527,17 +534,7 @@ ProcessUtility(Node *parsetree,
            break;
 
        case T_RuleStmt:        /* CREATE RULE */
-           {
-               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);
-           }
+           DefineQueryRewrite((RuleStmt *) parsetree);
            break;
 
        case T_CreateSeqStmt:
@@ -646,11 +643,7 @@ ProcessUtility(Node *parsetree,
                ClusterStmt *stmt = (ClusterStmt *) parsetree;
 
                relname = stmt->relation->relname;
-               if (IsSystemRelationName(relname))
-                   elog(ERROR, "CLUSTER: relation \"%s\" is a system catalog",
-                        relname);
-               if (!pg_ownercheck(GetUserId(), relname, RELNAME))
-                   elog(ERROR, "permission denied");
+               CheckOwnership(relname, true);
 
                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",
                                     relname);
                        }
-                       if (!pg_ownercheck(GetUserId(), relname, RELNAME))
-                           elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
+                       CheckOwnership(relname, false);
                        ReindexIndex(relname, stmt->force);
                        break;
                    case TABLE:
                        relname = (char *) stmt->relation->relname;
-                       if (!pg_ownercheck(GetUserId(), relname, RELNAME))
-                           elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
+                       CheckOwnership(relname, false);
                        ReindexTable(relname, stmt->force);
                        break;
                    case DATABASE:
index f868b36861d8260f3e54dc206144b544f3868c84..0e73cb04b10d7504a4e803b937c9387ce24201b2 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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);
    text       *priv_type_text = PG_GETARG_TEXT_P(1);
-   char       *relname;
    int32       usesysid;
    AclMode     mode;
    int32       result;
 
    usesysid = GetUserId();
 
-   /*
-    * Lookup relname based on rel oid
-    */
-   relname = get_rel_name(reloid);
-   if (relname == NULL)
-       elog(ERROR, "has_table_privilege: invalid relation oid %u",
-            reloid);
-
    /*
     * Convert priv_type_text to an AclMode
     */
    mode = convert_priv_string(priv_type_text);
 
    /*
-    * Finally, check for the privilege
+    * Check for the privilege
     */
-   result = pg_aclcheck(relname, usesysid, mode);
+   result = pg_class_aclcheck(reloid, usesysid, mode);
 
    if (result == ACLCHECK_OK)
        PG_RETURN_BOOL(true);
@@ -891,27 +882,18 @@ has_table_privilege_id_id(PG_FUNCTION_ARGS)
    int32       usesysid = PG_GETARG_INT32(0);
    Oid         reloid = PG_GETARG_OID(1);
    text       *priv_type_text = PG_GETARG_TEXT_P(2);
-   char       *relname;
    AclMode     mode;
    int32       result;
 
-   /*
-    * Lookup relname based on rel oid
-    */
-   relname = get_rel_name(reloid);
-   if (relname == NULL)
-       elog(ERROR, "has_table_privilege: invalid relation oid %u",
-            reloid);
-
    /*
     * Convert priv_type_text to an AclMode
     */
    mode = convert_priv_string(priv_type_text);
 
    /*
-    * Finally, check for the privilege
+    * Check for the privilege
     */
-   result = pg_aclcheck(relname, usesysid, mode);
+   result = pg_class_aclcheck(reloid, usesysid, mode);
 
    if (result == ACLCHECK_OK)
        PG_RETURN_BOOL(true);
@@ -1050,22 +1032,19 @@ static bool
 has_table_privilege_id_cname(int32 usesysid, char *relname,
                             text *priv_type_text)
 {
-   HeapTuple   tuple;
+   Oid         reloid;
    AclMode     mode;
    int32       result;
 
    /*
-    * Check relname is valid. This is needed to deal with the case when
-    * usename is a superuser in which case pg_aclcheck simply returns
-    * ACLCHECK_OK without validating relname
+    * Convert relname to rel OID.
     */
-   tuple = SearchSysCache(RELNAME,
-                          PointerGetDatum(relname),
-                          0, 0, 0);
-   if (!HeapTupleIsValid(tuple))
+   reloid = GetSysCacheOid(RELNAME,
+                           PointerGetDatum(relname),
+                           0, 0, 0);
+   if (!OidIsValid(reloid))
        elog(ERROR, "has_table_privilege: relation \"%s\" does not exist",
             relname);
-   ReleaseSysCache(tuple);
 
    /*
     * 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
     */
-   result = pg_aclcheck(relname, usesysid, mode);
+   result = pg_class_aclcheck(reloid, usesysid, mode);
 
    if (result == ACLCHECK_OK)
        return true;
index dfbcccffbed250efda87862838f135fc11c352cb..8779125d1591d4554ee0c9c8809626df6dd1b6de 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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
  *   These routines allow the parser/planner/executor to perform
@@ -103,6 +103,16 @@ static struct cachedesc cacheinfo[] = {
            0,
            0
    }},
+   {AggregateRelationName,     /* AGGOID */
+       AggregateOidIndex,
+       0,
+       1,
+       {
+           ObjectIdAttributeNumber,
+           0,
+           0,
+           0
+   }},
    {AccessMethodRelationName,  /* AMNAME */
        AmNameIndex,
        0,
index 672ed7f85d880629f67eba6724813c8e31459153..ccfc2dbb12bb76c4e8d1e2f471d9a7a1abe2ef97 100644 (file)
@@ -7,14 +7,13 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * 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
 #define REWRITEREMOVE_H
 
-extern char *RewriteGetRuleEventRel(char *rulename);
 extern void RemoveRewriteRule(char *ruleName);
 extern void RelationRemoveRules(Oid relid);
 
index 3619797151b68e10728cc1b51f856d50bf476b9c..2a862af4bdd06cedf1b54191c8afa53dacfb7e20 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * 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
  *   For backward-compatibility purposes we have to allow there
 
 #include "nodes/parsenodes.h"
 #include "utils/array.h"
-#include "utils/memutils.h"
+
 
 /*
  * AclId       system identifier for the user, group, etc.
- *             XXX currently UNIX uid for users...
+ *             XXX Perhaps replace this type by OID?
  */
 typedef uint32 AclId;
 
@@ -159,14 +159,14 @@ typedef ArrayType IdList;
 #define ACL_MODE_REFERENCES_CHR 'x'
 #define ACL_MODE_TRIGGER_CHR   't'
 
-/* result codes for pg_aclcheck */
+/* 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 ACL_CHECK_* result code).  set in aclchk.c. */
-extern char *aclcheck_error_strings[];
+/* error messages (index by ACLCHECK_* result code).  set in aclchk.c. */
+extern const char * const aclcheck_error_strings[];
 
 /*
  * routines used internally
@@ -199,16 +199,16 @@ extern void ExecuteGrantStmt(GrantStmt *stmt);
 extern AclId get_grosysid(char *groname);
 extern char *get_groname(AclId grosysid);
 
-extern int32 pg_aclcheck(char *relname, 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);
-
+/* these return ACLCHECK_* result codes */
+extern int32 pg_class_aclcheck(Oid table_oid, Oid userid, AclMode mode);
 extern int32 pg_proc_aclcheck(Oid proc_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 */
index 6164c02b1525e6320b545250f39518e9a16f82e2..d4bcd14256e1fd9650bace2110f6f2d1edc68fe4 100644 (file)
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
  */
 
 #define AGGNAME            0
-#define AMNAME         1
-#define AMOID          2
-#define AMOPOPID       3
-#define AMOPSTRATEGY   4
-#define AMPROCNUM      5
-#define ATTNAME            6
-#define ATTNUM         7
-#define CLAAMNAME      8
-#define CLAOID         9
-#define GRONAME            10
-#define GROSYSID       11
-#define INDEXRELID     12
-#define INHRELID       13
-#define LANGNAME       14
-#define LANGOID            15
-#define OPERNAME       16
-#define OPEROID            17
-#define PROCNAME       18
-#define PROCOID            19
-#define RELNAME            20
-#define RELOID         21
-#define RULENAME       22
-#define SHADOWNAME     23
-#define SHADOWSYSID        24
-#define STATRELATT     25
-#define TYPENAME       26
-#define TYPEOID            27
+#define AGGOID         1
+#define AMNAME         2
+#define AMOID          3
+#define AMOPOPID       4
+#define AMOPSTRATEGY   5
+#define AMPROCNUM      6
+#define ATTNAME            7
+#define ATTNUM         8
+#define CLAAMNAME      9
+#define CLAOID         10
+#define GRONAME            11
+#define GROSYSID       12
+#define INDEXRELID     13
+#define INHRELID       14
+#define LANGNAME       15
+#define LANGOID            16
+#define OPERNAME       17
+#define OPEROID            18
+#define PROCNAME       19
+#define PROCOID            20
+#define RELNAME            21
+#define RELOID         22
+#define RULENAME       23
+#define SHADOWNAME     24
+#define SHADOWSYSID        25
+#define STATRELATT     26
+#define TYPENAME       27
+#define TYPEOID            28
+
 
 extern void InitCatalogCache(void);
 extern void InitCatalogCachePhase2(void);
index 625c6d7499d8ac8f3585e37cf016ad00a35c3f05..bd9707c2bdbeeb07e734cd35c97ca55885c9516f 100644 (file)
@@ -221,7 +221,7 @@ drop rule 314159;
 ERROR:  parser: parse error at or near "314159"
 -- no such rule 
 drop rule nonesuch;
-ERROR:  Rule or view "nonesuch" not found
+ERROR:  Rule "nonesuch" not found
 -- bad keyword 
 drop tuple rule nonesuch;
 ERROR:  parser: parse error at or near "tuple"
index 0bf560a949f8f932e1c9fd0dab3a9e21f0453c06..6c9b84dda2b8f56a4d63deec162b66c41300679d 100644 (file)
@@ -90,7 +90,7 @@ ERROR:  LOCK TABLE: permission denied
 COPY atest2 FROM stdin; -- fail
 ERROR:  atest2: Permission denied.
 GRANT ALL ON atest1 TO PUBLIC; -- fail
-ERROR:  permission denied
+ERROR:  atest1: permission denied
 -- checks in subquery, both ok
 SELECT * FROM atest1 WHERE ( b IN ( SELECT col1 FROM atest2 ) );
  a | b 
@@ -246,9 +246,9 @@ ERROR:  user "nosuchuser" does not exist
 select has_table_privilege('pg_shadow','sel');
 ERROR:  has_table_privilege: invalid privilege type sel
 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');
-ERROR:  has_table_privilege: invalid relation oid 1
+ERROR:  pg_class_aclcheck: relation 1 not found
 -- superuser
 \c -
 select has_table_privilege(current_user,'pg_shadow','select');