diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml index 5f3f724b7c622172fe187efa400c4b4750f099d1..f21a4797bdb5e5813b9f8f605402d65c1c6558e9 100644 --- a/doc/src/sgml/ddl.sgml +++ b/doc/src/sgml/ddl.sgml @@ -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 diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index ebf793ae55e749acd9e448bc0326927d5628ced6..13209c87a29145e1989b69f426a3a293bf0ee3ef 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -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'); diff --git a/doc/src/sgml/information_schema.sgml b/doc/src/sgml/information_schema.sgml index 1ce808463df3e7088ed7e078461f6caa63709268..544b811c546a6bff245534a40c3b34f7a6768468 100644 --- a/doc/src/sgml/information_schema.sgml +++ b/doc/src/sgml/information_schema.sgml @@ -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> diff --git a/doc/src/sgml/ref/create_rule.sgml b/doc/src/sgml/ref/create_rule.sgml index 9380ab5a184627c7507fcc96f5ad6662da195967..1c9cf0b91a8819abb0dc3584603106fa759ed6d0 100644 --- a/doc/src/sgml/ref/create_rule.sgml +++ b/doc/src/sgml/ref/create_rule.sgml @@ -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> diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml index d846cd07fde4118f4ccdbeca066b431237b2c1d0..e00ea521e931d6b4b0941dbb8ebb76738d4be7ad 100644 --- a/doc/src/sgml/ref/grant.sgml +++ b/doc/src/sgml/ref/grant.sgml @@ -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> diff --git a/doc/src/sgml/ref/revoke.sgml b/doc/src/sgml/ref/revoke.sgml index df38437436fe3324a36fc2b1672e7c6a237b8a55..03746d5622955e11feabd2af43d9bfbf50cd0506 100644 --- a/doc/src/sgml/ref/revoke.sgml +++ b/doc/src/sgml/ref/revoke.sgml @@ -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 } [, ...] diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml index c86837d1f7a84b4a7ed815e1c7c577cff56353fb..ec5c6e43c4dd68a35e5ae841e7644b6f2020108b 100644 --- a/doc/src/sgml/user-manag.sgml +++ b/doc/src/sgml/user-manag.sgml @@ -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 diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index 73b9ef6e9d94a75817e1b531f3e85cee8360ee40..e74c9b4410e7c0f1a427b3b16b679fda83eb7b4b 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -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: diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql index a30cddd2878941eeed64270a0ba442fcb68c31c5..a735fa3081f818effbed1290a3f8e1e27d366040 100644 --- a/src/backend/catalog/information_schema.sql +++ b/src/backend/catalog/information_schema.sql @@ -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') ); diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c index 2e29535c4e7b4960bfbfed05425675c4a5749f7d..f54243a49554f3ae828b02000070c3f94f60162e 100644 --- a/src/backend/commands/comment.c +++ b/src/backend/commands/comment.c @@ -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 */ diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index a961f49d9b1b16915f488c5343a37d2cfac3f79f..17f437c385597f3e003c307870aa449e211446d7 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -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. diff --git a/src/backend/rewrite/rewriteRemove.c b/src/backend/rewrite/rewriteRemove.c index b0acc01f8273289936f33c4afc99cf1c1247a1f1..e57724af4d7ce90de616feff51d50d05e3482c5f 100644 --- a/src/backend/rewrite/rewriteRemove.c +++ b/src/backend/rewrite/rewriteRemove.c @@ -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)); /* diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index c3ac26dce4aa47e0accb3fa58f77ed20d2ce3a51..509c6dea92af9d1a79207a3e2fad6590548725df 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -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))); diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 08697d503667c6cc5956f0891288da101b7f1399..190543e2bd712eeab57ee0b25115195cd08c281a 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -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; diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 6266b591cab463e1dea362bb0c8478a31d94294a..7e207a8ee2d6635c4bd8a958fb96a328afc87b66 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -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 diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 40708404fccd555b7c92dd4cfda576b4a0588621..0b9de4905d10c85fc0477ed771fc2839f6ab66bb 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -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 */ diff --git a/src/include/rewrite/rewriteDefine.h b/src/include/rewrite/rewriteDefine.h index 3d284894e3aaeb90f3dac13269e4aeefc0341888..e404ac526a82c389052bd22ce9a6ef857fc92fd3 100644 --- a/src/include/rewrite/rewriteDefine.h +++ b/src/include/rewrite/rewriteDefine.h @@ -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 */ diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index 27aaf0dfbf7e01de6f9f1dc81cbad43905598e0c..56226b42162473e2b10423beb3cac9b78c73257e 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -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) diff --git a/src/test/regress/expected/dependency.out b/src/test/regress/expected/dependency.out index ba65a351bc8c41cd74d2452d3739a2ee6499014d..82c1bf01383da4b1ecf6477d0d19969e5dab6ebe 100644 --- a/src/test/regress/expected/dependency.out +++ b/src/test/regress/expected/dependency.out @@ -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 diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out index 201e8a11d313e3bb465b2a13f2be2bd551c19cf6..5404969c6089813c415a5cc048add3816d9c76fb 100644 --- a/src/test/regress/expected/privileges.out +++ b/src/test/regress/expected/privileges.out @@ -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 diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql index 3b96abe87ea739f10b917c50c97ea59aaf4c4e7c..4c0d9c43f2783a31e7f6f3a6c5a41275a3450578 100644 --- a/src/test/regress/sql/privileges.sql +++ b/src/test/regress/sql/privileges.sql @@ -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;