LCOV - code coverage report
Current view: top level - src/backend/utils/init - usercontext.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 100.0 % 17 17
Test Date: 2026-03-03 02:14:47 Functions: 100.0 % 2 2
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-2026, 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       148564 : SwitchToUntrustedUser(Oid userid, UserContext *context)
      34              : {
      35              :     /* Get the current user ID and security context. */
      36       148564 :     GetUserIdAndSecContext(&context->save_userid,
      37              :                            &context->save_sec_context);
      38              : 
      39              :     /* Check that we have sufficient privileges to assume the target role. */
      40       148564 :     if (!member_can_set_role(context->save_userid, userid))
      41            1 :         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       148563 :     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       148530 :         SetUserIdAndSecContext(userid, context->save_sec_context);
      60       148530 :         context->save_nestlevel = -1;
      61              :     }
      62              :     else
      63              :     {
      64           33 :         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           33 :         sec_context |= SECURITY_RESTRICTED_OPERATION;
      75           33 :         SetUserIdAndSecContext(userid, sec_context);
      76           33 :         context->save_nestlevel = NewGUCNestLevel();
      77              :     }
      78       148563 : }
      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       148505 : RestoreUserContext(UserContext *context)
      88              : {
      89       148505 :     if (context->save_nestlevel != -1)
      90           24 :         AtEOXact_GUC(false, context->save_nestlevel);
      91       148505 :     SetUserIdAndSecContext(context->save_userid, context->save_sec_context);
      92       148505 : }
        

Generated by: LCOV version 2.0-1