diff options
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/adt/ri_triggers.c | 125 | ||||
-rw-r--r-- | src/backend/utils/fmgr/fmgr.c | 11 | ||||
-rw-r--r-- | src/backend/utils/init/miscinit.c | 69 |
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); } |