Fix permission-checking bug reported by Tim Burgess 10-Feb-03 (this time
for sure...). Rather than relying on the query context of a rangetable entry to identify what permissions it wants checked, store a full AclMode mask in each RTE, and check exactly those bits. This allows an RTE specifying, say, INSERT privilege on a view to be copied into a derived UPDATE query without changing meaning. Per recent discussion thread. initdb forced due to change of stored rule representation.
This commit is contained in:
parent
01d320d421
commit
cfd7fb7ed4
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.80 2004/01/10 23:28:44 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.81 2004/01/14 23:01:54 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -297,8 +297,8 @@ UpdateRangeTableOfViewParse(Oid viewOid, Query *viewParse)
|
|||||||
makeAlias("*NEW*", NIL),
|
makeAlias("*NEW*", NIL),
|
||||||
false, false);
|
false, false);
|
||||||
/* Must override addRangeTableEntry's default access-check flags */
|
/* Must override addRangeTableEntry's default access-check flags */
|
||||||
rt_entry1->checkForRead = false;
|
rt_entry1->requiredPerms = 0;
|
||||||
rt_entry2->checkForRead = false;
|
rt_entry2->requiredPerms = 0;
|
||||||
|
|
||||||
new_rt = lcons(rt_entry1, lcons(rt_entry2, viewParse->rtable));
|
new_rt = lcons(rt_entry1, lcons(rt_entry2, viewParse->rtable));
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.226 2004/01/10 23:28:44 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.227 2004/01/14 23:01:54 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -86,8 +86,8 @@ static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid,
|
|||||||
EState *estate);
|
EState *estate);
|
||||||
static TupleTableSlot *EvalPlanQualNext(EState *estate);
|
static TupleTableSlot *EvalPlanQualNext(EState *estate);
|
||||||
static void EndEvalPlanQual(EState *estate);
|
static void EndEvalPlanQual(EState *estate);
|
||||||
static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation);
|
static void ExecCheckRTEPerms(RangeTblEntry *rte);
|
||||||
static void ExecCheckXactReadOnly(Query *parsetree, CmdType operation);
|
static void ExecCheckXactReadOnly(Query *parsetree);
|
||||||
static void EvalPlanQualStart(evalPlanQual *epq, EState *estate,
|
static void EvalPlanQualStart(evalPlanQual *epq, EState *estate,
|
||||||
evalPlanQual *priorepq);
|
evalPlanQual *priorepq);
|
||||||
static void EvalPlanQualStop(evalPlanQual *epq);
|
static void EvalPlanQualStop(evalPlanQual *epq);
|
||||||
@ -136,8 +136,8 @@ ExecutorStart(QueryDesc *queryDesc, bool useCurrentSnapshot, bool explainOnly)
|
|||||||
* If the transaction is read-only, we need to check if any writes are
|
* If the transaction is read-only, we need to check if any writes are
|
||||||
* planned to non-temporary tables.
|
* planned to non-temporary tables.
|
||||||
*/
|
*/
|
||||||
if (!explainOnly)
|
if (XactReadOnly && !explainOnly)
|
||||||
ExecCheckXactReadOnly(queryDesc->parsetree, queryDesc->operation);
|
ExecCheckXactReadOnly(queryDesc->parsetree);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build EState, switch into per-query memory context for startup.
|
* Build EState, switch into per-query memory context for startup.
|
||||||
@ -351,7 +351,7 @@ ExecutorRewind(QueryDesc *queryDesc)
|
|||||||
* Check access permissions for all relations listed in a range table.
|
* Check access permissions for all relations listed in a range table.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ExecCheckRTPerms(List *rangeTable, CmdType operation)
|
ExecCheckRTPerms(List *rangeTable)
|
||||||
{
|
{
|
||||||
List *lp;
|
List *lp;
|
||||||
|
|
||||||
@ -359,7 +359,7 @@ ExecCheckRTPerms(List *rangeTable, CmdType operation)
|
|||||||
{
|
{
|
||||||
RangeTblEntry *rte = lfirst(lp);
|
RangeTblEntry *rte = lfirst(lp);
|
||||||
|
|
||||||
ExecCheckRTEPerms(rte, operation);
|
ExecCheckRTEPerms(rte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,18 +368,18 @@ ExecCheckRTPerms(List *rangeTable, CmdType operation)
|
|||||||
* Check access permissions for a single RTE.
|
* Check access permissions for a single RTE.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
|
ExecCheckRTEPerms(RangeTblEntry *rte)
|
||||||
{
|
{
|
||||||
|
AclMode requiredPerms;
|
||||||
Oid relOid;
|
Oid relOid;
|
||||||
AclId userid;
|
AclId userid;
|
||||||
AclResult aclcheck_result;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If it's a subquery, recursively examine its rangetable.
|
* If it's a subquery, recursively examine its rangetable.
|
||||||
*/
|
*/
|
||||||
if (rte->rtekind == RTE_SUBQUERY)
|
if (rte->rtekind == RTE_SUBQUERY)
|
||||||
{
|
{
|
||||||
ExecCheckRTPerms(rte->subquery->rtable, operation);
|
ExecCheckRTPerms(rte->subquery->rtable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,6 +391,13 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
|
|||||||
if (rte->rtekind != RTE_RELATION)
|
if (rte->rtekind != RTE_RELATION)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No work if requiredPerms is empty.
|
||||||
|
*/
|
||||||
|
requiredPerms = rte->requiredPerms;
|
||||||
|
if (requiredPerms == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
relOid = rte->relid;
|
relOid = rte->relid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -404,77 +411,68 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
|
|||||||
*/
|
*/
|
||||||
userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
|
userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
|
||||||
|
|
||||||
#define CHECK(MODE) pg_class_aclcheck(relOid, userid, MODE)
|
/*
|
||||||
|
* For each bit in requiredPerms, apply the required check. (We can't
|
||||||
|
* do this in one aclcheck call because aclcheck treats multiple bits
|
||||||
|
* as OR semantics, when we want AND.)
|
||||||
|
*
|
||||||
|
* We use a well-known cute trick for isolating the rightmost one-bit
|
||||||
|
* in a nonzero word. See nodes/bitmapset.c for commentary.
|
||||||
|
*/
|
||||||
|
#define RIGHTMOST_ONE(x) ((int32) (x) & -((int32) (x)))
|
||||||
|
|
||||||
if (rte->checkForRead)
|
while (requiredPerms != 0)
|
||||||
{
|
{
|
||||||
aclcheck_result = CHECK(ACL_SELECT);
|
AclMode thisPerm;
|
||||||
if (aclcheck_result != ACLCHECK_OK)
|
AclResult aclcheck_result;
|
||||||
aclcheck_error(aclcheck_result, ACL_KIND_CLASS,
|
|
||||||
get_rel_name(relOid));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rte->checkForWrite)
|
thisPerm = RIGHTMOST_ONE(requiredPerms);
|
||||||
{
|
requiredPerms &= ~thisPerm;
|
||||||
/*
|
|
||||||
* Note: write access in a SELECT context means SELECT FOR UPDATE.
|
aclcheck_result = pg_class_aclcheck(relOid, userid, thisPerm);
|
||||||
* Right now we don't distinguish that from true update as far as
|
|
||||||
* permissions checks are concerned.
|
|
||||||
*/
|
|
||||||
switch (operation)
|
|
||||||
{
|
|
||||||
case CMD_INSERT:
|
|
||||||
aclcheck_result = CHECK(ACL_INSERT);
|
|
||||||
break;
|
|
||||||
case CMD_SELECT:
|
|
||||||
case CMD_UPDATE:
|
|
||||||
aclcheck_result = CHECK(ACL_UPDATE);
|
|
||||||
break;
|
|
||||||
case CMD_DELETE:
|
|
||||||
aclcheck_result = CHECK(ACL_DELETE);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
elog(ERROR, "unrecognized operation code: %d",
|
|
||||||
(int) operation);
|
|
||||||
aclcheck_result = ACLCHECK_OK; /* keep compiler quiet */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (aclcheck_result != ACLCHECK_OK)
|
if (aclcheck_result != ACLCHECK_OK)
|
||||||
aclcheck_error(aclcheck_result, ACL_KIND_CLASS,
|
aclcheck_error(aclcheck_result, ACL_KIND_CLASS,
|
||||||
get_rel_name(relOid));
|
get_rel_name(relOid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that the query does not imply any writes to non-temp tables.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
ExecCheckXactReadOnly(Query *parsetree, CmdType operation)
|
ExecCheckXactReadOnly(Query *parsetree)
|
||||||
{
|
{
|
||||||
if (!XactReadOnly)
|
List *lp;
|
||||||
return;
|
|
||||||
|
|
||||||
/* CREATE TABLE AS or SELECT INTO */
|
/*
|
||||||
if (operation == CMD_SELECT && parsetree->into != NULL)
|
* CREATE TABLE AS or SELECT INTO?
|
||||||
|
*
|
||||||
|
* XXX should we allow this if the destination is temp?
|
||||||
|
*/
|
||||||
|
if (parsetree->into != NULL)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (operation == CMD_DELETE || operation == CMD_INSERT
|
/* Fail if write permissions are requested on any non-temp table */
|
||||||
|| operation == CMD_UPDATE)
|
foreach(lp, parsetree->rtable)
|
||||||
{
|
{
|
||||||
List *lp;
|
RangeTblEntry *rte = lfirst(lp);
|
||||||
|
|
||||||
foreach(lp, parsetree->rtable)
|
if (rte->rtekind == RTE_SUBQUERY)
|
||||||
{
|
{
|
||||||
RangeTblEntry *rte = lfirst(lp);
|
ExecCheckXactReadOnly(rte->subquery);
|
||||||
|
continue;
|
||||||
if (rte->rtekind != RTE_RELATION)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!rte->checkForWrite)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (isTempNamespace(get_rel_namespace(rte->relid)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
goto fail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rte->rtekind != RTE_RELATION)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((rte->requiredPerms & (~ACL_SELECT)) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (isTempNamespace(get_rel_namespace(rte->relid)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -511,7 +509,7 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
|
|||||||
* rangetable here --- subplan RTEs will be checked during
|
* rangetable here --- subplan RTEs will be checked during
|
||||||
* ExecInitSubPlan().
|
* ExecInitSubPlan().
|
||||||
*/
|
*/
|
||||||
ExecCheckRTPerms(parseTree->rtable, operation);
|
ExecCheckRTPerms(parseTree->rtable);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get information from query descriptor
|
* get information from query descriptor
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.59 2003/11/29 19:51:48 pgsql Exp $
|
* $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.60 2004/01/14 23:01:54 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -670,10 +670,9 @@ ExecInitSubPlan(SubPlanState *node, EState *estate)
|
|||||||
MemoryContext oldcontext;
|
MemoryContext oldcontext;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do access checking on the rangetable entries in the subquery. Here,
|
* Do access checking on the rangetable entries in the subquery.
|
||||||
* we assume the subquery is a SELECT.
|
|
||||||
*/
|
*/
|
||||||
ExecCheckRTPerms(subplan->rtable, CMD_SELECT);
|
ExecCheckRTPerms(subplan->rtable);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* initialize my state
|
* initialize my state
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.276 2004/01/10 23:28:44 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.277 2004/01/14 23:01:54 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1258,8 +1258,7 @@ _copyRangeTblEntry(RangeTblEntry *from)
|
|||||||
COPY_NODE_FIELD(eref);
|
COPY_NODE_FIELD(eref);
|
||||||
COPY_SCALAR_FIELD(inh);
|
COPY_SCALAR_FIELD(inh);
|
||||||
COPY_SCALAR_FIELD(inFromCl);
|
COPY_SCALAR_FIELD(inFromCl);
|
||||||
COPY_SCALAR_FIELD(checkForRead);
|
COPY_SCALAR_FIELD(requiredPerms);
|
||||||
COPY_SCALAR_FIELD(checkForWrite);
|
|
||||||
COPY_SCALAR_FIELD(checkAsUser);
|
COPY_SCALAR_FIELD(checkAsUser);
|
||||||
|
|
||||||
return newnode;
|
return newnode;
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.214 2004/01/10 23:28:45 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.215 2004/01/14 23:01:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1574,8 +1574,7 @@ _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
|
|||||||
COMPARE_NODE_FIELD(eref);
|
COMPARE_NODE_FIELD(eref);
|
||||||
COMPARE_SCALAR_FIELD(inh);
|
COMPARE_SCALAR_FIELD(inh);
|
||||||
COMPARE_SCALAR_FIELD(inFromCl);
|
COMPARE_SCALAR_FIELD(inFromCl);
|
||||||
COMPARE_SCALAR_FIELD(checkForRead);
|
COMPARE_SCALAR_FIELD(requiredPerms);
|
||||||
COMPARE_SCALAR_FIELD(checkForWrite);
|
|
||||||
COMPARE_SCALAR_FIELD(checkAsUser);
|
COMPARE_SCALAR_FIELD(checkAsUser);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.229 2004/01/06 04:31:01 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.230 2004/01/14 23:01:55 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Every node type that can appear in stored rules' parsetrees *must*
|
* Every node type that can appear in stored rules' parsetrees *must*
|
||||||
@ -1358,9 +1358,8 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
|
|||||||
|
|
||||||
WRITE_BOOL_FIELD(inh);
|
WRITE_BOOL_FIELD(inh);
|
||||||
WRITE_BOOL_FIELD(inFromCl);
|
WRITE_BOOL_FIELD(inFromCl);
|
||||||
WRITE_BOOL_FIELD(checkForRead);
|
WRITE_UINT_FIELD(requiredPerms);
|
||||||
WRITE_BOOL_FIELD(checkForWrite);
|
WRITE_UINT_FIELD(checkAsUser);
|
||||||
WRITE_OID_FIELD(checkAsUser);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.164 2004/01/07 18:56:26 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.165 2004/01/14 23:01:55 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Path and Plan nodes do not have any readfuncs support, because we
|
* Path and Plan nodes do not have any readfuncs support, because we
|
||||||
@ -939,9 +939,8 @@ _readRangeTblEntry(void)
|
|||||||
|
|
||||||
READ_BOOL_FIELD(inh);
|
READ_BOOL_FIELD(inh);
|
||||||
READ_BOOL_FIELD(inFromCl);
|
READ_BOOL_FIELD(inFromCl);
|
||||||
READ_BOOL_FIELD(checkForRead);
|
READ_UINT_FIELD(requiredPerms);
|
||||||
READ_BOOL_FIELD(checkForWrite);
|
READ_UINT_FIELD(checkAsUser);
|
||||||
READ_OID_FIELD(checkAsUser);
|
|
||||||
|
|
||||||
READ_DONE();
|
READ_DONE();
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.111 2004/01/05 05:07:35 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.112 2004/01/14 23:01:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -227,8 +227,7 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel,
|
|||||||
* it examines the parent's inheritlist entry. There's no need to
|
* it examines the parent's inheritlist entry. There's no need to
|
||||||
* check twice, so turn off access check bits in the original RTE.
|
* check twice, so turn off access check bits in the original RTE.
|
||||||
*/
|
*/
|
||||||
rte->checkForRead = false;
|
rte->requiredPerms = 0;
|
||||||
rte->checkForWrite = false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize to compute size estimates for whole inheritance tree
|
* Initialize to compute size estimates for whole inheritance tree
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.295 2004/01/11 04:58:17 neilc Exp $
|
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.296 2004/01/14 23:01:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -472,7 +472,8 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
|
|||||||
/* set up range table with just the result rel */
|
/* set up range table with just the result rel */
|
||||||
qry->resultRelation = setTargetTable(pstate, stmt->relation,
|
qry->resultRelation = setTargetTable(pstate, stmt->relation,
|
||||||
interpretInhOption(stmt->relation->inhOpt),
|
interpretInhOption(stmt->relation->inhOpt),
|
||||||
true);
|
true,
|
||||||
|
ACL_DELETE);
|
||||||
|
|
||||||
qry->distinctClause = NIL;
|
qry->distinctClause = NIL;
|
||||||
|
|
||||||
@ -539,7 +540,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt,
|
|||||||
* table is not added to the joinlist or namespace.
|
* table is not added to the joinlist or namespace.
|
||||||
*/
|
*/
|
||||||
qry->resultRelation = setTargetTable(pstate, stmt->relation,
|
qry->resultRelation = setTargetTable(pstate, stmt->relation,
|
||||||
false, false);
|
false, false, ACL_INSERT);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is it INSERT ... SELECT or INSERT ... VALUES?
|
* Is it INSERT ... SELECT or INSERT ... VALUES?
|
||||||
@ -1721,8 +1722,8 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
|
|||||||
makeAlias("*NEW*", NIL),
|
makeAlias("*NEW*", NIL),
|
||||||
false, true);
|
false, true);
|
||||||
/* Must override addRangeTableEntry's default access-check flags */
|
/* Must override addRangeTableEntry's default access-check flags */
|
||||||
oldrte->checkForRead = false;
|
oldrte->requiredPerms = 0;
|
||||||
newrte->checkForRead = false;
|
newrte->requiredPerms = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* They must be in the namespace too for lookup purposes, but only add
|
* They must be in the namespace too for lookup purposes, but only add
|
||||||
@ -1820,8 +1821,8 @@ transformRuleStmt(ParseState *pstate, RuleStmt *stmt,
|
|||||||
newrte = addRangeTableEntry(sub_pstate, stmt->relation,
|
newrte = addRangeTableEntry(sub_pstate, stmt->relation,
|
||||||
makeAlias("*NEW*", NIL),
|
makeAlias("*NEW*", NIL),
|
||||||
false, false);
|
false, false);
|
||||||
oldrte->checkForRead = false;
|
oldrte->requiredPerms = 0;
|
||||||
newrte->checkForRead = false;
|
newrte->requiredPerms = 0;
|
||||||
addRTEtoQuery(sub_pstate, oldrte, false, true);
|
addRTEtoQuery(sub_pstate, oldrte, false, true);
|
||||||
addRTEtoQuery(sub_pstate, newrte, false, true);
|
addRTEtoQuery(sub_pstate, newrte, false, true);
|
||||||
|
|
||||||
@ -2493,7 +2494,8 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
|
|||||||
|
|
||||||
qry->resultRelation = setTargetTable(pstate, stmt->relation,
|
qry->resultRelation = setTargetTable(pstate, stmt->relation,
|
||||||
interpretInhOption(stmt->relation->inhOpt),
|
interpretInhOption(stmt->relation->inhOpt),
|
||||||
true);
|
true,
|
||||||
|
ACL_UPDATE);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the FROM clause is non-standard SQL syntax. We used to be able to
|
* the FROM clause is non-standard SQL syntax. We used to be able to
|
||||||
@ -2880,7 +2882,7 @@ transformForUpdate(Query *qry, List *forUpdate)
|
|||||||
case RTE_RELATION:
|
case RTE_RELATION:
|
||||||
if (!intMember(i, rowMarks)) /* avoid duplicates */
|
if (!intMember(i, rowMarks)) /* avoid duplicates */
|
||||||
rowMarks = lappendi(rowMarks, i);
|
rowMarks = lappendi(rowMarks, i);
|
||||||
rte->checkForWrite = true;
|
rte->requiredPerms |= ACL_SELECT_FOR_UPDATE;
|
||||||
break;
|
break;
|
||||||
case RTE_SUBQUERY:
|
case RTE_SUBQUERY:
|
||||||
/*
|
/*
|
||||||
@ -2915,7 +2917,7 @@ transformForUpdate(Query *qry, List *forUpdate)
|
|||||||
case RTE_RELATION:
|
case RTE_RELATION:
|
||||||
if (!intMember(i, rowMarks)) /* avoid duplicates */
|
if (!intMember(i, rowMarks)) /* avoid duplicates */
|
||||||
rowMarks = lappendi(rowMarks, i);
|
rowMarks = lappendi(rowMarks, i);
|
||||||
rte->checkForWrite = true;
|
rte->requiredPerms |= ACL_SELECT_FOR_UPDATE;
|
||||||
break;
|
break;
|
||||||
case RTE_SUBQUERY:
|
case RTE_SUBQUERY:
|
||||||
/*
|
/*
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.125 2003/11/29 19:51:51 pgsql Exp $
|
* $PostgreSQL: pgsql/src/backend/parser/parse_clause.c,v 1.126 2004/01/14 23:01:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -116,11 +116,14 @@ transformFromClause(ParseState *pstate, List *frmList)
|
|||||||
* to check for namespace conflict; we assume that the namespace was
|
* to check for namespace conflict; we assume that the namespace was
|
||||||
* initially empty in these cases.)
|
* initially empty in these cases.)
|
||||||
*
|
*
|
||||||
|
* Finally, we mark the relation as requiring the permissions specified
|
||||||
|
* by requiredPerms.
|
||||||
|
*
|
||||||
* Returns the rangetable index of the target relation.
|
* Returns the rangetable index of the target relation.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
setTargetTable(ParseState *pstate, RangeVar *relation,
|
setTargetTable(ParseState *pstate, RangeVar *relation,
|
||||||
bool inh, bool alsoSource)
|
bool inh, bool alsoSource, AclMode requiredPerms)
|
||||||
{
|
{
|
||||||
RangeTblEntry *rte;
|
RangeTblEntry *rte;
|
||||||
int rtindex;
|
int rtindex;
|
||||||
@ -149,16 +152,15 @@ setTargetTable(ParseState *pstate, RangeVar *relation,
|
|||||||
Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
|
Assert(rte == rt_fetch(rtindex, pstate->p_rtable));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Override addRangeTableEntry's default checkForRead, and instead
|
* Override addRangeTableEntry's default ACL_SELECT permissions check,
|
||||||
* mark target table as requiring write access.
|
* and instead mark target table as requiring exactly the specified
|
||||||
|
* permissions.
|
||||||
*
|
*
|
||||||
* If we find an explicit reference to the rel later during parse
|
* If we find an explicit reference to the rel later during parse
|
||||||
* analysis, scanRTEForColumn will change checkForRead to 'true'
|
* analysis, scanRTEForColumn will add the ACL_SELECT bit back again.
|
||||||
* again. That can't happen for INSERT but it is possible for UPDATE
|
* That can't happen for INSERT but it is possible for UPDATE and DELETE.
|
||||||
* and DELETE.
|
|
||||||
*/
|
*/
|
||||||
rte->checkForRead = false;
|
rte->requiredPerms = requiredPerms;
|
||||||
rte->checkForWrite = true;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If UPDATE/DELETE, add table to joinlist and namespace.
|
* If UPDATE/DELETE, add table to joinlist and namespace.
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.91 2003/11/29 19:51:52 pgsql Exp $
|
* $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.92 2004/01/14 23:01:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -437,7 +437,7 @@ RTERangeTablePosn(ParseState *pstate, RangeTblEntry *rte, int *sublevels_up)
|
|||||||
* nothing. It might seem that we need to propagate the mark to all the
|
* nothing. It might seem that we need to propagate the mark to all the
|
||||||
* contained RTEs, but that is not necessary. This is so because a join
|
* contained RTEs, but that is not necessary. This is so because a join
|
||||||
* expression can only appear in a FROM clause, and any table named in
|
* expression can only appear in a FROM clause, and any table named in
|
||||||
* FROM will be marked checkForRead from the beginning.
|
* FROM will be marked as requiring read access from the beginning.
|
||||||
*/
|
*/
|
||||||
static Node *
|
static Node *
|
||||||
scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname)
|
scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname)
|
||||||
@ -477,7 +477,8 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname)
|
|||||||
errmsg("column reference \"%s\" is ambiguous",
|
errmsg("column reference \"%s\" is ambiguous",
|
||||||
colname)));
|
colname)));
|
||||||
result = (Node *) make_var(pstate, rte, attnum);
|
result = (Node *) make_var(pstate, rte, attnum);
|
||||||
rte->checkForRead = true;
|
/* Require read access */
|
||||||
|
rte->requiredPerms |= ACL_SELECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,7 +505,8 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname)
|
|||||||
0, 0))
|
0, 0))
|
||||||
{
|
{
|
||||||
result = (Node *) make_var(pstate, rte, attnum);
|
result = (Node *) make_var(pstate, rte, attnum);
|
||||||
rte->checkForRead = true;
|
/* Require read access */
|
||||||
|
rte->requiredPerms |= ACL_SELECT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -689,7 +691,7 @@ addRangeTableEntry(ParseState *pstate,
|
|||||||
* Flags:
|
* Flags:
|
||||||
* - this RTE should be expanded to include descendant tables,
|
* - this RTE should be expanded to include descendant tables,
|
||||||
* - this RTE is in the FROM clause,
|
* - this RTE is in the FROM clause,
|
||||||
* - this RTE should be checked for read/write access rights.
|
* - this RTE should be checked for appropriate access rights.
|
||||||
*
|
*
|
||||||
* The initial default on access checks is always check-for-READ-access,
|
* The initial default on access checks is always check-for-READ-access,
|
||||||
* which is the right thing for all except target tables.
|
* which is the right thing for all except target tables.
|
||||||
@ -697,10 +699,9 @@ addRangeTableEntry(ParseState *pstate,
|
|||||||
*/
|
*/
|
||||||
rte->inh = inh;
|
rte->inh = inh;
|
||||||
rte->inFromCl = inFromCl;
|
rte->inFromCl = inFromCl;
|
||||||
rte->checkForRead = true;
|
|
||||||
rte->checkForWrite = false;
|
|
||||||
|
|
||||||
rte->checkAsUser = InvalidOid; /* not set-uid by default, either */
|
rte->requiredPerms = ACL_SELECT;
|
||||||
|
rte->checkAsUser = 0; /* not set-uid by default, either */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add completed RTE to pstate's range table list, but not to join
|
* Add completed RTE to pstate's range table list, but not to join
|
||||||
@ -784,7 +785,7 @@ addRangeTableEntryForRelation(ParseState *pstate,
|
|||||||
* Flags:
|
* Flags:
|
||||||
* - this RTE should be expanded to include descendant tables,
|
* - this RTE should be expanded to include descendant tables,
|
||||||
* - this RTE is in the FROM clause,
|
* - this RTE is in the FROM clause,
|
||||||
* - this RTE should be checked for read/write access rights.
|
* - this RTE should be checked for appropriate access rights.
|
||||||
*
|
*
|
||||||
* The initial default on access checks is always check-for-READ-access,
|
* The initial default on access checks is always check-for-READ-access,
|
||||||
* which is the right thing for all except target tables.
|
* which is the right thing for all except target tables.
|
||||||
@ -792,10 +793,9 @@ addRangeTableEntryForRelation(ParseState *pstate,
|
|||||||
*/
|
*/
|
||||||
rte->inh = inh;
|
rte->inh = inh;
|
||||||
rte->inFromCl = inFromCl;
|
rte->inFromCl = inFromCl;
|
||||||
rte->checkForRead = true;
|
|
||||||
rte->checkForWrite = false;
|
|
||||||
|
|
||||||
rte->checkAsUser = InvalidOid; /* not set-uid by default, either */
|
rte->requiredPerms = ACL_SELECT;
|
||||||
|
rte->checkAsUser = 0; /* not set-uid by default, either */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add completed RTE to pstate's range table list, but not to join
|
* Add completed RTE to pstate's range table list, but not to join
|
||||||
@ -864,17 +864,16 @@ addRangeTableEntryForSubquery(ParseState *pstate,
|
|||||||
* Flags:
|
* Flags:
|
||||||
* - this RTE should be expanded to include descendant tables,
|
* - this RTE should be expanded to include descendant tables,
|
||||||
* - this RTE is in the FROM clause,
|
* - this RTE is in the FROM clause,
|
||||||
* - this RTE should be checked for read/write access rights.
|
* - this RTE should be checked for appropriate access rights.
|
||||||
*
|
*
|
||||||
* Subqueries are never checked for access rights.
|
* Subqueries are never checked for access rights.
|
||||||
*----------
|
*----------
|
||||||
*/
|
*/
|
||||||
rte->inh = false; /* never true for subqueries */
|
rte->inh = false; /* never true for subqueries */
|
||||||
rte->inFromCl = inFromCl;
|
rte->inFromCl = inFromCl;
|
||||||
rte->checkForRead = false;
|
|
||||||
rte->checkForWrite = false;
|
|
||||||
|
|
||||||
rte->checkAsUser = InvalidOid;
|
rte->requiredPerms = 0;
|
||||||
|
rte->checkAsUser = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add completed RTE to pstate's range table list, but not to join
|
* Add completed RTE to pstate's range table list, but not to join
|
||||||
@ -1034,15 +1033,17 @@ addRangeTableEntryForFunction(ParseState *pstate,
|
|||||||
* Flags:
|
* Flags:
|
||||||
* - this RTE should be expanded to include descendant tables,
|
* - this RTE should be expanded to include descendant tables,
|
||||||
* - this RTE is in the FROM clause,
|
* - this RTE is in the FROM clause,
|
||||||
* - this RTE should be checked for read/write access rights.
|
* - this RTE should be checked for appropriate access rights.
|
||||||
|
*
|
||||||
|
* Functions are never checked for access rights (at least, not by
|
||||||
|
* the RTE permissions mechanism).
|
||||||
*----------
|
*----------
|
||||||
*/
|
*/
|
||||||
rte->inh = false; /* never true for functions */
|
rte->inh = false; /* never true for functions */
|
||||||
rte->inFromCl = inFromCl;
|
rte->inFromCl = inFromCl;
|
||||||
rte->checkForRead = true;
|
|
||||||
rte->checkForWrite = false;
|
|
||||||
|
|
||||||
rte->checkAsUser = InvalidOid;
|
rte->requiredPerms = 0;
|
||||||
|
rte->checkAsUser = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add completed RTE to pstate's range table list, but not to join
|
* Add completed RTE to pstate's range table list, but not to join
|
||||||
@ -1095,17 +1096,16 @@ addRangeTableEntryForJoin(ParseState *pstate,
|
|||||||
* Flags:
|
* Flags:
|
||||||
* - this RTE should be expanded to include descendant tables,
|
* - this RTE should be expanded to include descendant tables,
|
||||||
* - this RTE is in the FROM clause,
|
* - this RTE is in the FROM clause,
|
||||||
* - this RTE should be checked for read/write access rights.
|
* - this RTE should be checked for appropriate access rights.
|
||||||
*
|
*
|
||||||
* Joins are never checked for access rights.
|
* Joins are never checked for access rights.
|
||||||
*----------
|
*----------
|
||||||
*/
|
*/
|
||||||
rte->inh = false; /* never true for joins */
|
rte->inh = false; /* never true for joins */
|
||||||
rte->inFromCl = inFromCl;
|
rte->inFromCl = inFromCl;
|
||||||
rte->checkForRead = false;
|
|
||||||
rte->checkForWrite = false;
|
|
||||||
|
|
||||||
rte->checkAsUser = InvalidOid;
|
rte->requiredPerms = 0;
|
||||||
|
rte->checkAsUser = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add completed RTE to pstate's range table list, but not to join
|
* Add completed RTE to pstate's range table list, but not to join
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.91 2003/11/29 19:51:55 pgsql Exp $
|
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.92 2004/01/14 23:01:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
|
|
||||||
static void setRuleCheckAsUser(Query *qry, AclId userid);
|
static void setRuleCheckAsUser(Query *qry, AclId userid);
|
||||||
static bool setRuleCheckAsUser_walker(Node *node, Oid *context);
|
static bool setRuleCheckAsUser_walker(Node *node, AclId *context);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -494,8 +494,8 @@ DefineQueryRewrite(RuleStmt *stmt)
|
|||||||
* Note: for a view (ON SELECT rule), the checkAsUser field of the *OLD*
|
* Note: for a view (ON SELECT rule), the checkAsUser field of the *OLD*
|
||||||
* RTE entry will be overridden when the view rule is expanded, and the
|
* RTE entry will be overridden when the view rule is expanded, and the
|
||||||
* checkAsUser field of the *NEW* entry is irrelevant because that entry's
|
* checkAsUser field of the *NEW* entry is irrelevant because that entry's
|
||||||
* checkFor bits will never be set. However, for other types of rules it's
|
* requiredPerms bits will always be zero. However, for other types of rules
|
||||||
* important to set these fields to match the rule owner. So we just set
|
* it's important to set these fields to match the rule owner. So we just set
|
||||||
* them always.
|
* them always.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
@ -528,7 +528,7 @@ setRuleCheckAsUser(Query *qry, AclId userid)
|
|||||||
* Expression-tree walker to find sublink queries
|
* Expression-tree walker to find sublink queries
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
setRuleCheckAsUser_walker(Node *node, Oid *context)
|
setRuleCheckAsUser_walker(Node *node, AclId *context)
|
||||||
{
|
{
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.132 2004/01/14 03:39:22 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/rewrite/rewriteHandler.c,v 1.133 2004/01/14 23:01:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -655,13 +655,11 @@ ApplyRetrieveRule(Query *parsetree,
|
|||||||
*/
|
*/
|
||||||
subrte = rt_fetch(PRS2_OLD_VARNO, rule_action->rtable);
|
subrte = rt_fetch(PRS2_OLD_VARNO, rule_action->rtable);
|
||||||
Assert(subrte->relid == relation->rd_id);
|
Assert(subrte->relid == relation->rd_id);
|
||||||
subrte->checkForRead = rte->checkForRead;
|
subrte->requiredPerms = rte->requiredPerms;
|
||||||
subrte->checkForWrite = rte->checkForWrite;
|
|
||||||
subrte->checkAsUser = rte->checkAsUser;
|
subrte->checkAsUser = rte->checkAsUser;
|
||||||
|
|
||||||
rte->checkForRead = false; /* no permission check on subquery itself */
|
rte->requiredPerms = 0; /* no permission check on subquery itself */
|
||||||
rte->checkForWrite = false;
|
rte->checkAsUser = 0;
|
||||||
rte->checkAsUser = InvalidOid;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FOR UPDATE of view?
|
* FOR UPDATE of view?
|
||||||
@ -713,7 +711,7 @@ markQueryForUpdate(Query *qry, bool skipOldNew)
|
|||||||
{
|
{
|
||||||
if (!intMember(rti, qry->rowMarks))
|
if (!intMember(rti, qry->rowMarks))
|
||||||
qry->rowMarks = lappendi(qry->rowMarks, rti);
|
qry->rowMarks = lappendi(qry->rowMarks, rti);
|
||||||
rte->checkForWrite = true;
|
rte->requiredPerms |= ACL_SELECT_FOR_UPDATE;
|
||||||
}
|
}
|
||||||
else if (rte->rtekind == RTE_SUBQUERY)
|
else if (rte->rtekind == RTE_SUBQUERY)
|
||||||
{
|
{
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.215 2004/01/06 23:55:19 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.216 2004/01/14 23:01:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -53,6 +53,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 200401061
|
#define CATALOG_VERSION_NO 200401141
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.104 2003/12/18 20:21:37 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.105 2004/01/14 23:01:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -91,7 +91,7 @@ extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc,
|
|||||||
ScanDirection direction, long count);
|
ScanDirection direction, long count);
|
||||||
extern void ExecutorEnd(QueryDesc *queryDesc);
|
extern void ExecutorEnd(QueryDesc *queryDesc);
|
||||||
extern void ExecutorRewind(QueryDesc *queryDesc);
|
extern void ExecutorRewind(QueryDesc *queryDesc);
|
||||||
extern void ExecCheckRTPerms(List *rangeTable, CmdType operation);
|
extern void ExecCheckRTPerms(List *rangeTable);
|
||||||
extern void ExecEndPlan(PlanState *planstate, EState *estate);
|
extern void ExecEndPlan(PlanState *planstate, EState *estate);
|
||||||
extern void ExecConstraints(ResultRelInfo *resultRelInfo,
|
extern void ExecConstraints(ResultRelInfo *resultRelInfo,
|
||||||
TupleTableSlot *slot, EState *estate);
|
TupleTableSlot *slot, EState *estate);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.252 2004/01/10 23:28:45 neilc Exp $
|
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.253 2004/01/14 23:01:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -27,6 +27,32 @@ typedef enum QuerySource
|
|||||||
QSRC_NON_INSTEAD_RULE /* added by non-INSTEAD rule */
|
QSRC_NON_INSTEAD_RULE /* added by non-INSTEAD rule */
|
||||||
} QuerySource;
|
} QuerySource;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Grantable rights are encoded so that we can OR them together in a bitmask.
|
||||||
|
* The present representation of AclItem limits us to 15 distinct rights,
|
||||||
|
* even though AclMode is defined as uint32. See utils/acl.h.
|
||||||
|
*
|
||||||
|
* Caution: changing these codes breaks stored ACLs, hence forces initdb.
|
||||||
|
*/
|
||||||
|
typedef uint32 AclMode; /* a bitmask of privilege bits */
|
||||||
|
|
||||||
|
#define ACL_INSERT (1<<0) /* for relations */
|
||||||
|
#define ACL_SELECT (1<<1)
|
||||||
|
#define ACL_UPDATE (1<<2)
|
||||||
|
#define ACL_DELETE (1<<3)
|
||||||
|
#define ACL_RULE (1<<4)
|
||||||
|
#define ACL_REFERENCES (1<<5)
|
||||||
|
#define ACL_TRIGGER (1<<6)
|
||||||
|
#define ACL_EXECUTE (1<<7) /* for functions */
|
||||||
|
#define ACL_USAGE (1<<8) /* for languages and namespaces */
|
||||||
|
#define ACL_CREATE (1<<9) /* for namespaces and databases */
|
||||||
|
#define ACL_CREATE_TEMP (1<<10) /* for databases */
|
||||||
|
#define N_ACL_RIGHTS 11 /* 1 plus the last 1<<x */
|
||||||
|
#define ACL_ALL_RIGHTS (-1) /* all-privileges marker in GRANT list */
|
||||||
|
#define ACL_NO_RIGHTS 0
|
||||||
|
/* Currently, SELECT ... FOR UPDATE requires UPDATE privileges */
|
||||||
|
#define ACL_SELECT_FOR_UPDATE ACL_UPDATE
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Query Tree
|
* Query Tree
|
||||||
@ -425,12 +451,13 @@ typedef struct DefElem
|
|||||||
* column names processed later, and it also shouldn't affect the
|
* column names processed later, and it also shouldn't affect the
|
||||||
* expansion of '*'.
|
* expansion of '*'.
|
||||||
*
|
*
|
||||||
* checkForRead, checkForWrite, and checkAsUser control run-time access
|
* requiredPerms and checkAsUser specify run-time access permissions
|
||||||
* permissions checks. A rel will be checked for read or write access
|
* checks to be performed at query startup. The user must have *all*
|
||||||
* (or both, or neither) per checkForRead and checkForWrite. If
|
* of the permissions that are OR'd together in requiredPerms (zero
|
||||||
* checkAsUser is not InvalidOid, then do the permissions checks using
|
* indicates no permissions checking). If checkAsUser is not zero,
|
||||||
* the access rights of that user, not the current effective user ID.
|
* then do the permissions checks using the access rights of that user,
|
||||||
* (This allows rules to act as setuid gateways.)
|
* not the current effective user ID. (This allows rules to act as
|
||||||
|
* setuid gateways.)
|
||||||
*--------------------
|
*--------------------
|
||||||
*/
|
*/
|
||||||
typedef enum RTEKind
|
typedef enum RTEKind
|
||||||
@ -490,9 +517,8 @@ typedef struct RangeTblEntry
|
|||||||
Alias *eref; /* expanded reference names */
|
Alias *eref; /* expanded reference names */
|
||||||
bool inh; /* inheritance requested? */
|
bool inh; /* inheritance requested? */
|
||||||
bool inFromCl; /* present in FROM clause */
|
bool inFromCl; /* present in FROM clause */
|
||||||
bool checkForRead; /* check rel for read access */
|
AclMode requiredPerms; /* bitmask of required access permissions */
|
||||||
bool checkForWrite; /* check rel for write access */
|
AclId checkAsUser; /* if not zero, check access as this user */
|
||||||
Oid checkAsUser; /* if not zero, check access as this user */
|
|
||||||
} RangeTblEntry;
|
} RangeTblEntry;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -809,26 +835,6 @@ typedef enum GrantObjectType
|
|||||||
ACL_OBJECT_NAMESPACE /* namespace */
|
ACL_OBJECT_NAMESPACE /* namespace */
|
||||||
} GrantObjectType;
|
} GrantObjectType;
|
||||||
|
|
||||||
/*
|
|
||||||
* Grantable rights are encoded so that we can OR them together in a bitmask.
|
|
||||||
* The present representation of AclItem limits us to 15 distinct rights.
|
|
||||||
* Caution: changing these codes breaks stored ACLs, hence forces initdb.
|
|
||||||
*/
|
|
||||||
#define ACL_INSERT (1<<0) /* for relations */
|
|
||||||
#define ACL_SELECT (1<<1)
|
|
||||||
#define ACL_UPDATE (1<<2)
|
|
||||||
#define ACL_DELETE (1<<3)
|
|
||||||
#define ACL_RULE (1<<4)
|
|
||||||
#define ACL_REFERENCES (1<<5)
|
|
||||||
#define ACL_TRIGGER (1<<6)
|
|
||||||
#define ACL_EXECUTE (1<<7) /* for functions */
|
|
||||||
#define ACL_USAGE (1<<8) /* for languages and namespaces */
|
|
||||||
#define ACL_CREATE (1<<9) /* for namespaces and databases */
|
|
||||||
#define ACL_CREATE_TEMP (1<<10) /* for databases */
|
|
||||||
#define N_ACL_RIGHTS 11 /* 1 plus the last 1<<x */
|
|
||||||
#define ACL_ALL_RIGHTS (-1) /* all-privileges marker in GRANT list */
|
|
||||||
#define ACL_NO_RIGHTS 0
|
|
||||||
|
|
||||||
typedef struct GrantStmt
|
typedef struct GrantStmt
|
||||||
{
|
{
|
||||||
NodeTag type;
|
NodeTag type;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/parser/parse_clause.h,v 1.38 2003/11/29 22:41:09 pgsql Exp $
|
* $PostgreSQL: pgsql/src/include/parser/parse_clause.h,v 1.39 2004/01/14 23:01:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
extern void transformFromClause(ParseState *pstate, List *frmList);
|
extern void transformFromClause(ParseState *pstate, List *frmList);
|
||||||
extern int setTargetTable(ParseState *pstate, RangeVar *relation,
|
extern int setTargetTable(ParseState *pstate, RangeVar *relation,
|
||||||
bool inh, bool alsoSource);
|
bool inh, bool alsoSource, AclMode requiredPerms);
|
||||||
extern bool interpretInhOption(InhOption inhOpt);
|
extern bool interpretInhOption(InhOption inhOpt);
|
||||||
|
|
||||||
extern Node *transformWhereClause(ParseState *pstate, Node *clause,
|
extern Node *transformWhereClause(ParseState *pstate, Node *clause,
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.65 2003/11/29 22:41:15 pgsql Exp $
|
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.66 2004/01/14 23:01:55 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* An ACL array is simply an array of AclItems, representing the union
|
* An ACL array is simply an array of AclItems, representing the union
|
||||||
@ -28,7 +28,12 @@
|
|||||||
#include "utils/array.h"
|
#include "utils/array.h"
|
||||||
|
|
||||||
|
|
||||||
/* typedef AclId is declared in c.h */
|
/*
|
||||||
|
* typedef AclId is declared in c.h
|
||||||
|
*
|
||||||
|
* typedef AclMode is declared in parsenodes.h, also the individual privilege
|
||||||
|
* bit meanings are defined there
|
||||||
|
*/
|
||||||
|
|
||||||
#define ACL_ID_WORLD 0 /* placeholder for id in a WORLD acl item */
|
#define ACL_ID_WORLD 0 /* placeholder for id in a WORLD acl item */
|
||||||
|
|
||||||
@ -39,11 +44,6 @@
|
|||||||
#define ACL_IDTYPE_UID 0x01 /* user id - from pg_shadow */
|
#define ACL_IDTYPE_UID 0x01 /* user id - from pg_shadow */
|
||||||
#define ACL_IDTYPE_GID 0x02 /* group id - from pg_group */
|
#define ACL_IDTYPE_GID 0x02 /* group id - from pg_group */
|
||||||
|
|
||||||
/*
|
|
||||||
* AclMode a bitmask of privilege bits
|
|
||||||
*/
|
|
||||||
typedef uint32 AclMode;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AclItem
|
* AclItem
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user