]> granicus.if.org Git - postgresql/commitdiff
Get rid of the separate RULE privilege for tables: now only a table's owner
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 5 Sep 2006 21:08:36 +0000 (21:08 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 5 Sep 2006 21:08:36 +0000 (21:08 +0000)
can create or modify rules for the table.  Do setRuleCheckAsUser() while
loading rules into the relcache, rather than when defining a rule.  This
ensures that permission checks for tables referenced in a rule are done with
respect to the current owner of the rule's table, whereas formerly ALTER TABLE
OWNER would fail to update the permission checking for associated rules.
Removal of separate RULE privilege is needed to prevent various scenarios
in which a grantee of RULE privilege could effectively have any privilege
of the table owner.  For backwards compatibility, GRANT/REVOKE RULE is still
accepted, but it doesn't do anything.  Per discussion here:
http://archives.postgresql.org/pgsql-hackers/2006-04/msg01138.php

21 files changed:
doc/src/sgml/ddl.sgml
doc/src/sgml/func.sgml
doc/src/sgml/information_schema.sgml
doc/src/sgml/ref/create_rule.sgml
doc/src/sgml/ref/grant.sgml
doc/src/sgml/ref/revoke.sgml
doc/src/sgml/user-manag.sgml
src/backend/catalog/aclchk.c
src/backend/catalog/information_schema.sql
src/backend/commands/comment.c
src/backend/rewrite/rewriteDefine.c
src/backend/rewrite/rewriteRemove.c
src/backend/utils/adt/acl.c
src/backend/utils/cache/relcache.c
src/include/catalog/catversion.h
src/include/nodes/parsenodes.h
src/include/rewrite/rewriteDefine.h
src/include/utils/acl.h
src/test/regress/expected/dependency.out
src/test/regress/expected/privileges.out
src/test/regress/sql/privileges.sql

index 5f3f724b7c622172fe187efa400c4b4750f099d1..f21a4797bdb5e5813b9f8f605402d65c1c6558e9 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.60 2006/07/14 00:13:05 neilc Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/ddl.sgml,v 1.61 2006/09/05 21:08:33 tgl Exp $ -->
 
 <chapter id="ddl">
  <title>Data Definition</title>
@@ -1342,7 +1342,7 @@ ALTER TABLE products RENAME TO items;
   <para>
    There are several different privileges: <literal>SELECT</>,
    <literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>,
-   <literal>RULE</>, <literal>REFERENCES</>, <literal>TRIGGER</>,
+   <literal>REFERENCES</>, <literal>TRIGGER</>,
    <literal>CREATE</>, <literal>CONNECT</>, <literal>TEMPORARY</>,
    <literal>EXECUTE</>, and <literal>USAGE</>.
    The privileges applicable to a particular
index ebf793ae55e749acd9e448bc0326927d5628ced6..13209c87a29145e1989b69f426a3a293bf0ee3ef 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.333 2006/09/04 21:47:25 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.334 2006/09/05 21:08:33 tgl Exp $ -->
 
  <chapter id="functions">
   <title>Functions and Operators</title>
@@ -9543,9 +9543,10 @@ SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute');
     the name can be schema-qualified if necessary.
     The desired access privilege type
     is specified by a text string, which must evaluate to one of the
-    values <literal>SELECT</literal>, <literal>INSERT</literal>, <literal>UPDATE</literal>,
-    <literal>DELETE</literal>, <literal>RULE</literal>, <literal>REFERENCES</literal>, or
-    <literal>TRIGGER</literal>.  (Case of the string is not significant, however.)
+    values <literal>SELECT</literal>, <literal>INSERT</literal>,
+    <literal>UPDATE</literal>, <literal>DELETE</literal>,
+    <literal>REFERENCES</literal>, or <literal>TRIGGER</literal>.
+    (Case of the string is not significant, however.)
     An example is:
 <programlisting>
 SELECT has_table_privilege('myschema.mytable', 'select');
index 1ce808463df3e7088ed7e078461f6caa63709268..544b811c546a6bff245534a40c3b34f7a6768468 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/information_schema.sgml,v 1.26 2006/05/02 18:07:51 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/information_schema.sgml,v 1.27 2006/09/05 21:08:34 tgl Exp $ -->
 
 <chapter id="information-schema">
  <title>The Information Schema</title>
@@ -2832,7 +2832,7 @@ ORDER BY c.ordinal_position;
        Type of the privilege: <literal>SELECT</literal>,
        <literal>DELETE</literal>, <literal>INSERT</literal>,
        <literal>UPDATE</literal>, <literal>REFERENCES</literal>,
-       <literal>RULE</literal>, or <literal>TRIGGER</literal>
+       or <literal>TRIGGER</literal>
       </entry>
      </row>
 
@@ -4418,7 +4418,7 @@ ORDER BY c.ordinal_position;
        Type of the privilege: <literal>SELECT</literal>,
        <literal>DELETE</literal>, <literal>INSERT</literal>,
        <literal>UPDATE</literal>, <literal>REFERENCES</literal>,
-       <literal>RULE</literal>, or <literal>TRIGGER</literal>
+       or <literal>TRIGGER</literal>
       </entry>
      </row>
 
index 9380ab5a184627c7507fcc96f5ad6662da195967..1c9cf0b91a8819abb0dc3584603106fa759ed6d0 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_rule.sgml,v 1.46 2006/09/02 17:06:52 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_rule.sgml,v 1.47 2006/09/05 21:08:35 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -200,8 +200,7 @@ CREATE [ OR REPLACE ] RULE <replaceable class="parameter">name</replaceable> AS
   <title>Notes</title>
 
   <para>
-   You must have the privilege <literal>RULE</literal> on a table to
-   be allowed to define a rule on it.
+   You must be the owner of a table to create or change rules for it.
   </para>
 
   <para>
index d846cd07fde4118f4ccdbeca066b431237b2c1d0..e00ea521e931d6b4b0941dbb8ebb76738d4be7ad 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.60 2006/08/02 16:29:49 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.61 2006/09/05 21:08:35 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -20,7 +20,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-GRANT { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER }
+GRANT { { SELECT | INSERT | UPDATE | DELETE | REFERENCES | TRIGGER }
     [,...] | ALL [ PRIVILEGES ] }
     ON [ TABLE ] <replaceable class="PARAMETER">tablename</replaceable> [, ...]
     TO { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
@@ -178,16 +178,6 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
      </listitem>
     </varlistentry>
 
-    <varlistentry>
-     <term>RULE</term>
-     <listitem>
-      <para>
-       Allows the creation of a rule on the table/view.  (See the <xref
-       linkend="sql-createrule" endterm="sql-createrule-title"> statement.)
-      </para>
-     </listitem>
-    </varlistentry>
-
     <varlistentry>
      <term>REFERENCES</term>
      <listitem>
@@ -418,8 +408,8 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
 
                         Access privileges for database "lusitania"
  Schema |  Name   | Type  |                     Access privileges
---------+---------+-------+------------------------------------------------------------
- public | mytable | table | {miriam=arwdRxt/miriam,=r/miriam,"group todos=arw/miriam"}
+--------+---------+-------+-----------------------------------------------------------
+ public | mytable | table | {miriam=arwdxt/miriam,=r/miriam,"group todos=arw/miriam"}
 (1 row)
 </programlisting>
     The entries shown by <command>\z</command> are interpreted thus:
@@ -432,7 +422,6 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
                   w -- UPDATE ("write")
                   a -- INSERT ("append")
                   d -- DELETE
-                  R -- RULE
                   x -- REFERENCES
                   t -- TRIGGER
                   X -- EXECUTE
@@ -440,7 +429,7 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
                   C -- CREATE
                   c -- CONNECT
                   T -- TEMPORARY
-            arwdRxt -- ALL PRIVILEGES (for tables)
+             arwdxt -- ALL PRIVILEGES (for tables)
                   * -- grant option for preceding privilege
 
               /yyyy -- user who granted this privilege
@@ -463,7 +452,7 @@ and may include some privileges for <literal>PUBLIC</> depending on the
 object type, as explained above.  The first <command>GRANT</> or
 <command>REVOKE</> on an object
 will instantiate the default privileges (producing, for example,
-<literal>{miriam=arwdRxt/miriam}</>) and then modify them per the
+<literal>{miriam=arwdxt/miriam}</>) and then modify them per the
 specified request.
    </para>
 
@@ -548,8 +537,7 @@ GRANT <replaceable class="PARAMETER">privileges</replaceable>
    </para>
 
    <para>
-    The <literal>RULE</literal> privilege, and privileges on
-    databases, tablespaces, schemas, and languages are
+    Privileges on databases, tablespaces, schemas, and languages are
     <productname>PostgreSQL</productname> extensions.
    </para>
  </refsect1>
index df38437436fe3324a36fc2b1672e7c6a237b8a55..03746d5622955e11feabd2af43d9bfbf50cd0506 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.39 2006/08/02 16:29:49 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.40 2006/09/05 21:08:35 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -21,7 +21,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 REVOKE [ GRANT OPTION FOR ]
-    { { SELECT | INSERT | UPDATE | DELETE | RULE | REFERENCES | TRIGGER }
+    { { SELECT | INSERT | UPDATE | DELETE | REFERENCES | TRIGGER }
     [,...] | ALL [ PRIVILEGES ] }
     ON [ TABLE ] <replaceable class="PARAMETER">tablename</replaceable> [, ...]
     FROM { <replaceable class="PARAMETER">username</replaceable> | GROUP <replaceable class="PARAMETER">groupname</replaceable> | PUBLIC } [, ...]
index c86837d1f7a84b4a7ed815e1c7c577cff56353fb..ec5c6e43c4dd68a35e5ae841e7644b6f2020108b 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/user-manag.sgml,v 1.36 2006/08/02 16:29:49 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/user-manag.sgml,v 1.37 2006/09/05 21:08:34 tgl Exp $ -->
 
 <chapter id="user-manag">
  <title>Database Roles and Privileges</title>
@@ -293,7 +293,7 @@ ALTER ROLE myname SET enable_indexscan TO off;
    granted.
    There are several different kinds of privilege: <literal>SELECT</>,
    <literal>INSERT</>, <literal>UPDATE</>, <literal>DELETE</>,
-   <literal>RULE</>, <literal>REFERENCES</>, <literal>TRIGGER</>,
+   <literal>REFERENCES</>, <literal>TRIGGER</>,
    <literal>CREATE</>, <literal>CONNECT</>, <literal>TEMPORARY</>,
    <literal>EXECUTE</>, and <literal>USAGE</>.
    For more information on the different types of privileges supported by
index 73b9ef6e9d94a75817e1b531f3e85cee8360ee40..e74c9b4410e7c0f1a427b3b16b679fda83eb7b4b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.130 2006/07/14 14:52:17 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.131 2006/09/05 21:08:35 tgl Exp $
  *
  * NOTES
  *       See acl.h.
@@ -1328,8 +1328,6 @@ string_to_privilege(const char *privname)
                return ACL_UPDATE;
        if (strcmp(privname, "delete") == 0)
                return ACL_DELETE;
-       if (strcmp(privname, "rule") == 0)
-               return ACL_RULE;
        if (strcmp(privname, "references") == 0)
                return ACL_REFERENCES;
        if (strcmp(privname, "trigger") == 0)
@@ -1346,6 +1344,8 @@ string_to_privilege(const char *privname)
                return ACL_CREATE_TEMP;
        if (strcmp(privname, "connect") == 0)
                return ACL_CONNECT;
+       if (strcmp(privname, "rule") == 0)
+               return 0;                               /* ignore old RULE privileges */
        ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
                         errmsg("unrecognized privilege type \"%s\"", privname)));
