/
githubmirror
/
postgres
Обзор
Документация
Войти
/
githubmirror
/
postgres
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/backend/utils/init/usercontext.c
98 строк
3 KB
Noah Misch
Empty search_path in amcheck.
10 авг 2026, 16:37
10 авг 2026, 16:37
0fbf785
Код
Авторство
О чём код?
/*------------------------------------------------------------------------- * * usercontext.c * Convenience functions for running code as a different database user. * * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION * src/backend/utils/init/usercontext.c * *------------------------------------------------------------------------- */ #include "postgres.h" #include "miscadmin.h" #include "utils/acl.h" #include "utils/guc.h" #include "utils/usercontext.h" /* * Temporarily switch to a new user ID. * * If the current user doesn't have permission to SET ROLE to the new user, * an ERROR occurs. * * If the new user doesn't have permission to SET ROLE to the current user, * SECURITY_RESTRICTED_OPERATION is imposed and a new GUC nest level is * created so that any settings changes can be rolled back. */ void SwitchToUntrustedUser(Oid userid, UserContext *context) { /* Get the current user ID and security context. */ GetUserIdAndSecContext(&context->save_userid, &context->save_sec_context); /* Check that we have sufficient privileges to assume the target role. */ if (!member_can_set_role(context->save_userid, userid)) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("role \"%s\" cannot SET ROLE to \"%s\"", GetUserNameFromId(context->save_userid, false), GetUserNameFromId(userid, false)))); /* * Try to prevent the user to which we're switching from assuming the * privileges of the current user, unless they can SET ROLE to that user * anyway. */ if (member_can_set_role(userid, context->save_userid)) { /* * Each user can SET ROLE to the other, so there's no point in * imposing any security restrictions. Just let the user do whatever * they want. */ SetUserIdAndSecContext(userid, context->save_sec_context); context->save_nestlevel = -1; } else { int sec_context = context->save_sec_context; /* * This user can SET ROLE to the target user, but not the other way * around, so protect ourselves against the target user by setting * SECURITY_RESTRICTED_OPERATION to prevent certain changes to the * session state. Also set up a new GUC nest level, so that we can * roll back any GUC changes that may be made by code running as the * target user, inasmuch as they could be malicious. * * Unlike most use of SECURITY_RESTRICTED_OPERATION, this opts not to * use RestrictSearchPath(). Calling it would just stop the current * user from attacking "userid", but we've already established that * the current user could just SET ROLE to "userid". Calling it would * be a compatibility break. */ sec_context |= SECURITY_RESTRICTED_OPERATION; SetUserIdAndSecContext(userid, sec_context); context->save_nestlevel = NewGUCNestLevel(); } } /* * Switch back to the original user ID. * * If we created a new GUC nest level, also roll back any changes that were * made within it. */ void RestoreUserContext(UserContext *context) { if (context->save_nestlevel != -1) AtEOXact_GUC(false, context->save_nestlevel); SetUserIdAndSecContext(context->save_userid, context->save_sec_context); }