LCOV - code coverage report
Current view: top level - src/backend/utils/init - usercontext.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 17 17 100.0 %
Date: 2024-12-12 17:14:55 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * usercontext.c
       4             :  *    Convenience functions for running code as a different database user.
       5             :  *
       6             :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/utils/init/usercontext.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include "miscadmin.h"
      18             : #include "utils/acl.h"
      19             : #include "utils/guc.h"
      20             : #include "utils/usercontext.h"
      21             : 
      22             : /*
      23             :  * Temporarily switch to a new user ID.
      24             :  *
      25             :  * If the current user doesn't have permission to SET ROLE to the new user,
      26             :  * an ERROR occurs.
      27             :  *
      28             :  * If the new user doesn't have permission to SET ROLE to the current user,
      29             :  * SECURITY_RESTRICTED_OPERATION is imposed and a new GUC nest level is
      30             :  * created so that any settings changes can be rolled back.
      31             :  */
      32             : void
      33      297520 : SwitchToUntrustedUser(Oid userid, UserContext *context)
      34             : {
      35             :     /* Get the current user ID and security context. */
      36      297520 :     GetUserIdAndSecContext(&context->save_userid,
      37             :                            &context->save_sec_context);
      38             : 
      39             :     /* Check that we have sufficient privileges to assume the target role. */
      40      297520 :     if (!member_can_set_role(context->save_userid, userid))
      41           2 :         ereport(ERROR,
      42             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
      43             :                  errmsg("role \"%s\" cannot SET ROLE to \"%s\"",
      44             :                         GetUserNameFromId(context->save_userid, false),
      45             :                         GetUserNameFromId(userid, false))));
      46             : 
      47             :     /*
      48             :      * Try to prevent the user to which we're switching from assuming the
      49             :      * privileges of the current user, unless they can SET ROLE to that user
      50             :      * anyway.
      51             :      */
      52      297518 :     if (member_can_set_role(userid, context->save_userid))
      53             :     {
      54             :         /*
      55             :          * Each user can SET ROLE to the other, so there's no point in
      56             :          * imposing any security restrictions. Just let the user do whatever
      57             :          * they want.
      58             :          */
      59      297458 :         SetUserIdAndSecContext(userid, context->save_sec_context);
      60      297458 :         context->save_nestlevel = -1;
      61             :     }
      62             :     else
      63             :     {
      64          60 :         int         sec_context = context->save_sec_context;
      65             : 
      66             :         /*
      67             :          * This user can SET ROLE to the target user, but not the other way
      68             :          * around, so protect ourselves against the target user by setting
      69             :          * SECURITY_RESTRICTED_OPERATION to prevent certain changes to the
      70             :          * session state. Also set up a new GUC nest level, so that we can
      71             :          * roll back any GUC changes that may be made by code running as the
      72             :          * target user, inasmuch as they could be malicious.
      73             :          */
      74          60 :         sec_context |= SECURITY_RESTRICTED_OPERATION;
      75          60 :         SetUserIdAndSecContext(userid, sec_context);
      76          60 :         context->save_nestlevel = NewGUCNestLevel();
      77             :     }
      78      297518 : }
      79             : 
      80             : /*
      81             :  * Switch back to the original user ID.
      82             :  *
      83             :  * If we created a new GUC nest level, also roll back any changes that were
      84             :  * made within it.
      85             :  */
      86             : void
      87      297472 : RestoreUserContext(UserContext *context)
      88             : {
      89      297472 :     if (context->save_nestlevel != -1)
      90          48 :         AtEOXact_GUC(false, context->save_nestlevel);
      91      297472 :     SetUserIdAndSecContext(context->save_userid, context->save_sec_context);
      92      297472 : }

Generated by: LCOV version 1.14