@@ -1365,8 +1365,6 @@ privilege_to_string(AclMode privilege)
                        return "UPDATE";
                case ACL_DELETE:
                        return "DELETE";
-               case ACL_RULE:
-                       return "RULE";
                case ACL_REFERENCES:
                        return "REFERENCES";
                case ACL_TRIGGER:
index a30cddd2878941eeed64270a0ba442fcb68c31c5..a735fa3081f818effbed1290a3f8e1e27d366040 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Copyright (c) 2003-2006, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.35 2006/09/04 23:13:01 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.36 2006/09/05 21:08:35 tgl Exp $
  */
 
 /*
@@ -1194,7 +1194,6 @@ CREATE VIEW role_table_grants AS
           SELECT 'INSERT' UNION ALL
           SELECT 'UPDATE' UNION ALL
           SELECT 'REFERENCES' UNION ALL
-          SELECT 'RULE' UNION ALL
           SELECT 'TRIGGER') AS pr (type)
 
     WHERE c.relnamespace = nc.oid
@@ -1705,7 +1704,6 @@ CREATE VIEW table_constraints AS
                OR has_table_privilege(r.oid, 'INSERT')
                OR has_table_privilege(r.oid, 'UPDATE')
                OR has_table_privilege(r.oid, 'DELETE')
-               OR has_table_privilege(r.oid, 'RULE')
                OR has_table_privilege(r.oid, 'REFERENCES')
                OR has_table_privilege(r.oid, 'TRIGGER') )
 
@@ -1739,7 +1737,6 @@ CREATE VIEW table_constraints AS
                OR has_table_privilege(r.oid, 'INSERT')
                OR has_table_privilege(r.oid, 'UPDATE')
                OR has_table_privilege(r.oid, 'DELETE')
-               OR has_table_privilege(r.oid, 'RULE')
                OR has_table_privilege(r.oid, 'REFERENCES')
                OR has_table_privilege(r.oid, 'TRIGGER') );
 
@@ -1785,7 +1782,6 @@ CREATE VIEW table_privileges AS
           SELECT 'INSERT' UNION ALL
           SELECT 'UPDATE' UNION ALL
           SELECT 'REFERENCES' UNION ALL
-          SELECT 'RULE' UNION ALL
           SELECT 'TRIGGER') AS pr (type)
 
     WHERE c.relnamespace = nc.oid
@@ -1841,7 +1837,6 @@ CREATE VIEW tables AS
                OR has_table_privilege(c.oid, 'INSERT')
                OR has_table_privilege(c.oid, 'UPDATE')
                OR has_table_privilege(c.oid, 'DELETE')
-               OR has_table_privilege(c.oid, 'RULE')
                OR has_table_privilege(c.oid, 'REFERENCES')
                OR has_table_privilege(c.oid, 'TRIGGER') );
 
@@ -1963,7 +1958,6 @@ CREATE VIEW triggers AS
                OR has_table_privilege(c.oid, 'INSERT')
                OR has_table_privilege(c.oid, 'UPDATE')
                OR has_table_privilege(c.oid, 'DELETE')
-               OR has_table_privilege(c.oid, 'RULE')
                OR has_table_privilege(c.oid, 'REFERENCES')
                OR has_table_privilege(c.oid, 'TRIGGER') );
 
@@ -2162,7 +2156,6 @@ CREATE VIEW views AS
                OR has_table_privilege(c.oid, 'INSERT')
                OR has_table_privilege(c.oid, 'UPDATE')
                OR has_table_privilege(c.oid, 'DELETE')
-               OR has_table_privilege(c.oid, 'RULE')
                OR has_table_privilege(c.oid, 'REFERENCES')
                OR has_table_privilege(c.oid, 'TRIGGER') );
 
index 2e29535c4e7b4960bfbfed05425675c4a5749f7d..f54243a49554f3ae828b02000070c3f94f60162e 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 1996-2006, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.90 2006/07/14 14:52:18 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.91 2006/09/05 21:08:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -741,7 +741,6 @@ CommentRule(List *qualname, char *comment)
        HeapTuple       tuple;
        Oid                     reloid;
        Oid                     ruleoid;
-       AclResult       aclcheck;
 
        /* Separate relname and trig name */
        nnames = list_length(qualname);
