Skip to content

Commit 01ead9a

Browse files
This functionality can allow users to get temporary SU permisions, within
a certain scope. See $hadron$/pgxn/neon/su_statements.c for details.
1 parent 2933c9e commit 01ead9a

8 files changed

Lines changed: 69 additions & 9 deletions

File tree

src/backend/commands/event_trigger.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ typedef struct EventTriggerQueryState
7474
} EventTriggerQueryState;
7575

7676
static EventTriggerQueryState *currentEventTriggerState = NULL;
77+
EventTrigger_hook_type EventTrigger_hook = NULL;
7778

7879
/* Support for dropped objects */
7980
typedef struct SQLDropObject
@@ -922,7 +923,10 @@ EventTriggerInvoke(List *fn_oid_list, EventTriggerData *trigdata)
922923
InitFunctionCallInfoData(*fcinfo, &flinfo, 0,
923924
InvalidOid, (Node *) trigdata, NULL);
924925
pgstat_init_function_usage(fcinfo, &fcusage);
925-
FunctionCallInvoke(fcinfo);
926+
if (EventTrigger_hook)
927+
EventTrigger_hook(fcinfo);
928+
else
929+
FunctionCallInvoke(fcinfo);
926930
pgstat_end_function_usage(&fcusage, true);
927931

928932
/* Reclaim memory. */

src/backend/commands/trigger.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ int SessionReplicationRole = SESSION_REPLICATION_ROLE_ORIGIN;
7070
/* How many levels deep into trigger execution are we? */
7171
static int MyTriggerDepth = 0;
7272

