aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/init/miscinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/init/miscinit.c')
-rw-r--r--src/backend/utils/init/miscinit.c95
1 files changed, 77 insertions, 18 deletions
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 7a81fabb8fb..34dfe670e43 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.150.2.2 2008/01/03 21:24:26 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.150.2.3 2009/12/09 21:58:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -293,8 +293,10 @@ make_absolute_path(const char *path)
* be the same as OuterUserId, but it changes during calls to SECURITY
* 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.
+ * SecurityRestrictionContext holds flags indicating reason(s) for changing
+ * CurrentUserId. In some cases we need to lock down operations that are
+ * not directly controlled by privilege settings, and this provides a
+ * convenient way to do it.
* ----------------------------------------------------------------
*/
static Oid AuthenticatedUserId = InvalidOid;
@@ -306,7 +308,7 @@ static Oid CurrentUserId = InvalidOid;
static bool AuthenticatedUserIsSuperuser = false;
static bool SessionUserIsSuperuser = false;
-static bool SecurityDefinerContext = false;
+static int SecurityRestrictionContext = 0;
/* We also remember if a SET ROLE is currently active */
static bool SetRoleIsActive = false;
@@ -315,7 +317,7 @@ static bool SetRoleIsActive = false;
/*
* GetUserId - get the current effective user ID.
*
- * Note: there's no SetUserId() anymore; use SetUserIdAndContext().
+ * Note: there's no SetUserId() anymore; use SetUserIdAndSecContext().
*/
Oid
GetUserId(void)
@@ -339,7 +341,7 @@ GetOuterUserId(void)
static void
SetOuterUserId(Oid userid)
{
- AssertState(!SecurityDefinerContext);
+ AssertState(SecurityRestrictionContext == 0);
AssertArg(OidIsValid(userid));
OuterUserId = userid;
@@ -362,7 +364,7 @@ GetSessionUserId(void)
static void
SetSessionUserId(Oid userid, bool is_superuser)
{
- AssertState(!SecurityDefinerContext);
+ AssertState(SecurityRestrictionContext == 0);
AssertArg(OidIsValid(userid));
SessionUserId = userid;
SessionUserIsSuperuser = is_superuser;
@@ -375,11 +377,29 @@ SetSessionUserId(Oid userid, bool is_superuser)
/*
- * GetUserIdAndContext/SetUserIdAndContext - get/set the current user ID
- * and the SecurityDefinerContext flag.
+ * GetUserIdAndSecContext/SetUserIdAndSecContext - get/set the current user ID
+ * and the SecurityRestrictionContext flags.
*
- * Unlike GetUserId, GetUserIdAndContext does *not* Assert that the current
- * value of CurrentUserId is valid; nor does SetUserIdAndContext require
+ * Currently there are two valid bits in SecurityRestrictionContext:
+ *
+ * SECURITY_LOCAL_USERID_CHANGE indicates that we are inside an operation
+ * that is temporarily changing CurrentUserId via these functions. This is
+ * needed to indicate that the actual value of CurrentUserId is not in sync
+ * with guc.c's internal state, so SET ROLE has to be disallowed.
+ *
+ * SECURITY_RESTRICTED_OPERATION indicates that we are inside an operation
+ * that does not wish to trust called user-defined functions at all. This
+ * bit prevents not only SET ROLE, but various other changes of session state
+ * that normally is unprotected but might possibly be used to subvert the
+ * calling session later. An example is replacing an existing prepared
+ * statement with new code, which will then be executed with the outer
+ * session's permissions when the prepared statement is next used. Since
+ * these restrictions are fairly draconian, we apply them only in contexts
+ * where the called functions are really supposed to be side-effect-free
+ * anyway, such as VACUUM/ANALYZE/REINDEX.
+ *
+ * Unlike GetUserId, GetUserIdAndSecContext does *not* Assert that the current
+ * value of CurrentUserId is valid; nor does SetUserIdAndSecContext 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,
@@ -388,27 +408,66 @@ SetSessionUserId(Oid userid, bool is_superuser)
* through AbortTransaction without asserting in case InitPostgres fails.
*/
void
-GetUserIdAndContext(Oid *userid, bool *sec_def_context)
+GetUserIdAndSecContext(Oid *userid, int *sec_context)
{
*userid = CurrentUserId;
- *sec_def_context = SecurityDefinerContext;
+ *sec_context = SecurityRestrictionContext;
}
void
-SetUserIdAndContext(Oid userid, bool sec_def_context)
+SetUserIdAndSecContext(Oid userid, int sec_context)
{
CurrentUserId = userid;
- SecurityDefinerContext = sec_def_context;
+ SecurityRestrictionContext = sec_context;
}
/*
- * InSecurityDefinerContext - are we inside a SECURITY DEFINER context?
+ * InLocalUserIdChange - are we inside a local change of CurrentUserId?
*/
bool
-InSecurityDefinerContext(void)
+InLocalUserIdChange(void)
{
- return SecurityDefinerContext;
+ return (SecurityRestrictionContext & SECURITY_LOCAL_USERID_CHANGE) != 0;
+}
+
+/*
+ * InSecurityRestrictedOperation - are we inside a security-restricted command?
+ */
+bool
+InSecurityRestrictedOperation(void)
+{
+ return (SecurityRestrictionContext & SECURITY_RESTRICTED_OPERATION) != 0;
+}
+
+
+/*
+ * These are obsolete versions of Get/SetUserIdAndSecContext that are
+ * only provided for bug-compatibility with some rather dubious code in
+ * pljava. We allow the userid to be set, but only when not inside a
+ * security restriction context.
+ */
+void
+GetUserIdAndContext(Oid *userid, bool *sec_def_context)
+{
+ *userid = CurrentUserId;
+ *sec_def_context = InLocalUserIdChange();
+}
+
+void
+SetUserIdAndContext(Oid userid, bool sec_def_context)
+{
+ /* We throw the same error SET ROLE would. */
+ if (InSecurityRestrictedOperation())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("cannot set parameter \"%s\" within security-restricted operation",
+ "role")));
+ CurrentUserId = userid;
+ if (sec_def_context)
+ SecurityRestrictionContext |= SECURITY_LOCAL_USERID_CHANGE;
+ else
+ SecurityRestrictionContext &= ~SECURITY_LOCAL_USERID_CHANGE;
}