@@ -819,9 +818,8 @@ CommentRule(List *qualname, char *comment)
        }
 
        /* Check object security */
-       aclcheck = pg_class_aclcheck(reloid, GetUserId(), ACL_RULE);
-       if (aclcheck != ACLCHECK_OK)
-               aclcheck_error(aclcheck, ACL_KIND_CLASS,
+       if (!pg_class_ownercheck(reloid, GetUserId()))
+               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
                                           get_rel_name(reloid));
 
        /* Call CreateComments() to create/drop the comments */
index a961f49d9b1b16915f488c5343a37d2cfac3f79f..17f437c385597f3e003c307870aa449e211446d7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.113 2006/09/02 17:06:52 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.114 2006/09/05 21:08:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,9 +33,8 @@
 
 static void checkRuleResultList(List *targetList, TupleDesc resultDesc,
                                                                bool isSelect);
-static void setRuleCheckAsUser_Query(Query *qry, Oid userid);
-static void setRuleCheckAsUser_Expr(Node *node, Oid userid);
 static bool setRuleCheckAsUser_walker(Node *node, Oid *context);
+static void setRuleCheckAsUser_Query(Query *qry, Oid userid);
 
 
 /*
@@ -193,7 +192,6 @@ DefineQueryRewrite(RuleStmt *stmt)
        int                     event_attno;
        ListCell   *l;
        Query      *query;
-       AclResult       aclresult;
        bool            RelisBecomingView = false;
 
        /*
@@ -209,9 +207,8 @@ DefineQueryRewrite(RuleStmt *stmt)
        /*
         * Check user has permission to apply rules to this relation.
         */