73+
DataTrigger_hook_type DataTrigger_hook = NULL;
74+
7375
/* Local function prototypes */
7476
static void renametrig_internal(Relation tgrel, Relation targetrel,
7577
HeapTuple trigtup, const char *newname,
@@ -2429,7 +2431,10 @@ ExecCallTriggerFunc(TriggerData *trigdata,
24292431
MyTriggerDepth++;
24302432
PG_TRY();
24312433
{
2432-
result = FunctionCallInvoke(fcinfo);
2434+
if (DataTrigger_hook)
2435+
result = DataTrigger_hook(fcinfo);
2436+
else
2437+
result = FunctionCallInvoke(fcinfo);
24332438
}
24342439
PG_FINALLY();
24352440
{

src/backend/utils/adt/acl.c

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,24 @@ static void RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue
123123
*/
124124
char *privileged_role_name = NULL;
125125

126+
static bool
127+
is_privileged_role_arg_super(Oid roleid, bool nosuper)
128+
{
129+
Oid privileged_role_oid;
130+
131+
if (privileged_role_name == NULL)
132+
return false;
133+
134+
privileged_role_oid = get_role_oid(privileged_role_name, true /* missing_ok */);
135+
136+
if (privileged_role_oid == InvalidOid)
137+
return false;
138+
139+
if (nosuper)
140+
return has_privs_of_role_nosuper(roleid, privileged_role_oid);
141+
return has_privs_of_role(roleid, privileged_role_oid);
142+
}
143+
126144
bool
127145
is_privileged_role(void)
128146
{
@@ -132,14 +150,12 @@ is_privileged_role(void)
132150
bool
133151
is_privileged_role_arg(Oid roleid)
134152
{
135-
Oid privileged_role_oid;
136-
137-
if (privileged_role_name == NULL)
138-
return false;
139-
140-
privileged_role_oid = get_role_oid(privileged_role_name, true /* missing_ok */);
153+
return is_privileged_role_arg_super(roleid, false);
154+
}
141155

142-
return privileged_role_oid != InvalidOid && has_privs_of_role(roleid, privileged_role_oid);
156+
bool is_privileged_role_nosuper(void)
157+
{
158+
return is_privileged_role_arg_super(GetUserId(), true);
143159
}
144160

145161
/*
@@ -5008,6 +5024,23 @@ has_privs_of_role(Oid member, Oid role)
50085024
role);
50095025
}
50105026

5027+
/*
5028+
* Same as has_privs_of_role, but ignores checking superuser.
5029+
*/
5030+
bool
5031+
has_privs_of_role_nosuper(Oid member, Oid role)
5032+
{
5033+
/* Fast path for simple case */
5034+
if (member == role)
5035+
return true;
5036+
/*
5037+
* Find all the roles that member has the privileges of, including
5038+
* multi-level recursion, then see if target role is any one of them.
5039+
*/
5040+
return list_member_oid(roles_is_member_of(member, ROLERECURSE_PRIVS,
5041+
InvalidOid, NULL),
5042+
role);
5043+
}
50115044

50125045
/*
50135046
* Is member a member of role (directly or indirectly)?

src/backend/utils/misc/superuser.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
static Oid last_roleid = InvalidOid; /* InvalidOid == cache not valid */
3636
static bool last_roleid_is_super = false;
3737
static bool roleid_callback_registered = false;
38+
SUForUser_hook_type SUForUser_hook = NULL;
3839

3940
static void RoleidCallback(Datum arg, int cacheid, uint32 hashvalue);
4041

@@ -72,6 +73,11 @@ superuser_arg(Oid roleid)
7273
{
7374
result = ((Form_pg_authid) GETSTRUCT(rtup))->rolsuper;
7475
ReleaseSysCache(rtup);
76+
77+
if (!result && SUForUser_hook != NULL)
78+
{
79+
result = SUForUser_hook(roleid);
80+
}
7581
}
7682
else
7783
{

src/include/commands/event_trigger.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "catalog/dependency.h"
1717
#include "catalog/objectaddress.h"
1818
#include "catalog/pg_event_trigger.h"
19+
#include "fmgr.h"
1920
#include "nodes/parsenodes.h"
2021
#include "tcop/cmdtag.h"
2122
#include "tcop/deparse_utility.h"
@@ -47,6 +48,9 @@ typedef struct EventTriggerData
4748
#define CALLED_AS_EVENT_TRIGGER(fcinfo) \
4849
((fcinfo)->context != NULL && IsA((fcinfo)->context, EventTriggerData))
4950

51+
typedef void (*EventTrigger_hook_type)(FunctionCallInfo fcinfo);
52+
extern PGDLLEXPORT EventTrigger_hook_type EventTrigger_hook;
53+
5054
extern Oid CreateEventTrigger(CreateEventTrigStmt *stmt);
5155
extern Oid get_event_trigger_oid(const char *trigname, bool missing_ok);
5256

src/include/commands/trigger.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ extern PGDLLIMPORT int SessionReplicationRole;
151151
#define TRIGGER_FIRES_ON_REPLICA 'R'
152152
#define TRIGGER_DISABLED 'D'
153153

154+
typedef Datum (*DataTrigger_hook_type)(FunctionCallInfo fcinfo);
155+
extern PGDLLEXPORT DataTrigger_hook_type DataTrigger_hook;
156+
154157
extern ObjectAddress CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
155158
Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid,
156159
Oid funcoid, Oid parentTriggerOid, Node *whenClause,

src/include/miscadmin.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,9 +379,13 @@ extern void SetCurrentRoleId(Oid roleid, bool is_superuser);
379379
extern bool superuser(void); /* current user is superuser */
380380
extern bool superuser_arg(Oid roleid); /* given user is superuser */
381381

382+
typedef bool (*SUForUser_hook_type) (Oid roleid);
383+
extern SUForUser_hook_type SUForUser_hook;
384+
382385
/* in utils/adt/acl.c */
383386
extern PGDLLIMPORT char *privileged_role_name;
384387
extern bool is_privileged_role(void); /* current user is a privileged role */
388+
extern bool is_privileged_role_nosuper(void); /* current user is a privileged role */
385389
extern bool is_privileged_role_arg(Oid roleid); /* given user is a privileged role */
386390

387391

src/include/utils/acl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ extern AclMode aclmask(const Acl *acl, Oid roleid, Oid ownerId,
209209
extern int aclmembers(const Acl *acl, Oid **roleids);
210210

211211
extern bool has_privs_of_role(Oid member, Oid role);
212+
extern bool has_privs_of_role_nosuper(Oid member, Oid role);
212213
extern bool is_member_of_role(Oid member, Oid role);
213214
extern bool is_member_of_role_nosuper(Oid member, Oid role);
214215
extern bool is_admin_of_role(Oid member, Oid role);

0 commit comments

Comments
 (0)