From 7b30490bc9cebef913f6f95cd0487a3c6989dafa Mon Sep 17 00:00:00 2001 From: "Marc G. Fournier" Date: Sat, 21 Feb 1998 06:32:15 +0000 Subject: [PATCH] First step done, below is the patch to have views to override the permission checks for the accessed tables. Now we can do the following: CREATE VIEW db_user AS SELECT usename, usesysid, usecreatedb, usetrace, usecatupd, '**********'::text as passwd, valuntil FROM pg_user; REVOKE ALL ON pg_user FROM public; REVOKE ALL ON db_user FROM public; GRANT SELECT ON db_user TO public; --- src/backend/executor/execMain.c | 13 +++- src/backend/nodes/copyfuncs.c | 3 +- src/backend/parser/gram.c | 8 +- src/backend/parser/scan.c | 4 +- src/backend/rewrite/rewriteHandler.c | 110 +++++++++++++++++++++++++-- src/include/nodes/parsenodes.h | 3 +- src/interfaces/ecpg/Makefile | 2 - 7 files changed, 126 insertions(+), 17 deletions(-) diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 8702ede248..760d277dee 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.42 1998/02/13 03:26:38 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.43 1998/02/21 06:31:37 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -299,6 +299,17 @@ ExecCheckPerms(CmdType operation, { RangeTblEntry *rte = lfirst(lp); + if (rte->skipAcl) + { + /* + * This happens if the access to this table is due + * to a view query rewriting - the rewrite handler + * checked the permissions against the view owner, + * so we just skip this entry. + */ + continue; + } + relid = rte->relid; htp = SearchSysCacheTuple(RELOID, ObjectIdGetDatum(relid), diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 35dec7f1d9..344b409519 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.38 1998/02/13 03:27:42 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.39 1998/02/21 06:31:40 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -1495,6 +1495,7 @@ _copyRangeTblEntry(RangeTblEntry *from) newnode->relid = from->relid; newnode->inh = from->inh; newnode->inFromCl = from->inFromCl; + newnode->skipAcl = from->skipAcl; return newnode; diff --git a/src/backend/parser/gram.c b/src/backend/parser/gram.c index 142f33fc23..cbf49d2b60 100644 --- a/src/backend/parser/gram.c +++ b/src/backend/parser/gram.c @@ -210,7 +210,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/Attic/gram.c,v 2.1 1998/02/18 07:28:06 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/Attic/gram.c,v 2.2 1998/02/21 06:31:46 scrappy Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -3753,7 +3753,7 @@ static const short yycheck[] = { 3, -1, -1, -1, 172 }; /* -*-C-*- Note some compilers choke on comments on `#line' lines. */ -#line 3 "/usr/lib/bison.simple" +#line 3 "/usr/share/misc/bison.simple" /* Skeleton output parser for bison, Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. @@ -3946,7 +3946,7 @@ __yy_memcpy (char *to, char *from, int count) #endif #endif -#line 196 "/usr/lib/bison.simple" +#line 196 "/usr/share/misc/bison.simple" /* The user can define YYPARSE_PARAM as the name of an argument to be passed into yyparse. The argument should have type void *. @@ -9401,7 +9401,7 @@ case 842: break;} } /* the action file gets copied in in place of this dollarsign */ -#line 498 "/usr/lib/bison.simple" +#line 498 "/usr/share/misc/bison.simple" yyvsp -= yylen; yyssp -= yylen; diff --git a/src/backend/parser/scan.c b/src/backend/parser/scan.c index 6abb33ffda..4fda82c955 100644 --- a/src/backend/parser/scan.c +++ b/src/backend/parser/scan.c @@ -1,7 +1,7 @@ /* A lexical scanner generated by flex */ /* Scanner skeleton version: - * $Header: /cvsroot/pgsql/src/backend/parser/Attic/scan.c,v 1.14 1998/02/18 07:23:22 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/Attic/scan.c,v 1.15 1998/02/21 06:31:52 scrappy Exp $ */ #define FLEX_SCANNER @@ -547,7 +547,7 @@ char *yytext; * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/Attic/scan.c,v 1.14 1998/02/18 07:23:22 thomas Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/Attic/scan.c,v 1.15 1998/02/21 06:31:52 scrappy Exp $ * *------------------------------------------------------------------------- */ diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c index 415ce6e80f..1191507685 100644 --- a/src/backend/rewrite/rewriteHandler.c +++ b/src/backend/rewrite/rewriteHandler.c @@ -6,10 +6,11 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.11 1998/01/21 04:24:36 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.12 1998/02/21 06:31:57 scrappy Exp $ * *------------------------------------------------------------------------- */ +#include #include "postgres.h" #include "miscadmin.h" #include "utils/palloc.h" @@ -29,13 +30,19 @@ #include "commands/creatinh.h" #include "access/heapam.h" +#include "utils/syscache.h" +#include "utils/acl.h" +#include "catalog/pg_user.h" + static void ApplyRetrieveRule(Query *parsetree, RewriteRule *rule, - int rt_index, int relation_level, int *modified); + int rt_index, int relation_level, + Relation relation, int *modified); static List *fireRules(Query *parsetree, int rt_index, CmdType event, bool *instead_flag, List *locks, List **qual_products); static void QueryRewriteSubLink(Node *node); static List *QueryRewriteOne(Query *parsetree); static List *deepRewriteQuery(Query *parsetree); +static void CheckViewPerms(Relation view, List *rtable); /* * gatherRewriteMeta - @@ -219,7 +226,7 @@ FireRetrieveRulesAtQuery(Query *parsetree, *instead_flag = TRUE; return rule_lock->actions; } - ApplyRetrieveRule(parsetree, rule_lock, rt_index, relation_level, + ApplyRetrieveRule(parsetree, rule_lock, rt_index, relation_level, relation, &modified); if (modified) { @@ -247,6 +254,7 @@ ApplyRetrieveRule(Query *parsetree, RewriteRule *rule, int rt_index, int relation_level, + Relation relation, int *modified) { Query *rule_action = NULL; @@ -256,16 +264,41 @@ ApplyRetrieveRule(Query *parsetree, int nothing, rt_length; int badsql = FALSE; + int viewAclOverride = FALSE; rule_qual = rule->qual; if (rule->actions) { if (length(rule->actions) > 1) /* ??? because we don't handle - * rules with more than one - * action? -ay */ + * rules with more than one + * action? -ay */ + + /* WARNING!!! + * If we sometimes handle + * rules with more than one + * action, the view acl checks + * might get broken. + * viewAclOverride should only + * become true (below) if this + * is a relation_level, instead, + * select query - Jan + */ 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 { @@ -284,7 +317,30 @@ ApplyRetrieveRule(Query *parsetree, rte->inFromCl = false; } rt_length = length(rtable); - rtable = nconc(rtable, copyObject(rule_action->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)); + } parsetree->rtable = rtable; rule_action->rtable = rtable; @@ -750,3 +806,45 @@ 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, 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_user) 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/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 108949f8c7..f91e115373 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: parsenodes.h,v 1.47 1998/02/10 16:04:26 momjian Exp $ + * $Id: parsenodes.h,v 1.48 1998/02/21 06:32:02 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -864,6 +864,7 @@ typedef struct RangeTblEntry Oid relid; bool inh; /* inheritance? */ bool inFromCl; /* comes from From Clause */ + bool skipAcl; /* skip ACL check in executor */ } RangeTblEntry; /* diff --git a/src/interfaces/ecpg/Makefile b/src/interfaces/ecpg/Makefile index 7c2df8122e..ee99aaeab5 100644 --- a/src/interfaces/ecpg/Makefile +++ b/src/interfaces/ecpg/Makefile @@ -1,7 +1,5 @@ SUBDIRS = include lib preproc doc all install uninstall clean: - $(MAKE) -C include $@ $(MAKE) -C lib $@ $(MAKE) -C preproc $@ -# $(MAKE) -C doc $@ -- GitLab