-       aclresult = pg_class_aclcheck(ev_relid, GetUserId(), ACL_RULE);
-       if (aclresult != ACLCHECK_OK)
-               aclcheck_error(aclresult, ACL_KIND_CLASS,
+       if (!pg_class_ownercheck(ev_relid, GetUserId()))
+               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
                                           RelationGetRelationName(event_relation));
 
        /*
@@ -411,19 +408,6 @@ DefineQueryRewrite(RuleStmt *stmt)
         */
        event_attno = -1;
 
-       /*
-        * We want the rule's table references to be checked as though by the rule
-        * owner, not the user referencing the rule.  Therefore, scan through the
-        * rule's rtables and set the checkAsUser field on all rtable entries.  We
-        * have to look at event_qual as well, in case it contains sublinks.
-        */
-       foreach(l, action)
-       {
-               query = (Query *) lfirst(l);
-               setRuleCheckAsUser_Query(query, GetUserId());
-       }
-       setRuleCheckAsUser_Expr(event_qual, GetUserId());
-
        /* discard rule if it's null action and not INSTEAD; it's a no-op */
        if (action != NIL || is_instead)
        {
@@ -554,9 +538,9 @@ checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect)
 }
 
 /*
- * setRuleCheckAsUser_Query
- *             Recursively scan a query and set the checkAsUser field to the
- *             given userid in all rtable entries.
+ * setRuleCheckAsUser
+ *             Recursively scan a query or expression tree and set the checkAsUser
+ *             field to the given userid in all rtable entries.
  *
  * Note: for a view (ON SELECT rule), the checkAsUser field of the *OLD*
  * RTE entry will be overridden when the view rule is expanded, and the
@@ -565,6 +549,26 @@ checkRuleResultList(List *targetList, TupleDesc resultDesc, bool isSelect)
  * it's important to set these fields to match the rule owner.  So we just set
  * them always.
  */
