mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
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;
This commit is contained in:
@ -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,
|
|||||||
{
|
{
|
||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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,
|
|||||||
-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)
|
|||||||
#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:
|
|||||||
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;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* 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;
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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 @@
|
|||||||
#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,
|
|||||||
*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,
|
|||||||
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,6 +264,7 @@ 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)
|
||||||
@ -263,9 +272,33 @@ ApplyRetrieveRule(Query *parsetree,
|
|||||||
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,
|
|||||||
rte->inFromCl = false;
|
rte->inFromCl = false;
|
||||||
}
|
}
|
||||||
rt_length = length(rtable);
|
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;
|
parsetree->rtable = rtable;
|
||||||
|
|
||||||
rule_action->rtable = rtable;
|
rule_action->rtable = rtable;
|
||||||
@ -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 @@
|
|||||||
*
|
*
|
||||||
* 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
|
|||||||
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;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
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 $@
|
|
||||||
|
Reference in New Issue
Block a user