aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/rewrite')
-rw-r--r--src/backend/rewrite/locks.c103
-rw-r--r--src/backend/rewrite/rewriteDefine.c55
-rw-r--r--src/backend/rewrite/rewriteHandler.c119
-rw-r--r--src/backend/rewrite/rewriteSupport.c6
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;