Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 9 additions & 13 deletions src/backend/commands/user.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,6 @@ typedef enum
/* Potentially set by pg_upgrade_support functions */
Oid binary_upgrade_next_pg_authid_oid = InvalidOid;

typedef struct
{
unsigned specified;
bool admin;
bool inherit;
bool set;
} GrantRoleOptions;

#define GRANT_ROLE_SPECIFIED_ADMIN 0x0001
#define GRANT_ROLE_SPECIFIED_INHERIT 0x0002
#define GRANT_ROLE_SPECIFIED_SET 0x0004
Expand All @@ -89,7 +81,7 @@ GrantRoleOptions createrole_self_grant_options;

/* Hook to check passwords in CreateRole() and AlterRole() */
check_password_hook_type check_password_hook = NULL;

CheckRoleMembershipAuthorization_hook_type CheckRoleMembershipAuthorization_hook = NULL;
static void AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
List *memberSpecs, List *memberIds,
Oid grantorId, GrantRoleOptions *popt);
Expand All @@ -98,7 +90,7 @@ static void DelRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
Oid grantorId, GrantRoleOptions *popt,
DropBehavior behavior);
static void check_role_membership_authorization(Oid currentUserId, Oid roleid,
bool is_grant);
bool is_grant, List* memberIds, GrantRoleOptions * popt);
static Oid check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId,
bool is_grant);
static RevokeRoleGrantAction *initialize_revoke_actions(CatCList *memlist);
Expand Down Expand Up @@ -517,7 +509,7 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
char *oldrolename = NameStr(oldroleform->rolname);

/* can only add this role to roles for which you have rights */
check_role_membership_authorization(currentUserId, oldroleid, true);
check_role_membership_authorization(currentUserId, oldroleid, true, thisrole_oidlist, &popt);
AddRoleMems(currentUserId, oldrolename, oldroleid,
thisrole_list,
thisrole_oidlist,
Expand Down Expand Up @@ -1557,7 +1549,7 @@ GrantRole(ParseState *pstate, GrantRoleStmt *stmt)

roleid = get_role_oid(rolename, false);
check_role_membership_authorization(currentUserId,
roleid, stmt->is_grant);
roleid, stmt->is_grant, grantee_ids, &popt);
if (stmt->is_grant)
AddRoleMems(currentUserId, rolename, roleid,
stmt->grantee_roles, grantee_ids,
Expand Down Expand Up @@ -2108,7 +2100,7 @@ DelRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
*/
static void
check_role_membership_authorization(Oid currentUserId, Oid roleid,
bool is_grant)
bool is_grant, List *memberIds, GrantRoleOptions * popt)
{
/*
* The charter of pg_database_owner is to have exactly one, implicit,
Expand Down Expand Up @@ -2147,6 +2139,10 @@ check_role_membership_authorization(Oid currentUserId, Oid roleid,
}
else
{
if (CheckRoleMembershipAuthorization_hook && CheckRoleMembershipAuthorization_hook(currentUserId, roleid, is_grant, memberIds, popt))
{
return;
}
/*
* Otherwise, must have admin option on the role to be changed.
*/
Expand Down
6 changes: 6 additions & 0 deletions src/backend/utils/adt/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ static void RoleMembershipCacheCallback(Datum arg, int cacheid, uint32 hashvalue
* Generally neon_superuser on neon.com
*/
char *privileged_role_name = NULL;
SelectBestAdmin_hook_type SelectBestAdmin_hook = NULL;

bool
is_privileged_role(void)
Expand Down Expand Up @@ -5336,6 +5337,11 @@ select_best_admin(Oid member, Oid role)
return InvalidOid;

(void) roles_is_member_of(member, ROLERECURSE_PRIVS, role, &admin_role);

if (SelectBestAdmin_hook)
{
SelectBestAdmin_hook(&admin_role, member, role);
}
return admin_role;
}

Expand Down
11 changes: 11 additions & 0 deletions src/include/commands/user.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@
#include "parser/parse_node.h"
#include "utils/guc.h"

typedef struct
{
unsigned specified;
bool admin;
bool inherit;
bool set;
} GrantRoleOptions;

/* GUCs */
extern PGDLLIMPORT int Password_encryption; /* values from enum PasswordType */
extern PGDLLIMPORT char *createrole_self_grant;
Expand All @@ -26,6 +34,9 @@ typedef void (*check_password_hook_type) (const char *username, const char *shad

extern PGDLLIMPORT check_password_hook_type check_password_hook;

typedef bool (*CheckRoleMembershipAuthorization_hook_type) (Oid currentUserId, Oid roleid, bool is_grant, List *memberIds, GrantRoleOptions * popt);
extern PGDLLIMPORT CheckRoleMembershipAuthorization_hook_type CheckRoleMembershipAuthorization_hook;

extern Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt);
extern Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt);
extern Oid AlterRoleSet(AlterRoleSetStmt *stmt);
Expand Down
3 changes: 3 additions & 0 deletions src/include/utils/acl.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,4 +287,7 @@ extern bool object_ownercheck(Oid classid, Oid objectid, Oid roleid);
extern bool has_createrole_privilege(Oid roleid);
extern bool has_bypassrls_privilege(Oid roleid);

typedef void (*SelectBestAdmin_hook_type) (Oid* admin_role, Oid member, Oid role);
extern PGDLLIMPORT SelectBestAdmin_hook_type SelectBestAdmin_hook;

#endif /* ACL_H */