diff options
Diffstat (limited to 'src/backend/rewrite/locks.c')
-rw-r--r-- | src/backend/rewrite/locks.c | 103 |
1 files changed, 102 insertions, 1 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; +} + + |