+void
+setRuleCheckAsUser(Node *node, Oid userid)
+{
+       (void) setRuleCheckAsUser_walker(node, &userid);
+}
+
+static bool
+setRuleCheckAsUser_walker(Node *node, Oid *context)
+{
+       if (node == NULL)
+               return false;
+       if (IsA(node, Query))
+       {
+               setRuleCheckAsUser_Query((Query *) node, *context);
+               return false;
+       }
+       return expression_tree_walker(node, setRuleCheckAsUser_walker,
+                                                                 (void *) context);
+}
+
 static void
 setRuleCheckAsUser_Query(Query *qry, Oid userid)
 {
@@ -591,31 +595,6 @@ setRuleCheckAsUser_Query(Query *qry, Oid userid)
                                                  QTW_IGNORE_RT_SUBQUERIES);
 }
 
-/*
- * Expression-tree walker to find sublink queries
- */
-static void
-setRuleCheckAsUser_Expr(Node *node, Oid userid)
-{
-       (void) setRuleCheckAsUser_walker(node, &userid);
-}
-
-static bool
-setRuleCheckAsUser_walker(Node *node, Oid *context)
-{
-       if (node == NULL)
-               return false;
-       if (IsA(node, Query))
-       {
-               Query      *qry = (Query *) node;
-
-               setRuleCheckAsUser_Query(qry, *context);
-               return false;
-       }
-       return expression_tree_walker(node, setRuleCheckAsUser_walker,
-                                                                 (void *) context);
-}
-
 
 /*
  * Rename an existing rewrite rule.
index b0acc01f8273289936f33c4afc99cf1c1247a1f1..e57724af4d7ce90de616feff51d50d05e3482c5f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/rewrite/rewriteRemove.c,v 1.65 2006/06/16 20:23:44 adunstan Exp $
+ *       $PostgreSQL: pgsql/src/backend/rewrite/rewriteRemove.c,v 1.66 2006/09/05 21:08:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -39,7 +39,6 @@ RemoveRewriteRule(Oid owningRel, const char *ruleName, DropBehavior behavior,
 {
        HeapTuple       tuple;
        Oid                     eventRelationOid;
-       AclResult       aclresult;
        ObjectAddress object;
 
        /*
@@ -72,9 +71,8 @@ RemoveRewriteRule(Oid owningRel, const char *ruleName, DropBehavior behavior,
         */
        eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
        Assert(eventRelationOid == owningRel);
