mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
Make standard maintenance operations (including VACUUM, ANALYZE, REINDEX,
and CLUSTER) execute as the table owner rather than the calling user, using the same privilege-switching mechanism already used for SECURITY DEFINER functions. The purpose of this change is to ensure that user-defined functions used in index definitions cannot acquire the privileges of a superuser account that is performing routine maintenance. While a function used in an index is supposed to be IMMUTABLE and thus not able to do anything very interesting, there are several easy ways around that restriction; and even if we could plug them all, there would remain a risk of reading sensitive information and broadcasting it through a covert channel such as CPU usage. To prevent bypassing this security measure, execution of SET SESSION AUTHORIZATION and SET ROLE is now forbidden within a SECURITY DEFINER context. Thanks to Itagaki Takahiro for reporting this vulnerability. Security: CVE-2007-6600
This commit is contained in:
parent
98f27aaef3
commit
eedb068c0a
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$PostgreSQL: pgsql/doc/src/sgml/ref/set_role.sgml,v 1.4 2007/01/31 23:26:04 momjian Exp $
|
$PostgreSQL: pgsql/doc/src/sgml/ref/set_role.sgml,v 1.5 2008/01/03 21:23:15 tgl Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ RESET ROLE
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
This command sets the current user
|
This command sets the current user
|
||||||
identifier of the current SQL-session context to be <replaceable
|
identifier of the current SQL session to be <replaceable
|
||||||
class="parameter">rolename</replaceable>. The role name can be
|
class="parameter">rolename</replaceable>. The role name can be
|
||||||
written as either an identifier or a string literal.
|
written as either an identifier or a string literal.
|
||||||
After <command>SET ROLE</>, permissions checking for SQL commands
|
After <command>SET ROLE</>, permissions checking for SQL commands
|
||||||
@ -89,6 +89,11 @@ RESET ROLE
|
|||||||
roles with <command>SET ROLE</> does not change the set of roles
|
roles with <command>SET ROLE</> does not change the set of roles
|
||||||
allowed to a later <command>SET ROLE</>.
|
allowed to a later <command>SET ROLE</>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<command>SET ROLE</> cannot be used within a
|
||||||
|
<literal>SECURITY DEFINER</> function.
|
||||||
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/set_session_auth.sgml,v 1.16 2007/01/31 23:26:04 momjian Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/ref/set_session_auth.sgml,v 1.17 2008/01/03 21:23:15 tgl Exp $ -->
|
||||||
<refentry id="SQL-SET-SESSION-AUTHORIZATION">
|
<refentry id="SQL-SET-SESSION-AUTHORIZATION">
|
||||||
<refmeta>
|
<refmeta>
|
||||||
<refentrytitle id="sql-set-session-authorization-title">SET SESSION AUTHORIZATION</refentrytitle>
|
<refentrytitle id="sql-set-session-authorization-title">SET SESSION AUTHORIZATION</refentrytitle>
|
||||||
@ -27,7 +27,7 @@ RESET SESSION AUTHORIZATION
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
This command sets the session user identifier and the current user
|
This command sets the session user identifier and the current user
|
||||||
identifier of the current SQL-session context to be <replaceable
|
identifier of the current SQL session to be <replaceable
|
||||||
class="parameter">username</replaceable>. The user name can be
|
class="parameter">username</replaceable>. The user name can be
|
||||||
written as either an identifier or a string literal. Using this
|
written as either an identifier or a string literal. Using this
|
||||||
command, it is possible, for example, to temporarily become an
|
command, it is possible, for example, to temporarily become an
|
||||||
@ -38,7 +38,7 @@ RESET SESSION AUTHORIZATION
|
|||||||
The session user identifier is initially set to be the (possibly
|
The session user identifier is initially set to be the (possibly
|
||||||
authenticated) user name provided by the client. The current user
|
authenticated) user name provided by the client. The current user
|
||||||
identifier is normally equal to the session user identifier, but
|
identifier is normally equal to the session user identifier, but
|
||||||
might change temporarily in the context of <quote>setuid</quote>
|
might change temporarily in the context of <literal>SECURITY DEFINER</>
|
||||||
functions and similar mechanisms; it can also be changed by
|
functions and similar mechanisms; it can also be changed by
|
||||||
<xref linkend="sql-set-role" endterm="sql-set-role-title">.
|
<xref linkend="sql-set-role" endterm="sql-set-role-title">.
|
||||||
The current user identifier is relevant for permission checking.
|
The current user identifier is relevant for permission checking.
|
||||||
@ -64,6 +64,15 @@ RESET SESSION AUTHORIZATION
|
|||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
<refsect1>
|
||||||
|
<title>Notes</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<command>SET SESSION AUTHORIZATION</> cannot be used within a
|
||||||
|
<literal>SECURITY DEFINER</> function.
|
||||||
|
</para>
|
||||||
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Examples</title>
|
<title>Examples</title>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$PostgreSQL: pgsql/doc/src/sgml/ref/show.sgml,v 1.44 2007/09/26 22:36:30 tgl Exp $
|
$PostgreSQL: pgsql/doc/src/sgml/ref/show.sgml,v 1.45 2008/01/03 21:23:15 tgl Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -104,8 +104,7 @@ SHOW ALL
|
|||||||
<term><literal>IS_SUPERUSER</literal></term>
|
<term><literal>IS_SUPERUSER</literal></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
True if the current session authorization identifier has
|
True if the current role has superuser privileges.
|
||||||
superuser privileges.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.255 2008/01/01 19:45:48 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.256 2008/01/03 21:23:15 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -123,7 +123,8 @@ typedef struct TransactionStateData
|
|||||||
MemoryContext curTransactionContext; /* my xact-lifetime context */
|
MemoryContext curTransactionContext; /* my xact-lifetime context */
|
||||||
ResourceOwner curTransactionOwner; /* my query resources */
|
ResourceOwner curTransactionOwner; /* my query resources */
|
||||||
List *childXids; /* subcommitted child XIDs */
|
List *childXids; /* subcommitted child XIDs */
|
||||||
Oid currentUser; /* subxact start current_user */
|
Oid prevUser; /* previous CurrentUserId setting */
|
||||||
|
bool prevSecDefCxt; /* previous SecurityDefinerContext setting */
|
||||||
bool prevXactReadOnly; /* entry-time xact r/o state */
|
bool prevXactReadOnly; /* entry-time xact r/o state */
|
||||||
struct TransactionStateData *parent; /* back link to parent */
|
struct TransactionStateData *parent; /* back link to parent */
|
||||||
} TransactionStateData;
|
} TransactionStateData;
|
||||||
@ -148,7 +149,8 @@ static TransactionStateData TopTransactionStateData = {
|
|||||||
NULL, /* cur transaction context */
|
NULL, /* cur transaction context */
|
||||||
NULL, /* cur transaction resource owner */
|
NULL, /* cur transaction resource owner */
|
||||||
NIL, /* subcommitted child Xids */
|
NIL, /* subcommitted child Xids */
|
||||||
0, /* entry-time current userid */
|
InvalidOid, /* previous CurrentUserId setting */
|
||||||
|
false, /* previous SecurityDefinerContext setting */
|
||||||
false, /* entry-time xact r/o state */
|
false, /* entry-time xact r/o state */
|
||||||
NULL /* link to parent state block */
|
NULL /* link to parent state block */
|
||||||
};
|
};
|
||||||
@ -1490,19 +1492,15 @@ StartTransaction(void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* initialize current transaction state fields
|
* initialize current transaction state fields
|
||||||
|
*
|
||||||
|
* note: prevXactReadOnly is not used at the outermost level
|
||||||
*/
|
*/
|
||||||
s->nestingLevel = 1;
|
s->nestingLevel = 1;
|
||||||
s->gucNestLevel = 1;
|
s->gucNestLevel = 1;
|
||||||
s->childXids = NIL;
|
s->childXids = NIL;
|
||||||
|
GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt);
|
||||||
/*
|
/* SecurityDefinerContext should never be set outside a transaction */
|
||||||
* You might expect to see "s->currentUser = GetUserId();" here, but you
|
Assert(!s->prevSecDefCxt);
|
||||||
* won't because it doesn't work during startup; the userid isn't set yet
|
|
||||||
* during a backend's first transaction start. We only use the
|
|
||||||
* currentUser field in sub-transaction state structs.
|
|
||||||
*
|
|
||||||
* prevXactReadOnly is also valid only in sub-transactions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* initialize other subsystems for new transaction
|
* initialize other subsystems for new transaction
|
||||||
@ -1963,17 +1961,16 @@ AbortTransaction(void)
|
|||||||
s->state = TRANS_ABORT;
|
s->state = TRANS_ABORT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reset user id which might have been changed transiently. We cannot use
|
* Reset user ID which might have been changed transiently. We need this
|
||||||
* s->currentUser, since it may not be set yet; instead rely on internal
|
* to clean up in case control escaped out of a SECURITY DEFINER function
|
||||||
* state of miscinit.c.
|
* or other local change of CurrentUserId; therefore, the prior value
|
||||||
|
* of SecurityDefinerContext also needs to be restored.
|
||||||
*
|
*
|
||||||
* (Note: it is not necessary to restore session authorization here
|
* (Note: it is not necessary to restore session authorization or role
|
||||||
* because that can only be changed via GUC, and GUC will take care of
|
* settings here because those can only be changed via GUC, and GUC will
|
||||||
* rolling it back if need be. However, an error within a SECURITY
|
* take care of rolling them back if need be.)
|
||||||
* DEFINER function could send control here with the wrong current
|
|
||||||
* userid.)
|
|
||||||
*/
|
*/
|
||||||
AtAbort_UserId();
|
SetUserIdAndContext(s->prevUser, s->prevSecDefCxt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do abort processing
|
* do abort processing
|
||||||
@ -3806,6 +3803,12 @@ AbortSubTransaction(void)
|
|||||||
|
|
||||||
s->state = TRANS_ABORT;
|
s->state = TRANS_ABORT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset user ID which might have been changed transiently. (See notes
|
||||||
|
* in AbortTransaction.)
|
||||||
|
*/
|
||||||
|
SetUserIdAndContext(s->prevUser, s->prevSecDefCxt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We can skip all this stuff if the subxact failed before creating a
|
* We can skip all this stuff if the subxact failed before creating a
|
||||||
* ResourceOwner...
|
* ResourceOwner...
|
||||||
@ -3858,20 +3861,6 @@ AbortSubTransaction(void)
|
|||||||
AtEOSubXact_PgStat(false, s->nestingLevel);
|
AtEOSubXact_PgStat(false, s->nestingLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Reset user id which might have been changed transiently. Here we want
|
|
||||||
* to restore to the userid that was current at subxact entry. (As in
|
|
||||||
* AbortTransaction, we need not worry about the session userid.)
|
|
||||||
*
|
|
||||||
* Must do this after AtEOXact_GUC to handle the case where we entered the
|
|
||||||
* subxact inside a SECURITY DEFINER function (hence current and session
|
|
||||||
* userids were different) and then session auth was changed inside the
|
|
||||||
* subxact. GUC will reset both current and session userids to the
|
|
||||||
* entry-time session userid. This is right in every other scenario so it
|
|
||||||
* seems simplest to let GUC do that and fix it here.
|
|
||||||
*/
|
|
||||||
SetUserId(s->currentUser);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Restore the upper transaction's read-only state, too. This should be
|
* Restore the upper transaction's read-only state, too. This should be
|
||||||
* redundant with GUC's cleanup but we may as well do it for consistency
|
* redundant with GUC's cleanup but we may as well do it for consistency
|
||||||
@ -3926,13 +3915,6 @@ PushTransaction(void)
|
|||||||
{
|
{
|
||||||
TransactionState p = CurrentTransactionState;
|
TransactionState p = CurrentTransactionState;
|
||||||
TransactionState s;
|
TransactionState s;
|
||||||
Oid currentUser;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* At present, GetUserId cannot fail, but let's not assume that. Get the
|
|
||||||
* ID before entering the critical code sequence.
|
|
||||||
*/
|
|
||||||
currentUser = GetUserId();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We keep subtransaction state nodes in TopTransactionContext.
|
* We keep subtransaction state nodes in TopTransactionContext.
|
||||||
@ -3966,7 +3948,7 @@ PushTransaction(void)
|
|||||||
s->savepointLevel = p->savepointLevel;
|
s->savepointLevel = p->savepointLevel;
|
||||||
s->state = TRANS_DEFAULT;
|
s->state = TRANS_DEFAULT;
|
||||||
s->blockState = TBLOCK_SUBBEGIN;
|
s->blockState = TBLOCK_SUBBEGIN;
|
||||||
s->currentUser = currentUser;
|
GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt);
|
||||||
s->prevXactReadOnly = XactReadOnly;
|
s->prevXactReadOnly = XactReadOnly;
|
||||||
|
|
||||||
CurrentTransactionState = s;
|
CurrentTransactionState = s;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.289 2008/01/01 19:45:48 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.290 2008/01/03 21:23:15 tgl Exp $
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* INTERFACE ROUTINES
|
* INTERFACE ROUTINES
|
||||||
@ -1339,6 +1339,8 @@ index_build(Relation heapRelation,
|
|||||||
{
|
{
|
||||||
RegProcedure procedure;
|
RegProcedure procedure;
|
||||||
IndexBuildResult *stats;
|
IndexBuildResult *stats;
|
||||||
|
Oid save_userid;
|
||||||
|
bool save_secdefcxt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* sanity checks
|
* sanity checks
|
||||||
@ -1349,6 +1351,13 @@ index_build(Relation heapRelation,
|
|||||||
procedure = indexRelation->rd_am->ambuild;
|
procedure = indexRelation->rd_am->ambuild;
|
||||||
Assert(RegProcedureIsValid(procedure));
|
Assert(RegProcedureIsValid(procedure));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Switch to the table owner's userid, so that any index functions are
|
||||||
|
* run as that user.
|
||||||
|
*/
|
||||||
|
GetUserIdAndContext(&save_userid, &save_secdefcxt);
|
||||||
|
SetUserIdAndContext(heapRelation->rd_rel->relowner, true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call the access method's build procedure
|
* Call the access method's build procedure
|
||||||
*/
|
*/
|
||||||
@ -1359,6 +1368,9 @@ index_build(Relation heapRelation,
|
|||||||
PointerGetDatum(indexInfo)));
|
PointerGetDatum(indexInfo)));
|
||||||
Assert(PointerIsValid(stats));
|
Assert(PointerIsValid(stats));
|
||||||
|
|
||||||
|
/* Restore userid */
|
||||||
|
SetUserIdAndContext(save_userid, save_secdefcxt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we found any potentially broken HOT chains, mark the index as not
|
* If we found any potentially broken HOT chains, mark the index as not
|
||||||
* being usable until the current transaction is below the event horizon.
|
* being usable until the current transaction is below the event horizon.
|
||||||
@ -1857,6 +1869,8 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
|
|||||||
IndexInfo *indexInfo;
|
IndexInfo *indexInfo;
|
||||||
IndexVacuumInfo ivinfo;
|
IndexVacuumInfo ivinfo;
|
||||||
v_i_state state;
|
v_i_state state;
|
||||||
|
Oid save_userid;
|
||||||
|
bool save_secdefcxt;
|
||||||
|
|
||||||
/* Open and lock the parent heap relation */
|
/* Open and lock the parent heap relation */
|
||||||
heapRelation = heap_open(heapId, ShareUpdateExclusiveLock);
|
heapRelation = heap_open(heapId, ShareUpdateExclusiveLock);
|
||||||
@ -1873,6 +1887,13 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
|
|||||||
/* mark build is concurrent just for consistency */
|
/* mark build is concurrent just for consistency */
|
||||||
indexInfo->ii_Concurrent = true;
|
indexInfo->ii_Concurrent = true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Switch to the table owner's userid, so that any index functions are
|
||||||
|
* run as that user.
|
||||||
|
*/
|
||||||
|
GetUserIdAndContext(&save_userid, &save_secdefcxt);
|
||||||
|
SetUserIdAndContext(heapRelation->rd_rel->relowner, true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan the index and gather up all the TIDs into a tuplesort object.
|
* Scan the index and gather up all the TIDs into a tuplesort object.
|
||||||
*/
|
*/
|
||||||
@ -1910,6 +1931,9 @@ validate_index(Oid heapId, Oid indexId, Snapshot snapshot)
|
|||||||
"validate_index found %.0f heap tuples, %.0f index tuples; inserted %.0f missing tuples",
|
"validate_index found %.0f heap tuples, %.0f index tuples; inserted %.0f missing tuples",
|
||||||
state.htups, state.itups, state.tups_inserted);
|
state.htups, state.itups, state.tups_inserted);
|
||||||
|
|
||||||
|
/* Restore userid */
|
||||||
|
SetUserIdAndContext(save_userid, save_secdefcxt);
|
||||||
|
|
||||||
/* Close rels, but keep locks */
|
/* Close rels, but keep locks */
|
||||||
index_close(indexRelation, NoLock);
|
index_close(indexRelation, NoLock);
|
||||||
heap_close(heapRelation, NoLock);
|
heap_close(heapRelation, NoLock);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.113 2008/01/01 19:45:48 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/analyze.c,v 1.114 2008/01/03 21:23:15 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -119,6 +119,8 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
|
|||||||
HeapTuple *rows;
|
HeapTuple *rows;
|
||||||
PGRUsage ru0;
|
PGRUsage ru0;
|
||||||
TimestampTz starttime = 0;
|
TimestampTz starttime = 0;
|
||||||
|
Oid save_userid;
|
||||||
|
bool save_secdefcxt;
|
||||||
|
|
||||||
if (vacstmt->verbose)
|
if (vacstmt->verbose)
|
||||||
elevel = INFO;
|
elevel = INFO;
|
||||||
@ -202,6 +204,18 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ereport(elevel,
|
||||||
|
(errmsg("analyzing \"%s.%s\"",
|
||||||
|
get_namespace_name(RelationGetNamespace(onerel)),
|
||||||
|
RelationGetRelationName(onerel))));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Switch to the table owner's userid, so that any index functions are
|
||||||
|
* run as that user.
|
||||||
|
*/
|
||||||
|
GetUserIdAndContext(&save_userid, &save_secdefcxt);
|
||||||
|
SetUserIdAndContext(onerel->rd_rel->relowner, true);
|
||||||
|
|
||||||
/* let others know what I'm doing */
|
/* let others know what I'm doing */
|
||||||
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
|
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
|
||||||
MyProc->vacuumFlags |= PROC_IN_ANALYZE;
|
MyProc->vacuumFlags |= PROC_IN_ANALYZE;
|
||||||
@ -215,11 +229,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
|
|||||||
starttime = GetCurrentTimestamp();
|
starttime = GetCurrentTimestamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
ereport(elevel,
|
|
||||||
(errmsg("analyzing \"%s.%s\"",
|
|
||||||
get_namespace_name(RelationGetNamespace(onerel)),
|
|
||||||
RelationGetRelationName(onerel))));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine which columns to analyze
|
* Determine which columns to analyze
|
||||||
*
|
*
|
||||||
@ -344,9 +353,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
|
|||||||
onerel->rd_rel->relisshared,
|
onerel->rd_rel->relisshared,
|
||||||
0, 0);
|
0, 0);
|
||||||
|
|
||||||
vac_close_indexes(nindexes, Irel, AccessShareLock);
|
goto cleanup;
|
||||||
relation_close(onerel, ShareUpdateExclusiveLock);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -466,6 +473,9 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
|
|||||||
totalrows, totaldeadrows);
|
totalrows, totaldeadrows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We skip to here if there were no analyzable columns */
|
||||||
|
cleanup:
|
||||||
|
|
||||||
/* Done with indexes */
|
/* Done with indexes */
|
||||||
vac_close_indexes(nindexes, Irel, NoLock);
|
vac_close_indexes(nindexes, Irel, NoLock);
|
||||||
|
|
||||||
@ -498,6 +508,9 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt,
|
|||||||
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
|
LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
|
||||||
MyProc->vacuumFlags &= ~PROC_IN_ANALYZE;
|
MyProc->vacuumFlags &= ~PROC_IN_ANALYZE;
|
||||||
LWLockRelease(ProcArrayLock);
|
LWLockRelease(ProcArrayLock);
|
||||||
|
|
||||||
|
/* Restore userid */
|
||||||
|
SetUserIdAndContext(save_userid, save_secdefcxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.48 2008/01/01 19:45:49 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/schemacmds.c,v 1.49 2008/01/03 21:23:15 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -48,9 +48,10 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
|
|||||||
ListCell *parsetree_item;
|
ListCell *parsetree_item;
|
||||||
Oid owner_uid;
|
Oid owner_uid;
|
||||||
Oid saved_uid;
|
Oid saved_uid;
|
||||||
|
bool saved_secdefcxt;
|
||||||
AclResult aclresult;
|
AclResult aclresult;
|
||||||
|
|
||||||
saved_uid = GetUserId();
|
GetUserIdAndContext(&saved_uid, &saved_secdefcxt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Who is supposed to own the new schema?
|
* Who is supposed to own the new schema?
|
||||||
@ -86,11 +87,11 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
|
|||||||
* temporarily set the current user so that the object(s) will be created
|
* temporarily set the current user so that the object(s) will be created
|
||||||
* with the correct ownership.
|
* with the correct ownership.
|
||||||
*
|
*
|
||||||
* (The setting will revert to session user on error or at the end of this
|
* (The setting will be restored at the end of this routine, or in case
|
||||||
* routine.)
|
* of error, transaction abort will clean things up.)
|
||||||
*/
|
*/
|
||||||
if (saved_uid != owner_uid)
|
if (saved_uid != owner_uid)
|
||||||
SetUserId(owner_uid);
|
SetUserIdAndContext(owner_uid, true);
|
||||||
|
|
||||||
/* Create the schema's namespace */
|
/* Create the schema's namespace */
|
||||||
namespaceId = NamespaceCreate(schemaName, owner_uid);
|
namespaceId = NamespaceCreate(schemaName, owner_uid);
|
||||||
@ -142,7 +143,7 @@ CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString)
|
|||||||
PopOverrideSearchPath();
|
PopOverrideSearchPath();
|
||||||
|
|
||||||
/* Reset current user */
|
/* Reset current user */
|
||||||
SetUserId(saved_uid);
|
SetUserIdAndContext(saved_uid, saved_secdefcxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.362 2008/01/01 19:45:49 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.363 2008/01/03 21:23:15 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -971,6 +971,8 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
|
|||||||
Relation onerel;
|
Relation onerel;
|
||||||
LockRelId onerelid;
|
LockRelId onerelid;
|
||||||
Oid toast_relid;
|
Oid toast_relid;
|
||||||
|
Oid save_userid;
|
||||||
|
bool save_secdefcxt;
|
||||||
|
|
||||||
/* Begin a transaction for vacuuming this relation */
|
/* Begin a transaction for vacuuming this relation */
|
||||||
StartTransactionCommand();
|
StartTransactionCommand();
|
||||||
@ -1100,6 +1102,14 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
|
|||||||
*/
|
*/
|
||||||
toast_relid = onerel->rd_rel->reltoastrelid;
|
toast_relid = onerel->rd_rel->reltoastrelid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Switch to the table owner's userid, so that any index functions are
|
||||||
|
* run as that user. (This is unnecessary, but harmless, for lazy
|
||||||
|
* VACUUM.)
|
||||||
|
*/
|
||||||
|
GetUserIdAndContext(&save_userid, &save_secdefcxt);
|
||||||
|
SetUserIdAndContext(onerel->rd_rel->relowner, true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the actual work --- either FULL or "lazy" vacuum
|
* Do the actual work --- either FULL or "lazy" vacuum
|
||||||
*/
|
*/
|
||||||
@ -1108,6 +1118,9 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
|
|||||||
else
|
else
|
||||||
lazy_vacuum_rel(onerel, vacstmt, vac_strategy);
|
lazy_vacuum_rel(onerel, vacstmt, vac_strategy);
|
||||||
|
|
||||||
|
/* Restore userid */
|
||||||
|
SetUserIdAndContext(save_userid, save_secdefcxt);
|
||||||
|
|
||||||
/* all done with this class, but hold lock until commit */
|
/* all done with this class, but hold lock until commit */
|
||||||
relation_close(onerel, NoLock);
|
relation_close(onerel, NoLock);
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/variable.c,v 1.124 2008/01/01 19:45:49 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/variable.c,v 1.125 2008/01/03 21:23:15 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -717,6 +717,21 @@ assign_session_authorization(const char *value, bool doit, GucSource source)
|
|||||||
/* not a saved ID, so look it up */
|
/* not a saved ID, so look it up */
|
||||||
HeapTuple roleTup;
|
HeapTuple roleTup;
|
||||||
|
|
||||||
|
if (InSecurityDefinerContext())
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Disallow SET SESSION AUTHORIZATION inside a security definer
|
||||||
|
* context. We need to do this because when we exit the context,
|
||||||
|
* GUC won't be notified, leaving things out of sync. Note that
|
||||||
|
* this test is positioned so that restoring a previously saved
|
||||||
|
* setting isn't prevented.
|
||||||
|
*/
|
||||||
|
ereport(GUC_complaint_elevel(source),
|
||||||
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
errmsg("cannot set session authorization within security-definer function")));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!IsTransactionState())
|
if (!IsTransactionState())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -823,6 +838,24 @@ assign_role(const char *value, bool doit, GucSource source)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (roleid == InvalidOid && InSecurityDefinerContext())
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Disallow SET ROLE inside a security definer context. We need to do
|
||||||
|
* this because when we exit the context, GUC won't be notified,
|
||||||
|
* leaving things out of sync. Note that this test is arranged so
|
||||||
|
* that restoring a previously saved setting isn't prevented.
|
||||||
|
*
|
||||||
|
* XXX it would be nice to allow this case in future, with the
|
||||||
|
* behavior being that the SET ROLE's effects end when the security
|
||||||
|
* definer context is exited.
|
||||||
|
*/
|
||||||
|
ereport(GUC_complaint_elevel(source),
|
||||||
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
|
errmsg("cannot set role within security-definer function")));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (roleid == InvalidOid &&
|
if (roleid == InvalidOid &&
|
||||||
strcmp(actual_rolename, "none") != 0)
|
strcmp(actual_rolename, "none") != 0)
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.100 2008/01/01 19:45:52 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/ri_triggers.c,v 1.101 2008/01/03 21:23:15 tgl Exp $
|
||||||
*
|
*
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
@ -3173,7 +3173,8 @@ ri_PlanCheck(const char *querystr, int nargs, Oid *argtypes,
|
|||||||
{
|
{
|
||||||
SPIPlanPtr qplan;
|
SPIPlanPtr qplan;
|
||||||
Relation query_rel;
|
Relation query_rel;
|
||||||
Oid save_uid;
|
Oid save_userid;
|
||||||
|
bool save_secdefcxt;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The query is always run against the FK table except when this is an
|
* The query is always run against the FK table except when this is an
|
||||||
@ -3187,8 +3188,8 @@ ri_PlanCheck(const char *querystr, int nargs, Oid *argtypes,
|
|||||||
query_rel = fk_rel;
|
query_rel = fk_rel;
|
||||||
|
|
||||||
/* Switch to proper UID to perform check as */
|
/* Switch to proper UID to perform check as */
|
||||||
save_uid = GetUserId();
|
GetUserIdAndContext(&save_userid, &save_secdefcxt);
|
||||||
SetUserId(RelationGetForm(query_rel)->relowner);
|
SetUserIdAndContext(RelationGetForm(query_rel)->relowner, true);
|
||||||
|
|
||||||
/* Create the plan */
|
/* Create the plan */
|
||||||
qplan = SPI_prepare(querystr, nargs, argtypes);
|
qplan = SPI_prepare(querystr, nargs, argtypes);
|
||||||
@ -3197,7 +3198,7 @@ ri_PlanCheck(const char *querystr, int nargs, Oid *argtypes,
|
|||||||
elog(ERROR, "SPI_prepare returned %d for %s", SPI_result, querystr);
|
elog(ERROR, "SPI_prepare returned %d for %s", SPI_result, querystr);
|
||||||
|
|
||||||
/* Restore UID */
|
/* Restore UID */
|
||||||
SetUserId(save_uid);
|
SetUserIdAndContext(save_userid, save_secdefcxt);
|
||||||
|
|
||||||
/* Save the plan if requested */
|
/* Save the plan if requested */
|
||||||
if (cache_plan)
|
if (cache_plan)
|
||||||
@ -3226,7 +3227,8 @@ ri_PerformCheck(RI_QueryKey *qkey, SPIPlanPtr qplan,
|
|||||||
Snapshot crosscheck_snapshot;
|
Snapshot crosscheck_snapshot;
|
||||||
int limit;
|
int limit;
|
||||||
int spi_result;
|
int spi_result;
|
||||||
Oid save_uid;
|
Oid save_userid;
|
||||||
|
bool save_secdefcxt;
|
||||||
Datum vals[RI_MAX_NUMKEYS * 2];
|
Datum vals[RI_MAX_NUMKEYS * 2];
|
||||||
char nulls[RI_MAX_NUMKEYS * 2];
|
char nulls[RI_MAX_NUMKEYS * 2];
|
||||||
|
|
||||||
@ -3304,8 +3306,8 @@ ri_PerformCheck(RI_QueryKey *qkey, SPIPlanPtr qplan,
|
|||||||
limit = (expect_OK == SPI_OK_SELECT) ? 1 : 0;
|
limit = (expect_OK == SPI_OK_SELECT) ? 1 : 0;
|
||||||
|
|
||||||
/* Switch to proper UID to perform check as */
|
/* Switch to proper UID to perform check as */
|
||||||
save_uid = GetUserId();
|
GetUserIdAndContext(&save_userid, &save_secdefcxt);
|
||||||
SetUserId(RelationGetForm(query_rel)->relowner);
|
SetUserIdAndContext(RelationGetForm(query_rel)->relowner, true);
|
||||||
|
|
||||||
/* Finally we can run the query. */
|
/* Finally we can run the query. */
|
||||||
spi_result = SPI_execute_snapshot(qplan,
|
spi_result = SPI_execute_snapshot(qplan,
|
||||||
@ -3314,7 +3316,7 @@ ri_PerformCheck(RI_QueryKey *qkey, SPIPlanPtr qplan,
|
|||||||
false, false, limit);
|
false, false, limit);
|
||||||
|
|
||||||
/* Restore UID */
|
/* Restore UID */
|
||||||
SetUserId(save_uid);
|
SetUserIdAndContext(save_userid, save_secdefcxt);
|
||||||
|
|
||||||
/* Check result */
|
/* Check result */
|
||||||
if (spi_result < 0)
|
if (spi_result < 0)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.112 2008/01/01 19:45:53 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/fmgr/fmgr.c,v 1.113 2008/01/03 21:23:15 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -864,6 +864,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
|
|||||||
struct fmgr_security_definer_cache *volatile fcache;
|
struct fmgr_security_definer_cache *volatile fcache;
|
||||||
FmgrInfo *save_flinfo;
|
FmgrInfo *save_flinfo;
|
||||||
Oid save_userid;
|
Oid save_userid;
|
||||||
|
bool save_secdefcxt;
|
||||||
volatile int save_nestlevel;
|
volatile int save_nestlevel;
|
||||||
|
|
||||||
if (!fcinfo->flinfo->fn_extra)
|
if (!fcinfo->flinfo->fn_extra)
|
||||||
@ -908,46 +909,50 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
|
|||||||
else
|
else
|
||||||
fcache = fcinfo->flinfo->fn_extra;
|
fcache = fcinfo->flinfo->fn_extra;
|
||||||
|
|
||||||
save_flinfo = fcinfo->flinfo;
|
/* GetUserIdAndContext is cheap enough that no harm in a wasted call */
|
||||||
/* GetUserId is cheap enough that no harm in a wasted call */
|
GetUserIdAndContext(&save_userid, &save_secdefcxt);
|
||||||
save_userid = GetUserId();
|
|
||||||
if (fcache->proconfig) /* Need a new GUC nesting level */
|
if (fcache->proconfig) /* Need a new GUC nesting level */
|
||||||
save_nestlevel = NewGUCNestLevel();
|
save_nestlevel = NewGUCNestLevel();
|
||||||
else
|
else
|
||||||
save_nestlevel = 0; /* keep compiler quiet */
|
save_nestlevel = 0; /* keep compiler quiet */
|
||||||
|
|
||||||
|
if (OidIsValid(fcache->userid))
|
||||||
|
SetUserIdAndContext(fcache->userid, true);
|
||||||
|
|
||||||
|
if (fcache->proconfig)
|
||||||
|
{
|
||||||
|
ProcessGUCArray(fcache->proconfig,
|
||||||
|
(superuser() ? PGC_SUSET : PGC_USERSET),
|
||||||
|
PGC_S_SESSION,
|
||||||
|
GUC_ACTION_SAVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't need to restore GUC or userid settings on error, because the
|
||||||
|
* ensuing xact or subxact abort will do that. The PG_TRY block is only
|
||||||
|
* needed to clean up the flinfo link.
|
||||||
|
*/
|
||||||
|
save_flinfo = fcinfo->flinfo;
|
||||||
|
|
||||||
PG_TRY();
|
PG_TRY();
|
||||||
{
|
{
|
||||||
fcinfo->flinfo = &fcache->flinfo;
|
fcinfo->flinfo = &fcache->flinfo;
|
||||||
|
|
||||||
if (OidIsValid(fcache->userid))
|
|
||||||
SetUserId(fcache->userid);
|
|
||||||
|
|
||||||
if (fcache->proconfig)
|
|
||||||
{
|
|
||||||
ProcessGUCArray(fcache->proconfig,
|
|
||||||
(superuser() ? PGC_SUSET : PGC_USERSET),
|
|
||||||
PGC_S_SESSION,
|
|
||||||
GUC_ACTION_SAVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
result = FunctionCallInvoke(fcinfo);
|
result = FunctionCallInvoke(fcinfo);
|
||||||
}
|
}
|
||||||
PG_CATCH();
|
PG_CATCH();
|
||||||
{
|
{
|
||||||
fcinfo->flinfo = save_flinfo;
|
fcinfo->flinfo = save_flinfo;
|
||||||
/* We don't need to restore GUC settings, outer xact abort will */
|
|
||||||
if (OidIsValid(fcache->userid))
|
|
||||||
SetUserId(save_userid);
|
|
||||||
PG_RE_THROW();
|
PG_RE_THROW();
|
||||||
}
|
}
|
||||||
PG_END_TRY();
|
PG_END_TRY();
|
||||||
|
|
||||||
fcinfo->flinfo = save_flinfo;
|
fcinfo->flinfo = save_flinfo;
|
||||||
|
|
||||||
if (fcache->proconfig)
|
if (fcache->proconfig)
|
||||||
AtEOXact_GUC(true, save_nestlevel);
|
AtEOXact_GUC(true, save_nestlevel);
|
||||||
if (OidIsValid(fcache->userid))
|
if (OidIsValid(fcache->userid))
|
||||||
SetUserId(save_userid);
|
SetUserIdAndContext(save_userid, save_secdefcxt);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.165 2008/01/01 19:45:53 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.166 2008/01/03 21:23:15 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -264,13 +264,15 @@ make_absolute_path(const char *path)
|
|||||||
* OuterUserId is the current user ID in effect at the "outer level" (outside
|
* OuterUserId is the current user ID in effect at the "outer level" (outside
|
||||||
* any transaction or function). This is initially the same as SessionUserId,
|
* any transaction or function). This is initially the same as SessionUserId,
|
||||||
* but can be changed by SET ROLE to any role that SessionUserId is a
|
* but can be changed by SET ROLE to any role that SessionUserId is a
|
||||||
* member of. We store this mainly so that AtAbort_UserId knows what to
|
* member of. (XXX rename to something like CurrentRoleId?)
|
||||||
* reset CurrentUserId to.
|
|
||||||
*
|
*
|
||||||
* CurrentUserId is the current effective user ID; this is the one to use
|
* CurrentUserId is the current effective user ID; this is the one to use
|
||||||
* for all normal permissions-checking purposes. At outer level this will
|
* for all normal permissions-checking purposes. At outer level this will
|
||||||
* be the same as OuterUserId, but it changes during calls to SECURITY
|
* be the same as OuterUserId, but it changes during calls to SECURITY
|
||||||
* DEFINER functions, as well as locally in some specialized commands.
|
* DEFINER functions, as well as locally in some specialized commands.
|
||||||
|
*
|
||||||
|
* SecurityDefinerContext is TRUE if we are within a SECURITY DEFINER function
|
||||||
|
* or another context that temporarily changes CurrentUserId.
|
||||||
* ----------------------------------------------------------------
|
* ----------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
static Oid AuthenticatedUserId = InvalidOid;
|
static Oid AuthenticatedUserId = InvalidOid;
|
||||||
@ -282,12 +284,16 @@ static Oid CurrentUserId = InvalidOid;
|
|||||||
static bool AuthenticatedUserIsSuperuser = false;
|
static bool AuthenticatedUserIsSuperuser = false;
|
||||||
static bool SessionUserIsSuperuser = false;
|
static bool SessionUserIsSuperuser = false;
|
||||||
|
|
||||||
|
static bool SecurityDefinerContext = false;
|
||||||
|
|
||||||
/* We also remember if a SET ROLE is currently active */
|
/* We also remember if a SET ROLE is currently active */
|
||||||
static bool SetRoleIsActive = false;
|
static bool SetRoleIsActive = false;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GetUserId/SetUserId - get/set the current effective user ID.
|
* GetUserId - get the current effective user ID.
|
||||||
|
*
|
||||||
|
* Note: there's no SetUserId() anymore; use SetUserIdAndContext().
|
||||||
*/
|
*/
|
||||||
Oid
|
Oid
|
||||||
GetUserId(void)
|
GetUserId(void)
|
||||||
@ -297,14 +303,6 @@ GetUserId(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
SetUserId(Oid userid)
|
|
||||||
{
|
|
||||||
AssertArg(OidIsValid(userid));
|
|
||||||
CurrentUserId = userid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GetOuterUserId/SetOuterUserId - get/set the outer-level user ID.
|
* GetOuterUserId/SetOuterUserId - get/set the outer-level user ID.
|
||||||
*/
|
*/
|
||||||
@ -319,6 +317,7 @@ GetOuterUserId(void)
|
|||||||
static void
|
static void
|
||||||
SetOuterUserId(Oid userid)
|
SetOuterUserId(Oid userid)
|
||||||
{
|
{
|
||||||
|
AssertState(!SecurityDefinerContext);
|
||||||
AssertArg(OidIsValid(userid));
|
AssertArg(OidIsValid(userid));
|
||||||
OuterUserId = userid;
|
OuterUserId = userid;
|
||||||
|
|
||||||
@ -341,6 +340,7 @@ GetSessionUserId(void)
|
|||||||
static void
|
static void
|
||||||
SetSessionUserId(Oid userid, bool is_superuser)
|
SetSessionUserId(Oid userid, bool is_superuser)
|
||||||
{
|
{
|
||||||
|
AssertState(!SecurityDefinerContext);
|
||||||
AssertArg(OidIsValid(userid));
|
AssertArg(OidIsValid(userid));
|
||||||
SessionUserId = userid;
|
SessionUserId = userid;
|
||||||
SessionUserIsSuperuser = is_superuser;
|
SessionUserIsSuperuser = is_superuser;
|
||||||
@ -352,6 +352,44 @@ SetSessionUserId(Oid userid, bool is_superuser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GetUserIdAndContext/SetUserIdAndContext - get/set the current user ID
|
||||||
|
* and the SecurityDefinerContext flag.
|
||||||
|
*
|
||||||
|
* Unlike GetUserId, GetUserIdAndContext does *not* Assert that the current
|
||||||
|
* value of CurrentUserId is valid; nor does SetUserIdAndContext require
|
||||||
|
* the new value to be valid. In fact, these routines had better not
|
||||||
|
* ever throw any kind of error. This is because they are used by
|
||||||
|
* StartTransaction and AbortTransaction to save/restore the settings,
|
||||||
|
* and during the first transaction within a backend, the value to be saved
|
||||||
|
* and perhaps restored is indeed invalid. We have to be able to get
|
||||||
|
* through AbortTransaction without asserting in case InitPostgres fails.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
GetUserIdAndContext(Oid *userid, bool *sec_def_context)
|
||||||
|
{
|
||||||
|
*userid = CurrentUserId;
|
||||||
|
*sec_def_context = SecurityDefinerContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SetUserIdAndContext(Oid userid, bool sec_def_context)
|
||||||
|
{
|
||||||
|
CurrentUserId = userid;
|
||||||
|
SecurityDefinerContext = sec_def_context;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* InSecurityDefinerContext - are we inside a SECURITY DEFINER context?
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
InSecurityDefinerContext(void)
|
||||||
|
{
|
||||||
|
return SecurityDefinerContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize user identity during normal backend startup
|
* Initialize user identity during normal backend startup
|
||||||
*/
|
*/
|
||||||
@ -479,21 +517,6 @@ InitializeSessionUserIdStandalone(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reset effective userid during AbortTransaction
|
|
||||||
*
|
|
||||||
* This is essentially SetUserId(GetOuterUserId()), but without the Asserts.
|
|
||||||
* The reason is that if a backend's InitPostgres transaction fails (eg,
|
|
||||||
* because an invalid user name was given), we have to be able to get through
|
|
||||||
* AbortTransaction without asserting.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
AtAbort_UserId(void)
|
|
||||||
{
|
|
||||||
CurrentUserId = OuterUserId;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Change session auth ID while running
|
* Change session auth ID while running
|
||||||
*
|
*
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2008, 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/miscadmin.h,v 1.198 2008/01/01 19:45:56 momjian Exp $
|
* $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.199 2008/01/03 21:23:15 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* some of the information in this file should be moved to other files.
|
* some of the information in this file should be moved to other files.
|
||||||
@ -234,12 +234,13 @@ extern void SetDatabasePath(const char *path);
|
|||||||
|
|
||||||
extern char *GetUserNameFromId(Oid roleid);
|
extern char *GetUserNameFromId(Oid roleid);
|
||||||
extern Oid GetUserId(void);
|
extern Oid GetUserId(void);
|
||||||
extern void SetUserId(Oid userid);
|
|
||||||
extern Oid GetOuterUserId(void);
|
extern Oid GetOuterUserId(void);
|
||||||
extern Oid GetSessionUserId(void);
|
extern Oid GetSessionUserId(void);
|
||||||
|
extern void GetUserIdAndContext(Oid *userid, bool *sec_def_context);
|
||||||
|
extern void SetUserIdAndContext(Oid userid, bool sec_def_context);
|
||||||
|
extern bool InSecurityDefinerContext(void);
|
||||||
extern void InitializeSessionUserId(const char *rolename);
|
extern void InitializeSessionUserId(const char *rolename);
|
||||||
extern void InitializeSessionUserIdStandalone(void);
|
extern void InitializeSessionUserIdStandalone(void);
|
||||||
extern void AtAbort_UserId(void);
|
|
||||||
extern void SetSessionAuthorization(Oid userid, bool is_superuser);
|
extern void SetSessionAuthorization(Oid userid, bool is_superuser);
|
||||||
extern Oid GetCurrentRoleId(void);
|
extern Oid GetCurrentRoleId(void);
|
||||||
extern void SetCurrentRoleId(Oid roleid, bool is_superuser);
|
extern void SetCurrentRoleId(Oid roleid, bool is_superuser);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user