diff options
Diffstat (limited to 'src/backend/rewrite')
-rw-r--r-- | src/backend/rewrite/locks.c | 103 | ||||
-rw-r--r-- | src/backend/rewrite/rewriteDefine.c | 55 | ||||
-rw-r--r-- | src/backend/rewrite/rewriteHandler.c | 119 | ||||
-rw-r--r-- | src/backend/rewrite/rewriteSupport.c | 6 |
4 files changed, 201 insertions, 82 deletions
diff --git a/src/backend/rewrite/locks.c b/src/backend/rewrite/locks.c index 04698be13e3..46727d94c6e 100644 --- a/src/backend/rewrite/locks.c +++ b/src/backend/rewrite/locks.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.10 1998/06/15 19:29:06 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/Attic/locks.c,v 1.11 1998/08/24 01:37:56 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -18,6 +18,14 @@ #include "utils/syscache.h" /* for SearchSysCache */ #include "rewrite/locks.h" /* for rewrite specific lock defns */ +#include "access/heapam.h" /* for ACL checking */ +#include "utils/syscache.h" +#include "utils/acl.h" +#include "utils/builtins.h" +#include "catalog/pg_shadow.h" + +static void checkLockPerms(List *locks, Query *parsetree, int rt_index); + /* * ThisLockWasTriggered * @@ -156,5 +164,98 @@ matchLocks(CmdType event, } } + checkLockPerms(real_locks, parsetree, varno); + return (real_locks); } + + +static void +checkLockPerms(List *locks, Query *parsetree, int rt_index) +{ + Relation ev_rel; + HeapTuple usertup; + char *evowner; + RangeTblEntry *rte; + int32 reqperm; + int32 aclcheck_res; + int i; + List *l; + + if (locks == NIL) + return; + + /* + * Get the usename of the rules event relation owner + */ + rte = (RangeTblEntry *)nth(rt_index - 1, parsetree->rtable); + ev_rel = heap_openr(rte->relname); + usertup = SearchSysCacheTuple(USESYSID, + ObjectIdGetDatum(ev_rel->rd_rel->relowner), + 0, 0, 0); + if (!HeapTupleIsValid(usertup)) + { + elog(ERROR, "cache lookup for userid %d failed", + ev_rel->rd_rel->relowner); + } + heap_close(ev_rel); + evowner = nameout(&(((Form_pg_shadow) GETSTRUCT(usertup))->usename)); + + /* + * Check all the locks, that should get fired on this query + */ + foreach (l, locks) { + RewriteRule *onelock = (RewriteRule *)lfirst(l); + List *action; + + /* + * In each lock check every action + */ + foreach (action, onelock->actions) { + Query *query = (Query *)lfirst(action); + + /* + * In each action check every rangetable entry + * for read/write permission of the event relations + * owner depending on if it's the result relation + * (write) or not (read) + */ + for (i = 2; i < length(query->rtable); i++) { + if (i + 1 == query->resultRelation) + switch (query->resultRelation) { + case CMD_INSERT: + reqperm = ACL_AP; + break; + default: + reqperm = ACL_WR; + break; + } + else + reqperm = ACL_RD; + + rte = (RangeTblEntry *)nth(i, query->rtable); + aclcheck_res = pg_aclcheck(rte->relname, + evowner, reqperm); + if (aclcheck_res != ACLCHECK_OK) { + elog(ERROR, "%s: %s", + rte->relname, + aclcheck_error_strings[aclcheck_res]); + } + + /* + * So this is allowed due to the permissions + * of the rules event relation owner. But + * let's see if the next one too + */ + rte->skipAcl = TRUE; + } + } + } + + /* + * Phew, that was close + */ + return; +} + + diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c index 4d8ecb8b1e9..c5c3b887867 100644 --- a/src/backend/rewrite/rewriteDefine.c +++ b/src/backend/rewrite/rewriteDefine.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.18 1998/08/19 02:02:29 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.19 1998/08/24 01:37:58 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -131,7 +131,7 @@ InsertRule(char *rulname, rulname, evtype, eventrel_oid, evslot_index, actionbuf, qualbuf, is_instead); - pg_exec_query(rulebuf); + pg_exec_query_acl_override(rulebuf); return (LastOidProcessed); } @@ -192,12 +192,61 @@ DefineQueryRewrite(RuleStmt *stmt) Oid event_attype = 0; char *actionP, *event_qualP; - + List *l; + Query *query; + + /* ---------- + * The current rewrite handler is known to work on relation level + * rules only. And for SELECT events, it expects one non-nothing + * action that is instead. Since we now hand out views and rules + * to regular users, we must deny anything else. + * + * I know that I must write a new rewrite handler from scratch + * for 6.5 so we can remove these checks and allow all the rules. + * + * Jan + * ---------- + */ if (event_obj->attrs) + elog(ERROR, "attribute level rules currently not supported"); + /* eslot_string = strVal(lfirst(event_obj->attrs)); + */ else eslot_string = NULL; + if (action != NIL) + foreach (l, action) { + query = (Query *)lfirst(l); + if (query->resultRelation == 1) { + elog(NOTICE, "rule actions on OLD currently not supported"); + elog(ERROR, " use views or triggers instead"); + } + if (query->resultRelation == 2) { + elog(NOTICE, "rule actions on NEW currently not supported"); + elog(ERROR, " use triggers instead"); + } + } + + if (event_type == CMD_SELECT) { + if (length(action) == 0) { + elog(NOTICE, "instead nothing rules on select currently not supported"); + elog(ERROR, " use views instead"); + } + if (length(action) > 1) { + elog(ERROR, "multiple action rules on select currently not supported"); + } + query = (Query *)lfirst(action); + if (!is_instead || query->commandType != CMD_SELECT) { + elog(ERROR, "only instead-select rules currently supported on select"); + } + } + /* + * This rule is currently allowed - too restricted I know - + * but women and children first + * Jan + */ + event_relation = heap_openr(event_obj->relname); if (event_relation == NULL) elog(ERROR, "virtual relations not supported yet"); diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 68169cbf2d2..02bbc69a8ca 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -6,7 +6,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.19 1998/08/19 02:02:30 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.20 1998/08/24 01:37:59 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -45,7 +45,6 @@ fireRules(Query *parsetree, int rt_index, CmdType event, static void QueryRewriteSubLink(Node *node); static List *QueryRewriteOne(Query *parsetree); static List *deepRewriteQuery(Query *parsetree); -static void CheckViewPerms(Relation view, List *rtable); static void RewritePreprocessQuery(Query *parsetree); static Query *RewritePostprocessNonSelect(Query *parsetree); @@ -273,7 +272,6 @@ ApplyRetrieveRule(Query *parsetree, int nothing, rt_length; int badsql = FALSE; - int viewAclOverride = FALSE; rule_qual = rule->qual; if (rule->actions) @@ -291,19 +289,6 @@ ApplyRetrieveRule(Query *parsetree, return; rule_action = copyObject(lfirst(rule->actions)); nothing = FALSE; - - /* - * If this rule is on the relation level, the rule action is a - * select and the rule is instead then it must be a view. - * Permissions for views now follow the owner of the view, not the - * current user. - */ - if (relation_level && rule_action->commandType == CMD_SELECT - && rule->isInstead) - { - CheckViewPerms(relation, rule_action->rtable); - viewAclOverride = TRUE; - } } else nothing = TRUE; @@ -321,28 +306,7 @@ ApplyRetrieveRule(Query *parsetree, } rt_length = length(rtable); - if (viewAclOverride) - { - List *rule_rtable, - *rule_rt; - RangeTblEntry *rte; - - rule_rtable = copyObject(rule_action->rtable); - foreach(rule_rt, rule_rtable) - { - rte = lfirst(rule_rt); - - /* - * tell the executor that the ACL check on this range table - * entry is already done - */ - rte->skipAcl = true; - } - - rtable = nconc(rtable, rule_rtable); - } - else - rtable = nconc(rtable, copyObject(rule_action->rtable)); + rtable = nconc(rtable, copyObject(rule_action->rtable)); parsetree->rtable = rtable; rule_action->rtable = rtable; @@ -425,6 +389,8 @@ ProcessRetrieveQuery(Query *parsetree, if (rule) return NIL; + rt_index = 0; + foreach(rt, rtable) { RangeTblEntry *rt_entry = lfirst(rt); @@ -537,6 +503,44 @@ fireRules(Query *parsetree, List *r; bool orig_instead_flag = *instead_flag; + /* + * Instead rules change the resultRelation of the + * query. So the permission checks on the initial + * resultRelation would never be done (this is + * normally done in the executor deep down). So + * we must do it here. The result relations resulting + * from earlier rewrites are already checked against + * the rules eventrelation owner (during matchLocks) + * and have the skipAcl flag set. + */ + if (rule_lock->isInstead && + parsetree->commandType != CMD_SELECT) { + RangeTblEntry *rte; + int32 acl_rc; + int32 reqperm; + + switch (parsetree->commandType) { + case CMD_INSERT: + reqperm = ACL_AP; + break; + default: + reqperm = ACL_WR; + break; + } + + rte = (RangeTblEntry *)nth(parsetree->resultRelation - 1, + parsetree->rtable); + if (!rte->skipAcl) { + acl_rc = pg_aclcheck(rte->relname, + GetPgUserName(), reqperm); + if (acl_rc != ACLCHECK_OK) { + elog(ERROR, "%s: %s", + rte->relname, + aclcheck_error_strings[acl_rc]); + } + } + } + /* multiple rule action time */ *instead_flag = rule_lock->isInstead; event_qual = rule_lock->qual; @@ -1024,42 +1028,3 @@ deepRewriteQuery(Query *parsetree) return rewritten; } - - -static void -CheckViewPerms(Relation view, List *rtable) -{ - HeapTuple utup; - NameData uname; - List *rt; - RangeTblEntry *rte; - int32 aclcheck_res; - - /* - * get the usename of the view's owner - */ - utup = SearchSysCacheTuple(USESYSID, - ObjectIdGetDatum(view->rd_rel->relowner), - 0, 0, 0); - if (!HeapTupleIsValid(utup)) - { - elog(ERROR, "cache lookup for userid %d failed", - view->rd_rel->relowner); - } - StrNCpy(uname.data, - ((Form_pg_shadow) GETSTRUCT(utup))->usename.data, - NAMEDATALEN); - - /* - * check that we have read access to all the classes in the range - * table of the view - */ - foreach(rt, rtable) - { - rte = (RangeTblEntry *) lfirst(rt); - - aclcheck_res = pg_aclcheck(rte->relname, uname.data, ACL_RD); - if (aclcheck_res != ACLCHECK_OK) - elog(ERROR, "%s: %s", rte->relname, aclcheck_error_strings[aclcheck_res]); - } -} diff --git a/src/backend/rewrite/rewriteSupport.c b/src/backend/rewrite/rewriteSupport.c index dae10410809..4c17cccb7f7 100644 --- a/src/backend/rewrite/rewriteSupport.c +++ b/src/backend/rewrite/rewriteSupport.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.25 1998/08/19 02:02:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.26 1998/08/24 01:38:01 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -158,6 +158,10 @@ prs2_addToRelation(Oid relid, */ oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); thisRule = (RewriteRule *) palloc(sizeof(RewriteRule)); + if (qual != NULL) + qual = copyObject(qual); + if (actions != NIL) + actions = copyObject(actions); MemoryContextSwitchTo(oldcxt); thisRule->ruleId = ruleId; |