-       aclresult = pg_class_aclcheck(eventRelationOid, GetUserId(), ACL_RULE);
-       if (aclresult != ACLCHECK_OK)
-               aclcheck_error(aclresult, ACL_KIND_CLASS,
+       if (!pg_class_ownercheck(eventRelationOid, GetUserId()))
+               aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
                                           get_rel_name(eventRelationOid));
 
        /*
index c3ac26dce4aa47e0accb3fa58f77ed20d2ce3a51..509c6dea92af9d1a79207a3e2fad6590548725df 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.134 2006/07/14 14:52:23 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.135 2006/09/05 21:08:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -265,9 +265,6 @@ aclparse(const char *s, AclItem *aip)
                        case ACL_DELETE_CHR:
                                read = ACL_DELETE;
                                break;
-                       case ACL_RULE_CHR:
-                               read = ACL_RULE;
-                               break;
                        case ACL_REFERENCES_CHR:
                                read = ACL_REFERENCES;
                                break;
@@ -289,6 +286,9 @@ aclparse(const char *s, AclItem *aip)
                        case ACL_CONNECT_CHR:
                                read = ACL_CONNECT;
                                break;
+                       case 'R':                       /* ignore old RULE privileges */
+                               read = 0;
+                               break;
                        default:
                                ereport(ERROR,
                                                (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
@@ -1325,8 +1325,6 @@ convert_priv_string(text *priv_type_text)
                return ACL_UPDATE;
        if (pg_strcasecmp(priv_type, "DELETE") == 0)
                return ACL_DELETE;
-       if (pg_strcasecmp(priv_type, "RULE") == 0)
-               return ACL_RULE;
        if (pg_strcasecmp(priv_type, "REFERENCES") == 0)
                return ACL_REFERENCES;
        if (pg_strcasecmp(priv_type, "TRIGGER") == 0)
@@ -1343,6 +1341,8 @@ convert_priv_string(text *priv_type_text)
                return ACL_CREATE_TEMP;
        if (pg_strcasecmp(priv_type, "CONNECT") == 0)
                return ACL_CONNECT;
+       if (pg_strcasecmp(priv_type, "RULE") == 0)
+               return 0;                               /* ignore old RULE privileges */
 
        ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1553,11 +1553,6 @@ convert_table_priv_string(text *priv_type_text)
        if (pg_strcasecmp(priv_type, "DELETE WITH GRANT OPTION") == 0)
                return ACL_GRANT_OPTION_FOR(ACL_DELETE);
 
-       if (pg_strcasecmp(priv_type, "RULE") == 0)
-               return ACL_RULE;
-       if (pg_strcasecmp(priv_type, "RULE WITH GRANT OPTION") == 0)
-               return ACL_GRANT_OPTION_FOR(ACL_RULE);
-
        if (pg_strcasecmp(priv_type, "REFERENCES") == 0)
                return ACL_REFERENCES;
        if (pg_strcasecmp(priv_type, "REFERENCES WITH GRANT OPTION") == 0)
@@ -1568,6 +1563,11 @@ convert_table_priv_string(text *priv_type_text)
        if (pg_strcasecmp(priv_type, "TRIGGER WITH GRANT OPTION") == 0)
                return ACL_GRANT_OPTION_FOR(ACL_TRIGGER);
 
+       if (pg_strcasecmp(priv_type, "RULE") == 0)
+               return 0;                               /* ignore old RULE privileges */
+       if (pg_strcasecmp(priv_type, "RULE WITH GRANT OPTION") == 0)
+               return 0;
+
        ereport(ERROR,
                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                         errmsg("unrecognized privilege type: \"%s\"", priv_type)));
index 08697d503667c6cc5956f0891288da101b7f1399..190543e2bd712eeab57ee0b25115195cd08c281a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.247 2006/07/31 20:09:05 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.248 2006/09/05 21:08:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -51,6 +51,7 @@
 #include "optimizer/clauses.h"
 #include "optimizer/planmain.h"
 #include "optimizer/prep.h"
+#include "rewrite/rewriteDefine.h"
 #include "storage/fd.h"
 #include "storage/smgr.h"
 #include "utils/builtins.h"
@@ -683,6 +684,22 @@ RelationBuildRuleLock(Relation relation)
                if ((Pointer) rule_text != DatumGetPointer(rule_datum))
                        pfree(rule_text);
 
+               /*
+                * We want the rule's table references to be checked as though by the
+                * table owner, not the user referencing the rule.  Therefore, scan
+                * through the rule's actions and set the checkAsUser field on all
+                * rtable entries.  We have to look at the qual as well, in case it
+                * contains sublinks.
+                *
+                * The reason for doing this when the rule is loaded, rather than
+                * when it is stored, is that otherwise ALTER TABLE OWNER would have
+                * to grovel through stored rules to update checkAsUser fields.
+                * Scanning the rule tree during load is relatively cheap (compared
+                * to constructing it in the first place), so we do it here.
+                */
+               setRuleCheckAsUser((Node *) rule->actions, relation->rd_rel->relowner);
+               setRuleCheckAsUser(rule->qual, relation->rd_rel->relowner);
+
                if (numlocks >= maxlocks)
                {
                        maxlocks *= 2;
index 6266b591cab463e1dea362bb0c8478a31d94294a..7e207a8ee2d6635c4bd8a958fb96a328afc87b66 100644 (file)
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.353 2006/08/25 04:06:54 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.354 2006/09/05 21:08:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200608211
+#define CATALOG_VERSION_NO     200609051
 
 #endif
index 40708404fccd555b7c92dd4cfda576b4a0588621..0b9de4905d10c85fc0477ed771fc2839f6ab66bb 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.329 2006/09/03 03:19:45 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.330 2006/09/05 21:08:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -50,7 +50,7 @@ typedef uint32 AclMode;                       /* a bitmask of privilege bits */
 #define ACL_SELECT             (1<<1)
 #define ACL_UPDATE             (1<<2)
 #define ACL_DELETE             (1<<3)
-#define ACL_RULE               (1<<4)
+/* #define ACL_RULE            (1<<4)  unused, available */
 #define ACL_REFERENCES (1<<5)
 #define ACL_TRIGGER            (1<<6)
 #define ACL_EXECUTE            (1<<7)  /* for functions */
index 3d284894e3aaeb90f3dac13269e4aeefc0341888..e404ac526a82c389052bd22ce9a6ef857fc92fd3 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/rewrite/rewriteDefine.h,v 1.21 2006/03/05 15:58:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/rewrite/rewriteDefine.h,v 1.22 2006/09/05 21:08:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,4 +21,6 @@ extern void DefineQueryRewrite(RuleStmt *args);
 extern void RenameRewriteRule(Oid owningRel, const char *oldName,
                                  const char *newName);
 
+extern void setRuleCheckAsUser(Node *node, Oid userid);
+
 #endif   /* REWRITEDEFINE_H */
index 27aaf0dfbf7e01de6f9f1dc81cbad43905598e0c..56226b42162473e2b10423beb3cac9b78c73257e 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.96 2006/05/03 22:45:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.97 2006/09/05 21:08:36 tgl Exp $
  *
  * NOTES
  *       An ACL array is simply an array of AclItems, representing the union
@@ -128,7 +128,6 @@ typedef ArrayType Acl;
 #define ACL_SELECT_CHR                 'r'             /* formerly known as "read" */
 #define ACL_UPDATE_CHR                 'w'             /* formerly known as "write" */
 #define ACL_DELETE_CHR                 'd'
-#define ACL_RULE_CHR                   'R'
 #define ACL_REFERENCES_CHR             'x'
 #define ACL_TRIGGER_CHR                        't'
 #define ACL_EXECUTE_CHR                        'X'
@@ -143,7 +142,7 @@ typedef ArrayType Acl;
 /*
  * Bitmasks defining "all rights" for each supported object type
  */
-#define ACL_ALL_RIGHTS_RELATION                (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_RULE|ACL_REFERENCES|ACL_TRIGGER)
+#define ACL_ALL_RIGHTS_RELATION                (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_REFERENCES|ACL_TRIGGER)
 #define ACL_ALL_RIGHTS_SEQUENCE                (ACL_USAGE|ACL_SELECT|ACL_UPDATE)
 #define ACL_ALL_RIGHTS_DATABASE                (ACL_CREATE|ACL_CREATE_TEMP|ACL_CONNECT)
 #define ACL_ALL_RIGHTS_FUNCTION                (ACL_EXECUTE)
index ba65a351bc8c41cd74d2452d3739a2ee6499014d..82c1bf01383da4b1ecf6477d0d19969e5dab6ebe 100644 (file)
@@ -68,19 +68,19 @@ NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "deptest_pkey" fo
 GRANT ALL ON deptest1 TO regression_user2;
 RESET SESSION AUTHORIZATION;
 \z deptest1
-                                                            Access privileges for database "regression"
- Schema |   Name   | Type  |                                                           Access privileges                                                            
---------+----------+-------+----------------------------------------------------------------------------------------------------------------------------------------
- public | deptest1 | table | {regression_user0=arwdRxt/regression_user0,regression_user1=a*r*w*d*R*x*t*/regression_user0,regression_user2=arwdRxt/regression_user1}
+                                                          Access privileges for database "regression"
+ Schema |   Name   | Type  |                                                         Access privileges                                                          
+--------+----------+-------+------------------------------------------------------------------------------------------------------------------------------------
+ public | deptest1 | table | {regression_user0=arwdxt/regression_user0,regression_user1=a*r*w*d*x*t*/regression_user0,regression_user2=arwdxt/regression_user1}
 (1 row)
 
 DROP OWNED BY regression_user1;
 -- all grants revoked
 \z deptest1
-               Access privileges for database "regression"
- Schema |   Name   | Type  |              Access privileges              
---------+----------+-------+---------------------------------------------
- public | deptest1 | table | {regression_user0=arwdRxt/regression_user0}
+              Access privileges for database "regression"
+ Schema |   Name   | Type  |             Access privileges              
+--------+----------+-------+--------------------------------------------
+ public | deptest1 | table | {regression_user0=arwdxt/regression_user0}
 (1 row)
 
 -- table was dropped
index 201e8a11d313e3bb465b2a13f2be2bd551c19cf6..5404969c6089813c415a5cc048add3816d9c76fb 100644 (file)
@@ -301,7 +301,7 @@ select has_table_privilege('pg_authid','sel');
 ERROR:  unrecognized privilege type: "sel"
 select has_table_privilege(-999999,'pg_authid','update');
 ERROR:  role with OID 4293967297 does not exist
-select has_table_privilege(1,'rule');
+select has_table_privilege(1,'select');
 ERROR:  relation with OID 1 does not exist
 -- superuser
 \c -
@@ -331,11 +331,13 @@ from (select oid from pg_roles where rolname = current_user) as t2;
  t
 (1 row)
 
+-- 'rule' privilege no longer exists, but for backwards compatibility
+-- has_table_privilege still recognizes the keyword and says FALSE
 select has_table_privilege(current_user,t1.oid,'rule')
 from (select oid from pg_class where relname = 'pg_authid') as t1;
  has_table_privilege 
 ---------------------
- t
+ f
 (1 row)
 
 select has_table_privilege(current_user,t1.oid,'references')
@@ -415,13 +417,6 @@ from (select oid from pg_roles where rolname = current_user) as t2;
  f
 (1 row)
 
-select has_table_privilege(current_user,t1.oid,'rule')
-from (select oid from pg_class where relname = 'pg_class') as t1;
- has_table_privilege 
----------------------
- f
-(1 row)
-
 select has_table_privilege(current_user,t1.oid,'references')
 from (select oid from pg_class where relname = 'pg_class') as t1;
  has_table_privilege 
@@ -497,13 +492,6 @@ from (select oid from pg_roles where rolname = current_user) as t2;
  f
 (1 row)
 
-select has_table_privilege(current_user,t1.oid,'rule')
-from (select oid from pg_class where relname = 'atest1') as t1;
- has_table_privilege 
----------------------
- f
-(1 row)
-
 select has_table_privilege(current_user,t1.oid,'references')
 from (select oid from pg_class where relname = 'atest1') as t1;
  has_table_privilege 
index 3b96abe87ea739f10b917c50c97ea59aaf4c4e7c..4c0d9c43f2783a31e7f6f3a6c5a41275a3450578 100644 (file)
@@ -214,7 +214,7 @@ select has_table_privilege('pg_shad','select');
 select has_table_privilege('nosuchuser','pg_authid','select');
 select has_table_privilege('pg_authid','sel');
 select has_table_privilege(-999999,'pg_authid','update');
-select has_table_privilege(1,'rule');
+select has_table_privilege(1,'select');
 
 -- superuser
 \c -
@@ -227,6 +227,8 @@ from (select oid from pg_roles where rolname = current_user) as t2;
 select has_table_privilege(t2.oid,'pg_authid','delete')
 from (select oid from pg_roles where rolname = current_user) as t2;
 
+-- 'rule' privilege no longer exists, but for backwards compatibility
+-- has_table_privilege still recognizes the keyword and says FALSE
 select has_table_privilege(current_user,t1.oid,'rule')
 from (select oid from pg_class where relname = 'pg_authid') as t1;
 select has_table_privilege(current_user,t1.oid,'references')
@@ -258,8 +260,6 @@ from (select oid from pg_roles where rolname = current_user) as t2;
 select has_table_privilege(t2.oid,'pg_class','delete')
 from (select oid from pg_roles where rolname = current_user) as t2;
 
-select has_table_privilege(current_user,t1.oid,'rule')
-from (select oid from pg_class where relname = 'pg_class') as t1;
 select has_table_privilege(current_user,t1.oid,'references')
 from (select oid from pg_class where relname = 'pg_class') as t1;
 
@@ -286,8 +286,6 @@ from (select oid from pg_roles where rolname = current_user) as t2;
 select has_table_privilege(t2.oid,'atest1','delete')
 from (select oid from pg_roles where rolname = current_user) as t2;
 
-select has_table_privilege(current_user,t1.oid,'rule')
-from (select oid from pg_class where relname = 'atest1') as t1;
 select has_table_privilege(current_user,t1.oid,'references')
 from (select oid from pg_class where relname = 'atest1') as t1;