*
* 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 $
*
* ----------
*/
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;
/*
* 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 - "
* 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 - "
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,
* 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);
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;
/*
* 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 - "
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;
/*
* 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 - "
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;
/*
* 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()");
bool isnull;
int i;
int j;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
Oid fk_owner;
ReferentialIntegritySnapshotOverride = true;
/*
* 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()");
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;
/*
* 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 - "
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;
/*
* 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 - "
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;
/*
* 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()");
int i;
int match_type;
bool use_cached_query;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
Oid fk_owner;
ReferentialIntegritySnapshotOverride = true;
/*
* 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()");
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;
/*
* 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()");
bool isnull;
int i;
int match_type;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
Oid fk_owner;
ReferentialIntegritySnapshotOverride = true;
/*
* 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()");
{
void *qplan;
Relation query_rel;
- Oid save_uid;
+ Oid save_userid;
+ bool save_secdefcxt;
/*
* The query is always run against the FK table except
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)
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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;
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)
}
-void
-SetUserId(Oid newid)
-{
- AssertArg(OidIsValid(newid));
- CurrentUserId = newid;
-}
-
-
/*
* This value is only relevant for informational purposes.
*/
}
-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)
{
elog(ERROR, "permission denied");
SetSessionUserId(userid);
- SetUserId(userid);
}