summaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/adt/ri_triggers.c125
-rw-r--r--src/backend/utils/fmgr/fmgr.c11
-rw-r--r--src/backend/utils/init/miscinit.c69
3 files changed, 129 insertions, 76 deletions
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index 6f85e6fc4a..acb17219da 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -17,7 +17,7 @@
*
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.43.2.5 2004/10/13 22:22:22 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.43.2.6 2008/01/03 21:25:58 tgl Exp $
*
* ----------
*/
@@ -178,9 +178,10 @@ RI_FKey_check(PG_FUNCTION_ARGS)
bool isnull;
int i;
int match_type;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
- save_uid = GetUserId();
+ GetUserIdAndContext(&save_userid, &save_secdefcxt);
ReferentialIntegritySnapshotOverride = true;
@@ -297,12 +298,12 @@ RI_FKey_check(PG_FUNCTION_ARGS)
/*
* Execute the plan
*/
- SetUserId(RelationGetForm(pk_rel)->relowner);
+ SetUserIdAndContext(RelationGetForm(pk_rel)->relowner, true);
if (SPI_execp(qplan, check_values, check_nulls, 1) != SPI_OK_SELECT)
elog(ERROR, "SPI_execp() failed in RI_FKey_check()");
- SetUserId(save_uid);
+ SetUserIdAndContext(save_userid, save_secdefcxt);
if (SPI_processed == 0)
elog(ERROR, "%s referential integrity violation - "
@@ -486,12 +487,12 @@ RI_FKey_check(PG_FUNCTION_ARGS)
* Now check that foreign key exists in PK table
*/
- SetUserId(RelationGetForm(pk_rel)->relowner);
+ SetUserIdAndContext(RelationGetForm(pk_rel)->relowner, true);
if (SPI_execp(qplan, check_values, check_nulls, 1) != SPI_OK_SELECT)
elog(ERROR, "SPI_execp() failed in RI_FKey_check()");
- SetUserId(save_uid);
+ SetUserIdAndContext(save_userid, save_secdefcxt);
if (SPI_processed == 0)
elog(ERROR, "%s referential integrity violation - "
@@ -558,10 +559,11 @@ ri_Check_Pk_Match(Relation pk_rel, HeapTuple old_row, Oid tgoid, int match_type,
Datum check_values[RI_MAX_NUMKEYS];
char check_nulls[RI_MAX_NUMKEYS + 1];
int i;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
bool result;
- save_uid = GetUserId();
+ GetUserIdAndContext(&save_userid, &save_secdefcxt);
ri_BuildQueryKeyPkCheck(&qkey, tgoid,
RI_PLAN_CHECK_LOOKUPPK, pk_rel,
@@ -681,12 +683,12 @@ ri_Check_Pk_Match(Relation pk_rel, HeapTuple old_row, Oid tgoid, int match_type,
* Now check that foreign key exists in PK table
*/
- SetUserId(RelationGetForm(pk_rel)->relowner);
+ SetUserIdAndContext(RelationGetForm(pk_rel)->relowner, true);
if (SPI_execp(qplan, check_values, check_nulls, 1) != SPI_OK_SELECT)
elog(ERROR, "SPI_execp() failed in ri_Check_Pk_Match()");
- SetUserId(save_uid);
+ SetUserIdAndContext(save_userid, save_secdefcxt);
result = (SPI_processed != 0);
@@ -721,9 +723,10 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS)
bool isnull;
int i;
int match_type;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
- save_uid = GetUserId();
+ GetUserIdAndContext(&save_userid, &save_secdefcxt);
ReferentialIntegritySnapshotOverride = true;
@@ -886,12 +889,12 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS)
/*
* Now check for existing references
*/
- SetUserId(RelationGetForm(pk_rel)->relowner);
+ SetUserIdAndContext(RelationGetForm(pk_rel)->relowner, true);
if (SPI_execp(qplan, del_values, del_nulls, 1) != SPI_OK_SELECT)
elog(ERROR, "SPI_execp() failed in RI_FKey_noaction_del()");
- SetUserId(save_uid);
+ SetUserIdAndContext(save_userid, save_secdefcxt);
if (SPI_processed > 0)
elog(ERROR, "%s referential integrity violation - "
@@ -948,9 +951,10 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS)
bool isnull;
int i;
int match_type;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
- save_uid = GetUserId();
+ GetUserIdAndContext(&save_userid, &save_secdefcxt);
ReferentialIntegritySnapshotOverride = true;
@@ -1124,12 +1128,12 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS)
/*
* Now check for existing references
*/
- SetUserId(RelationGetForm(pk_rel)->relowner);
+ SetUserIdAndContext(RelationGetForm(pk_rel)->relowner, true);
if (SPI_execp(qplan, upd_values, upd_nulls, 1) != SPI_OK_SELECT)
elog(ERROR, "SPI_execp() failed in RI_FKey_noaction_upd()");
- SetUserId(save_uid);
+ SetUserIdAndContext(save_userid, save_secdefcxt);
if (SPI_processed > 0)
elog(ERROR, "%s referential integrity violation - "
@@ -1182,7 +1186,8 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
char del_nulls[RI_MAX_NUMKEYS + 1];
bool isnull;
int i;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
Oid fk_owner;
ReferentialIntegritySnapshotOverride = true;
@@ -1333,13 +1338,13 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
/*
* Now delete constraint
*/
- save_uid = GetUserId();
- SetUserId(fk_owner);
+ GetUserIdAndContext(&save_userid, &save_secdefcxt);
+ SetUserIdAndContext(fk_owner, true);
if (SPI_execp(qplan, del_values, del_nulls, 0) != SPI_OK_DELETE)
elog(ERROR, "SPI_execp() failed in RI_FKey_cascade_del()");
- SetUserId(save_uid);
+ SetUserIdAndContext(save_userid, save_secdefcxt);
if (SPI_finish() != SPI_OK_FINISH)
elog(WARNING, "SPI_finish() failed in RI_FKey_cascade_del()");
@@ -1387,7 +1392,8 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
bool isnull;
int i;
int j;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
Oid fk_owner;
ReferentialIntegritySnapshotOverride = true;
@@ -1569,13 +1575,13 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
/*
* Now update the existing references
*/
- save_uid = GetUserId();
- SetUserId(fk_owner);
+ GetUserIdAndContext(&save_userid, &save_secdefcxt);
+ SetUserIdAndContext(fk_owner, true);
if (SPI_execp(qplan, upd_values, upd_nulls, 0) != SPI_OK_UPDATE)
elog(ERROR, "SPI_execp() failed in RI_FKey_cascade_upd()");
- SetUserId(save_uid);
+ SetUserIdAndContext(save_userid, save_secdefcxt);
if (SPI_finish() != SPI_OK_FINISH)
elog(WARNING, "SPI_finish() failed in RI_FKey_cascade_upd()");
@@ -1628,7 +1634,8 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS)
char del_nulls[RI_MAX_NUMKEYS + 1];
bool isnull;
int i;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
Oid fk_owner;
ReferentialIntegritySnapshotOverride = true;
@@ -1781,13 +1788,13 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS)
/*
* Now check for existing references
*/
- save_uid = GetUserId();
- SetUserId(fk_owner);
+ GetUserIdAndContext(&save_userid, &save_secdefcxt);
+ SetUserIdAndContext(fk_owner, true);
if (SPI_execp(qplan, del_values, del_nulls, 1) != SPI_OK_SELECT)
elog(ERROR, "SPI_execp() failed in RI_FKey_restrict_del()");
- SetUserId(save_uid);
+ SetUserIdAndContext(save_userid, save_secdefcxt);
if (SPI_processed > 0)
elog(ERROR, "%s referential integrity violation - "
@@ -1848,7 +1855,8 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS)
char upd_nulls[RI_MAX_NUMKEYS + 1];
bool isnull;
int i;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
Oid fk_owner;
ReferentialIntegritySnapshotOverride = true;
@@ -2012,15 +2020,13 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS)
/*
* Now check for existing references
*/
- save_uid = GetUserId();
- SetUserId(fk_owner);
-
- SetUserId(RelationGetForm(pk_rel)->relowner);
+ GetUserIdAndContext(&save_userid, &save_secdefcxt);
+ SetUserIdAndContext(RelationGetForm(pk_rel)->relowner, true);
if (SPI_execp(qplan, upd_values, upd_nulls, 1) != SPI_OK_SELECT)
elog(ERROR, "SPI_execp() failed in RI_FKey_restrict_upd()");
- SetUserId(save_uid);
+ SetUserIdAndContext(save_userid, save_secdefcxt);
if (SPI_processed > 0)
elog(ERROR, "%s referential integrity violation - "
@@ -2073,7 +2079,8 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS)
char upd_nulls[RI_MAX_NUMKEYS + 1];
bool isnull;
int i;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
Oid fk_owner;
ReferentialIntegritySnapshotOverride = true;
@@ -2234,13 +2241,13 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS)
/*
* Now update the existing references
*/
- save_uid = GetUserId();
- SetUserId(fk_owner);
+ GetUserIdAndContext(&save_userid, &save_secdefcxt);
+ SetUserIdAndContext(fk_owner, true);
if (SPI_execp(qplan, upd_values, upd_nulls, 0) != SPI_OK_UPDATE)
elog(ERROR, "SPI_execp() failed in RI_FKey_setnull_del()");
- SetUserId(save_uid);
+ SetUserIdAndContext(save_userid, save_secdefcxt);
if (SPI_finish() != SPI_OK_FINISH)
elog(WARNING, "SPI_finish() failed in RI_FKey_setnull_del()");
@@ -2289,7 +2296,8 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS)
int i;
int match_type;
bool use_cached_query;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
Oid fk_owner;
ReferentialIntegritySnapshotOverride = true;
@@ -2495,13 +2503,13 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS)
/*
* Now update the existing references
*/
- save_uid = GetUserId();
- SetUserId(fk_owner);
+ GetUserIdAndContext(&save_userid, &save_secdefcxt);
+ SetUserIdAndContext(fk_owner, true);
if (SPI_execp(qplan, upd_values, upd_nulls, 0) != SPI_OK_UPDATE)
elog(ERROR, "SPI_execp() failed in RI_FKey_setnull_upd()");
- SetUserId(save_uid);
+ SetUserIdAndContext(save_userid, save_secdefcxt);
if (SPI_finish() != SPI_OK_FINISH)
elog(WARNING, "SPI_finish() failed in RI_FKey_setnull_upd()");
@@ -2547,7 +2555,8 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
char upd_nulls[RI_MAX_NUMKEYS + 1];
bool isnull;
int i;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
Oid fk_owner;
ReferentialIntegritySnapshotOverride = true;
@@ -2739,13 +2748,13 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
/*
* Now update the existing references
*/
- save_uid = GetUserId();
- SetUserId(fk_owner);
+ GetUserIdAndContext(&save_userid, &save_secdefcxt);
+ SetUserIdAndContext(fk_owner, true);
if (SPI_execp(qplan, upd_values, upd_nulls, 0) != SPI_OK_UPDATE)
elog(ERROR, "SPI_execp() failed in RI_FKey_setdefault_del()");
- SetUserId(save_uid);
+ SetUserIdAndContext(save_userid, save_secdefcxt);
if (SPI_finish() != SPI_OK_FINISH)
elog(WARNING, "SPI_finish() failed in RI_FKey_setdefault_del()");
@@ -2803,7 +2812,8 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
bool isnull;
int i;
int match_type;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
Oid fk_owner;
ReferentialIntegritySnapshotOverride = true;
@@ -3018,13 +3028,13 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
/*
* Now update the existing references
*/
- save_uid = GetUserId();
- SetUserId(fk_owner);
+ GetUserIdAndContext(&save_userid, &save_secdefcxt);
+ SetUserIdAndContext(fk_owner, true);
if (SPI_execp(qplan, upd_values, upd_nulls, 0) != SPI_OK_UPDATE)
elog(ERROR, "SPI_execp() failed in RI_FKey_setdefault_upd()");
- SetUserId(save_uid);
+ SetUserIdAndContext(save_userid, save_secdefcxt);
if (SPI_finish() != SPI_OK_FINISH)
elog(WARNING, "SPI_finish() failed in RI_FKey_setdefault_upd()");
@@ -3171,7 +3181,8 @@ ri_PlanCheck(char *querystr, int nargs, Oid *argtypes,
{
void *qplan;
Relation query_rel;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
/*
* The query is always run against the FK table except
@@ -3185,14 +3196,14 @@ ri_PlanCheck(char *querystr, int nargs, Oid *argtypes,
query_rel = fk_rel;
/* Switch to proper UID to perform check as */
- save_uid = GetUserId();
- SetUserId(RelationGetForm(query_rel)->relowner);
+ GetUserIdAndContext(&save_userid, &save_secdefcxt);
+ SetUserIdAndContext(RelationGetForm(query_rel)->relowner, true);
/* Create the plan */
qplan = SPI_prepare(querystr, nargs, argtypes);
/* Restore UID */
- SetUserId(save_uid);
+ SetUserIdAndContext(save_userid, save_secdefcxt);
/* Save the plan if requested */
if (cache_plan)
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 470d4a11dd..5cebe0595b 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.63 2002/10/04 17:19:55 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.63.2.1 2008/01/03 21:25:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -651,6 +651,7 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
FmgrInfo *save_flinfo;
struct fmgr_security_definer_cache *fcache;
Oid save_userid;
+ bool save_secdefcxt;
HeapTuple tuple;
if (!fcinfo->flinfo->fn_extra)
@@ -673,16 +674,18 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
else
fcache = fcinfo->flinfo->fn_extra;
+ GetUserIdAndContext(&save_userid, &save_secdefcxt);
+ SetUserIdAndContext(fcache->userid, true);
+
save_flinfo = fcinfo->flinfo;
fcinfo->flinfo = &fcache->flinfo;
- save_userid = GetUserId();
- SetUserId(fcache->userid);
result = FunctionCallInvoke(fcinfo);
- SetUserId(save_userid);
fcinfo->flinfo = save_flinfo;
+ SetUserIdAndContext(save_userid, save_secdefcxt);
+
return result;
}
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index f41706862f..e772d6a8ec 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.96 2002/09/04 20:31:31 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.96.2.1 2008/01/03 21:25:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -483,6 +483,9 @@ GetCharSetByHost(char *TableName, int host, const char *DataDir)
* are implemented. Conceptually there is a stack, whose bottom
* is the session user. You are yourself responsible to save and
* restore the current user id if you need to change it.
+ *
+ * SecurityDefinerContext is TRUE if we are within a SECURITY DEFINER function
+ * or another context that temporarily changes CurrentUserId.
* ----------------------------------------------------------------
*/
static Oid AuthenticatedUserId = InvalidOid;
@@ -491,8 +494,13 @@ static Oid CurrentUserId = InvalidOid;
static bool AuthenticatedUserIsSuperuser = false;
+static bool SecurityDefinerContext = false;
+
+
/*
- * This function is relevant for all privilege checks.
+ * GetUserId - get the current effective user ID.
+ *
+ * Note: there's no SetUserId() anymore; use SetUserIdAndContext().
*/
Oid
GetUserId(void)
@@ -502,14 +510,6 @@ GetUserId(void)
}
-void
-SetUserId(Oid newid)
-{
- AssertArg(OidIsValid(newid));
- CurrentUserId = newid;
-}
-
-
/*
* This value is only relevant for informational purposes.
*/
@@ -521,17 +521,57 @@ GetSessionUserId(void)
}
-void
+static void
SetSessionUserId(Oid newid)
{
+ AssertState(!SecurityDefinerContext);
AssertArg(OidIsValid(newid));
SessionUserId = newid;
- /* Current user defaults to session user. */
- if (!OidIsValid(CurrentUserId))
- CurrentUserId = newid;
+ CurrentUserId = newid;
}
+/*
+ * 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
+ */
void
InitializeSessionUserId(const char *username)
{
@@ -616,7 +656,6 @@ SetSessionAuthorization(Oid userid)
elog(ERROR, "permission denied");
SetSessionUserId(userid);
- SetUserId(userid);
}