Commit 7b30490b authored by Marc G. Fournier's avatar Marc G. Fournier

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;
parent 73432884
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -299,6 +299,17 @@ ExecCheckPerms(CmdType operation,
{ {
RangeTblEntry *rte = lfirst(lp); 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; relid = rte->relid;
htp = SearchSysCacheTuple(RELOID, htp = SearchSysCacheTuple(RELOID,
ObjectIdGetDatum(relid), ObjectIdGetDatum(relid),
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -1495,6 +1495,7 @@ _copyRangeTblEntry(RangeTblEntry *from)
newnode->relid = from->relid; newnode->relid = from->relid;
newnode->inh = from->inh; newnode->inh = from->inh;
newnode->inFromCl = from->inFromCl; newnode->inFromCl = from->inFromCl;
newnode->skipAcl = from->skipAcl;
return newnode; return newnode;
......
...@@ -210,7 +210,7 @@ ...@@ -210,7 +210,7 @@
* *
* *
* IDENTIFICATION * 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 * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -3753,7 +3753,7 @@ static const short yycheck[] = { 3, ...@@ -3753,7 +3753,7 @@ static const short yycheck[] = { 3,
-1, -1, -1, 172 -1, -1, -1, 172
}; };
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ /* -*-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, /* Skeleton output parser for bison,
Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
...@@ -3946,7 +3946,7 @@ __yy_memcpy (char *to, char *from, int count) ...@@ -3946,7 +3946,7 @@ __yy_memcpy (char *to, char *from, int count)
#endif #endif
#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 /* The user can define YYPARSE_PARAM as the name of an argument to be passed
into yyparse. The argument should have type void *. into yyparse. The argument should have type void *.
...@@ -9401,7 +9401,7 @@ case 842: ...@@ -9401,7 +9401,7 @@ case 842:
break;} break;}
} }
/* the action file gets copied in in place of this dollarsign */ /* 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; yyvsp -= yylen;
yyssp -= yylen; yyssp -= yylen;
......
/* A lexical scanner generated by flex */ /* A lexical scanner generated by flex */
/* Scanner skeleton version: /* 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 #define FLEX_SCANNER
...@@ -547,7 +547,7 @@ char *yytext; ...@@ -547,7 +547,7 @@ char *yytext;
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
......
...@@ -6,10 +6,11 @@ ...@@ -6,10 +6,11 @@
* *
* *
* IDENTIFICATION * 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 <string.h>
#include "postgres.h" #include "postgres.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "utils/palloc.h" #include "utils/palloc.h"
...@@ -29,13 +30,19 @@ ...@@ -29,13 +30,19 @@
#include "commands/creatinh.h" #include "commands/creatinh.h"
#include "access/heapam.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, 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, static List *fireRules(Query *parsetree, int rt_index, CmdType event,
bool *instead_flag, List *locks, List **qual_products); bool *instead_flag, List *locks, List **qual_products);
static void QueryRewriteSubLink(Node *node); static void QueryRewriteSubLink(Node *node);
static List *QueryRewriteOne(Query *parsetree); static List *QueryRewriteOne(Query *parsetree);
static List *deepRewriteQuery(Query *parsetree); static List *deepRewriteQuery(Query *parsetree);
static void CheckViewPerms(Relation view, List *rtable);
/* /*
* gatherRewriteMeta - * gatherRewriteMeta -
...@@ -219,7 +226,7 @@ FireRetrieveRulesAtQuery(Query *parsetree, ...@@ -219,7 +226,7 @@ FireRetrieveRulesAtQuery(Query *parsetree,
*instead_flag = TRUE; *instead_flag = TRUE;
return rule_lock->actions; return rule_lock->actions;
} }
ApplyRetrieveRule(parsetree, rule_lock, rt_index, relation_level, ApplyRetrieveRule(parsetree, rule_lock, rt_index, relation_level, relation,
&modified); &modified);
if (modified) if (modified)
{ {
...@@ -247,6 +254,7 @@ ApplyRetrieveRule(Query *parsetree, ...@@ -247,6 +254,7 @@ ApplyRetrieveRule(Query *parsetree,
RewriteRule *rule, RewriteRule *rule,
int rt_index, int rt_index,
int relation_level, int relation_level,
Relation relation,
int *modified) int *modified)
{ {
Query *rule_action = NULL; Query *rule_action = NULL;
...@@ -256,16 +264,41 @@ ApplyRetrieveRule(Query *parsetree, ...@@ -256,16 +264,41 @@ ApplyRetrieveRule(Query *parsetree,
int nothing, int nothing,
rt_length; rt_length;
int badsql = FALSE; int badsql = FALSE;
int viewAclOverride = FALSE;
rule_qual = rule->qual; rule_qual = rule->qual;
if (rule->actions) if (rule->actions)
{ {
if (length(rule->actions) > 1) /* ??? because we don't handle if (length(rule->actions) > 1) /* ??? because we don't handle
* rules with more than one * rules with more than one
* action? -ay */ * 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; return;
rule_action = copyObject(lfirst(rule->actions)); rule_action = copyObject(lfirst(rule->actions));
nothing = FALSE; 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 else
{ {
...@@ -284,7 +317,30 @@ ApplyRetrieveRule(Query *parsetree, ...@@ -284,7 +317,30 @@ ApplyRetrieveRule(Query *parsetree,
rte->inFromCl = false; rte->inFromCl = false;
} }
rt_length = length(rtable); 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; parsetree->rtable = rtable;
rule_action->rtable = rtable; rule_action->rtable = rtable;
...@@ -750,3 +806,45 @@ deepRewriteQuery(Query *parsetree) ...@@ -750,3 +806,45 @@ deepRewriteQuery(Query *parsetree)
return rewritten; 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]);
}
}
}
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * 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 ...@@ -864,6 +864,7 @@ typedef struct RangeTblEntry
Oid relid; Oid relid;
bool inh; /* inheritance? */ bool inh; /* inheritance? */
bool inFromCl; /* comes from From Clause */ bool inFromCl; /* comes from From Clause */
bool skipAcl; /* skip ACL check in executor */
} RangeTblEntry; } RangeTblEntry;
/* /*
......
SUBDIRS = include lib preproc doc SUBDIRS = include lib preproc doc
all install uninstall clean: all install uninstall clean:
$(MAKE) -C include $@
$(MAKE) -C lib $@ $(MAKE) -C lib $@
$(MAKE) -C preproc $@ $(MAKE) -C preproc $@
# $(MAKE) -C doc $@
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment