Commit cfd7fb7e authored by Tom Lane's avatar Tom Lane

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.
parent 01d320d4
...@@ -8,7 +8,7 @@ ...@@ -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) ...@@ -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 @@ ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) if (rte->rtekind != RTE_RELATION)
continue; continue;
if (!rte->checkForWrite) if ((rte->requiredPerms & (~ACL_SELECT)) == 0)
continue; continue;
if (isTempNamespace(get_rel_namespace(rte->relid))) if (isTempNamespace(get_rel_namespace(rte->relid)))
continue; continue;
goto fail; goto fail;
}
} }
return; return;
...@@ -511,7 +509,7 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly) ...@@ -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 @@ ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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 @@ ...@@ -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, ...@@ -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 @@ ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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) ...@@ -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, ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 @@ ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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, ...@@ -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) ...@@ -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 @@ ...@@ -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 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200401061 #define CATALOG_VERSION_NO 200401141
#endif #endif
...@@ -7,7 +7,7 @@ ...@@ -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, ...@@ -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 @@ ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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
* *
......
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