1 /*-------------------------------------------------------------------------
4 * Commands for manipulating roles (formerly called users).
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * src/backend/commands/user.c
11 *-------------------------------------------------------------------------
15 #include "access/genam.h"
16 #include "access/htup_details.h"
17 #include "access/table.h"
18 #include "access/xact.h"
19 #include "catalog/binary_upgrade.h"
20 #include "catalog/catalog.h"
21 #include "catalog/dependency.h"
22 #include "catalog/indexing.h"
23 #include "catalog/objectaccess.h"
24 #include "catalog/pg_auth_members.h"
25 #include "catalog/pg_authid.h"
26 #include "catalog/pg_database.h"
27 #include "catalog/pg_db_role_setting.h"
28 #include "commands/comment.h"
29 #include "commands/dbcommands.h"
30 #include "commands/defrem.h"
31 #include "commands/seclabel.h"
32 #include "commands/user.h"
33 #include "libpq/crypt.h"
34 #include "miscadmin.h"
35 #include "storage/lmgr.h"
36 #include "utils/acl.h"
37 #include "utils/builtins.h"
38 #include "utils/catcache.h"
39 #include "utils/fmgroids.h"
40 #include "utils/syscache.h"
41 #include "utils/varlena.h"
44 * Removing a role grant - or the admin option on it - might recurse to
45 * dependent grants. We use these values to reason about what would need to
46 * be done in such cases.
48 * RRG_NOOP indicates a grant that would not need to be altered by the
51 * RRG_REMOVE_ADMIN_OPTION indicates a grant that would need to have
52 * admin_option set to false by the operation.
54 * Similarly, RRG_REMOVE_INHERIT_OPTION and RRG_REMOVE_SET_OPTION indicate
55 * grants that would need to have the corresponding options set to false.
57 * RRG_DELETE_GRANT indicates a grant that would need to be removed entirely
63 RRG_REMOVE_ADMIN_OPTION
,
64 RRG_REMOVE_INHERIT_OPTION
,
65 RRG_REMOVE_SET_OPTION
,
67 } RevokeRoleGrantAction
;
69 /* Potentially set by pg_upgrade_support functions */
70 Oid binary_upgrade_next_pg_authid_oid
= InvalidOid
;
80 #define GRANT_ROLE_SPECIFIED_ADMIN 0x0001
81 #define GRANT_ROLE_SPECIFIED_INHERIT 0x0002
82 #define GRANT_ROLE_SPECIFIED_SET 0x0004
85 int Password_encryption
= PASSWORD_TYPE_SCRAM_SHA_256
;
86 char *createrole_self_grant
= "";
87 static bool createrole_self_grant_enabled
= false;
88 static GrantRoleOptions createrole_self_grant_options
;
90 /* Hook to check passwords in CreateRole() and AlterRole() */
91 check_password_hook_type check_password_hook
= NULL
;
93 static void AddRoleMems(Oid currentUserId
, const char *rolename
, Oid roleid
,
94 List
*memberSpecs
, List
*memberIds
,
95 Oid grantorId
, GrantRoleOptions
*popt
);
96 static void DelRoleMems(Oid currentUserId
, const char *rolename
, Oid roleid
,
97 List
*memberSpecs
, List
*memberIds
,
98 Oid grantorId
, GrantRoleOptions
*popt
,
99 DropBehavior behavior
);
100 static void check_role_membership_authorization(Oid currentUserId
, Oid roleid
,
102 static Oid
check_role_grantor(Oid currentUserId
, Oid roleid
, Oid grantorId
,
104 static RevokeRoleGrantAction
*initialize_revoke_actions(CatCList
*memlist
);
105 static bool plan_single_revoke(CatCList
*memlist
,
106 RevokeRoleGrantAction
*actions
,
107 Oid member
, Oid grantor
,
108 GrantRoleOptions
*popt
,
109 DropBehavior behavior
);
110 static void plan_member_revoke(CatCList
*memlist
,
111 RevokeRoleGrantAction
*actions
, Oid member
);
112 static void plan_recursive_revoke(CatCList
*memlist
,
113 RevokeRoleGrantAction
*actions
,
115 bool revoke_admin_option_only
,
116 DropBehavior behavior
);
117 static void InitGrantRoleOptions(GrantRoleOptions
*popt
);
120 /* Check if current user has createrole privileges */
122 have_createrole_privilege(void)
124 return has_createrole_privilege(GetUserId());
132 CreateRole(ParseState
*pstate
, CreateRoleStmt
*stmt
)
134 Relation pg_authid_rel
;
135 TupleDesc pg_authid_dsc
;
137 Datum new_record
[Natts_pg_authid
] = {0};
138 bool new_record_nulls
[Natts_pg_authid
] = {0};
139 Oid currentUserId
= GetUserId();
143 char *password
= NULL
; /* user password */
144 bool issuper
= false; /* Make the user a superuser? */
145 bool inherit
= true; /* Auto inherit privileges? */
146 bool createrole
= false; /* Can this user create roles? */
147 bool createdb
= false; /* Can the user create databases? */
148 bool canlogin
= false; /* Can this user login? */
149 bool isreplication
= false; /* Is this a replication role? */
150 bool bypassrls
= false; /* Is this a row security enabled role? */
151 int connlimit
= -1; /* maximum connections allowed */
152 List
*addroleto
= NIL
; /* roles to make this a member of */
153 List
*rolemembers
= NIL
; /* roles to be members of this role */
154 List
*adminmembers
= NIL
; /* roles to be admins of this role */
155 char *validUntil
= NULL
; /* time the login is valid until */
156 Datum validUntil_datum
; /* same, as timestamptz Datum */
157 bool validUntil_null
;
158 DefElem
*dpassword
= NULL
;
159 DefElem
*dissuper
= NULL
;
160 DefElem
*dinherit
= NULL
;
161 DefElem
*dcreaterole
= NULL
;
162 DefElem
*dcreatedb
= NULL
;
163 DefElem
*dcanlogin
= NULL
;
164 DefElem
*disreplication
= NULL
;
165 DefElem
*dconnlimit
= NULL
;
166 DefElem
*daddroleto
= NULL
;
167 DefElem
*drolemembers
= NULL
;
168 DefElem
*dadminmembers
= NULL
;
169 DefElem
*dvalidUntil
= NULL
;
170 DefElem
*dbypassRLS
= NULL
;
171 GrantRoleOptions popt
;
173 /* The defaults can vary depending on the original statement type */
174 switch (stmt
->stmt_type
)
180 /* may eventually want inherit to default to false here */
186 /* Extract options from the statement node tree */
187 foreach(option
, stmt
->options
)
189 DefElem
*defel
= (DefElem
*) lfirst(option
);
191 if (strcmp(defel
->defname
, "password") == 0)
194 errorConflictingDefElem(defel
, pstate
);
197 else if (strcmp(defel
->defname
, "sysid") == 0)
200 (errmsg("SYSID can no longer be specified")));
202 else if (strcmp(defel
->defname
, "superuser") == 0)
205 errorConflictingDefElem(defel
, pstate
);
208 else if (strcmp(defel
->defname
, "inherit") == 0)
211 errorConflictingDefElem(defel
, pstate
);
214 else if (strcmp(defel
->defname
, "createrole") == 0)
217 errorConflictingDefElem(defel
, pstate
);
220 else if (strcmp(defel
->defname
, "createdb") == 0)
223 errorConflictingDefElem(defel
, pstate
);
226 else if (strcmp(defel
->defname
, "canlogin") == 0)
229 errorConflictingDefElem(defel
, pstate
);
232 else if (strcmp(defel
->defname
, "isreplication") == 0)
235 errorConflictingDefElem(defel
, pstate
);
236 disreplication
= defel
;
238 else if (strcmp(defel
->defname
, "connectionlimit") == 0)
241 errorConflictingDefElem(defel
, pstate
);
244 else if (strcmp(defel
->defname
, "addroleto") == 0)
247 errorConflictingDefElem(defel
, pstate
);
250 else if (strcmp(defel
->defname
, "rolemembers") == 0)
253 errorConflictingDefElem(defel
, pstate
);
254 drolemembers
= defel
;
256 else if (strcmp(defel
->defname
, "adminmembers") == 0)
259 errorConflictingDefElem(defel
, pstate
);
260 dadminmembers
= defel
;
262 else if (strcmp(defel
->defname
, "validUntil") == 0)
265 errorConflictingDefElem(defel
, pstate
);
268 else if (strcmp(defel
->defname
, "bypassrls") == 0)
271 errorConflictingDefElem(defel
, pstate
);
275 elog(ERROR
, "option \"%s\" not recognized",
279 if (dpassword
&& dpassword
->arg
)
280 password
= strVal(dpassword
->arg
);
282 issuper
= boolVal(dissuper
->arg
);
284 inherit
= boolVal(dinherit
->arg
);
286 createrole
= boolVal(dcreaterole
->arg
);
288 createdb
= boolVal(dcreatedb
->arg
);
290 canlogin
= boolVal(dcanlogin
->arg
);
292 isreplication
= boolVal(disreplication
->arg
);
295 connlimit
= intVal(dconnlimit
->arg
);
298 (errcode(ERRCODE_INVALID_PARAMETER_VALUE
),
299 errmsg("invalid connection limit: %d", connlimit
)));
302 addroleto
= (List
*) daddroleto
->arg
;
304 rolemembers
= (List
*) drolemembers
->arg
;
306 adminmembers
= (List
*) dadminmembers
->arg
;
308 validUntil
= strVal(dvalidUntil
->arg
);
310 bypassrls
= boolVal(dbypassRLS
->arg
);
312 /* Check some permissions first */
313 if (!superuser_arg(currentUserId
))
315 if (!has_createrole_privilege(currentUserId
))
317 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
318 errmsg("permission denied to create role"),
319 errdetail("Only roles with the %s attribute may create roles.",
323 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
324 errmsg("permission denied to create role"),
325 errdetail("Only roles with the %s attribute may create roles with the %s attribute.",
326 "SUPERUSER", "SUPERUSER")));
327 if (createdb
&& !have_createdb_privilege())
329 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
330 errmsg("permission denied to create role"),
331 errdetail("Only roles with the %s attribute may create roles with the %s attribute.",
332 "CREATEDB", "CREATEDB")));
333 if (isreplication
&& !has_rolreplication(currentUserId
))
335 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
336 errmsg("permission denied to create role"),
337 errdetail("Only roles with the %s attribute may create roles with the %s attribute.",
338 "REPLICATION", "REPLICATION")));
339 if (bypassrls
&& !has_bypassrls_privilege(currentUserId
))
341 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
342 errmsg("permission denied to create role"),
343 errdetail("Only roles with the %s attribute may create roles with the %s attribute.",
344 "BYPASSRLS", "BYPASSRLS")));
348 * Check that the user is not trying to create a role in the reserved
351 if (IsReservedName(stmt
->role
))
353 (errcode(ERRCODE_RESERVED_NAME
),
354 errmsg("role name \"%s\" is reserved",
356 errdetail("Role names starting with \"pg_\" are reserved.")));
359 * If built with appropriate switch, whine when regression-testing
360 * conventions for role names are violated.
362 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
363 if (strncmp(stmt
->role
, "regress_", 8) != 0)
364 elog(WARNING
, "roles created by regression test cases should have names starting with \"regress_\"");
368 * Check the pg_authid relation to be certain the role doesn't already
371 pg_authid_rel
= table_open(AuthIdRelationId
, RowExclusiveLock
);
372 pg_authid_dsc
= RelationGetDescr(pg_authid_rel
);
374 if (OidIsValid(get_role_oid(stmt
->role
, true)))
376 (errcode(ERRCODE_DUPLICATE_OBJECT
),
377 errmsg("role \"%s\" already exists",
380 /* Convert validuntil to internal form */
383 validUntil_datum
= DirectFunctionCall3(timestamptz_in
,
384 CStringGetDatum(validUntil
),
385 ObjectIdGetDatum(InvalidOid
),
387 validUntil_null
= false;
391 validUntil_datum
= (Datum
) 0;
392 validUntil_null
= true;
396 * Call the password checking hook if there is one defined
398 if (check_password_hook
&& password
)
399 (*check_password_hook
) (stmt
->role
,
401 get_password_type(password
),
406 * Build a tuple to insert
408 new_record
[Anum_pg_authid_rolname
- 1] =
409 DirectFunctionCall1(namein
, CStringGetDatum(stmt
->role
));
410 new_record
[Anum_pg_authid_rolsuper
- 1] = BoolGetDatum(issuper
);
411 new_record
[Anum_pg_authid_rolinherit
- 1] = BoolGetDatum(inherit
);
412 new_record
[Anum_pg_authid_rolcreaterole
- 1] = BoolGetDatum(createrole
);
413 new_record
[Anum_pg_authid_rolcreatedb
- 1] = BoolGetDatum(createdb
);
414 new_record
[Anum_pg_authid_rolcanlogin
- 1] = BoolGetDatum(canlogin
);
415 new_record
[Anum_pg_authid_rolreplication
- 1] = BoolGetDatum(isreplication
);
416 new_record
[Anum_pg_authid_rolconnlimit
- 1] = Int32GetDatum(connlimit
);
421 const char *logdetail
= NULL
;
424 * Don't allow an empty password. Libpq treats an empty password the
425 * same as no password at all, and won't even try to authenticate. But
426 * other clients might, so allowing it would be confusing. By clearing
427 * the password when an empty string is specified, the account is
428 * consistently locked for all clients.
430 * Note that this only covers passwords stored in the database itself.
431 * There are also checks in the authentication code, to forbid an
432 * empty password from being used with authentication methods that
433 * fetch the password from an external system, like LDAP or PAM.
435 if (password
[0] == '\0' ||
436 plain_crypt_verify(stmt
->role
, password
, "", &logdetail
) == STATUS_OK
)
439 (errmsg("empty string is not a valid password, clearing password")));
440 new_record_nulls
[Anum_pg_authid_rolpassword
- 1] = true;
444 /* Encrypt the password to the requested format. */
445 shadow_pass
= encrypt_password(Password_encryption
, stmt
->role
,
447 new_record
[Anum_pg_authid_rolpassword
- 1] =
448 CStringGetTextDatum(shadow_pass
);
452 new_record_nulls
[Anum_pg_authid_rolpassword
- 1] = true;
454 new_record
[Anum_pg_authid_rolvaliduntil
- 1] = validUntil_datum
;
455 new_record_nulls
[Anum_pg_authid_rolvaliduntil
- 1] = validUntil_null
;
457 new_record
[Anum_pg_authid_rolbypassrls
- 1] = BoolGetDatum(bypassrls
);
460 * pg_largeobject_metadata contains pg_authid.oid's, so we use the
461 * binary-upgrade override.
465 if (!OidIsValid(binary_upgrade_next_pg_authid_oid
))
467 (errcode(ERRCODE_INVALID_PARAMETER_VALUE
),
468 errmsg("pg_authid OID value not set when in binary upgrade mode")));
470 roleid
= binary_upgrade_next_pg_authid_oid
;
471 binary_upgrade_next_pg_authid_oid
= InvalidOid
;
475 roleid
= GetNewOidWithIndex(pg_authid_rel
, AuthIdOidIndexId
,
479 new_record
[Anum_pg_authid_oid
- 1] = ObjectIdGetDatum(roleid
);
481 tuple
= heap_form_tuple(pg_authid_dsc
, new_record
, new_record_nulls
);
484 * Insert new record in the pg_authid table
486 CatalogTupleInsert(pg_authid_rel
, tuple
);
489 * Advance command counter so we can see new record; else tests in
490 * AddRoleMems may fail.
492 if (addroleto
|| adminmembers
|| rolemembers
)
493 CommandCounterIncrement();
496 InitGrantRoleOptions(&popt
);
499 * Add the new role to the specified existing roles.
503 RoleSpec
*thisrole
= makeNode(RoleSpec
);
504 List
*thisrole_list
= list_make1(thisrole
);
505 List
*thisrole_oidlist
= list_make1_oid(roleid
);
507 thisrole
->roletype
= ROLESPEC_CSTRING
;
508 thisrole
->rolename
= stmt
->role
;
509 thisrole
->location
= -1;
511 foreach(item
, addroleto
)
513 RoleSpec
*oldrole
= lfirst(item
);
514 HeapTuple oldroletup
= get_rolespec_tuple(oldrole
);
515 Form_pg_authid oldroleform
= (Form_pg_authid
) GETSTRUCT(oldroletup
);
516 Oid oldroleid
= oldroleform
->oid
;
517 char *oldrolename
= NameStr(oldroleform
->rolname
);
519 /* can only add this role to roles for which you have rights */
520 check_role_membership_authorization(currentUserId
, oldroleid
, true);
521 AddRoleMems(currentUserId
, oldrolename
, oldroleid
,
526 ReleaseSysCache(oldroletup
);
531 * If the current user isn't a superuser, make them an admin of the new
532 * role so that they can administer the new object they just created.
533 * Superusers will be able to do that anyway.
535 * The grantor of record for this implicit grant is the bootstrap
536 * superuser, which means that the CREATEROLE user cannot revoke the
537 * grant. They can however grant the created role back to themselves with
538 * different options, since they enjoy ADMIN OPTION on it.
542 RoleSpec
*current_role
= makeNode(RoleSpec
);
543 GrantRoleOptions poptself
;
545 List
*memberIds
= list_make1_oid(currentUserId
);
547 current_role
->roletype
= ROLESPEC_CURRENT_ROLE
;
548 current_role
->location
= -1;
549 memberSpecs
= list_make1(current_role
);
551 poptself
.specified
= GRANT_ROLE_SPECIFIED_ADMIN
552 | GRANT_ROLE_SPECIFIED_INHERIT
553 | GRANT_ROLE_SPECIFIED_SET
;
554 poptself
.admin
= true;
555 poptself
.inherit
= false;
556 poptself
.set
= false;
558 AddRoleMems(BOOTSTRAP_SUPERUSERID
, stmt
->role
, roleid
,
559 memberSpecs
, memberIds
,
560 BOOTSTRAP_SUPERUSERID
, &poptself
);
563 * We must make the implicit grant visible to the code below, else the
564 * additional grants will fail.
566 CommandCounterIncrement();
569 * Because of the implicit grant above, a CREATEROLE user who creates
570 * a role has the ability to grant that role back to themselves with
571 * the INHERIT or SET options, if they wish to inherit the role's
572 * privileges or be able to SET ROLE to it. The createrole_self_grant
573 * GUC can be used to make this happen automatically. This has no
574 * security implications since the same user is able to make the same
575 * grant using an explicit GRANT statement; it's just convenient.
577 if (createrole_self_grant_enabled
)
578 AddRoleMems(currentUserId
, stmt
->role
, roleid
,
579 memberSpecs
, memberIds
,
580 currentUserId
, &createrole_self_grant_options
);
584 * Add the specified members to this new role. adminmembers get the admin
585 * option, rolemembers don't.
587 * NB: No permissions check is required here. If you have enough rights to
588 * create a role, you can add any members you like.
590 AddRoleMems(currentUserId
, stmt
->role
, roleid
,
591 rolemembers
, roleSpecsToIds(rolemembers
),
593 popt
.specified
|= GRANT_ROLE_SPECIFIED_ADMIN
;
595 AddRoleMems(currentUserId
, stmt
->role
, roleid
,
596 adminmembers
, roleSpecsToIds(adminmembers
),
599 /* Post creation hook for new role */
600 InvokeObjectPostCreateHook(AuthIdRelationId
, roleid
, 0);
603 * Close pg_authid, but keep lock till commit.
605 table_close(pg_authid_rel
, NoLock
);
614 * Note: the rolemembers option accepted here is intended to support the
615 * backwards-compatible ALTER GROUP syntax. Although it will work to say
616 * "ALTER ROLE role ROLE rolenames", we don't document it.
619 AlterRole(ParseState
*pstate
, AlterRoleStmt
*stmt
)
621 Datum new_record
[Natts_pg_authid
] = {0};
622 bool new_record_nulls
[Natts_pg_authid
] = {0};
623 bool new_record_repl
[Natts_pg_authid
] = {0};
624 Relation pg_authid_rel
;
625 TupleDesc pg_authid_dsc
;
628 Form_pg_authid authform
;
631 char *password
= NULL
; /* user password */
632 int connlimit
= -1; /* maximum connections allowed */
633 char *validUntil
= NULL
; /* time the login is valid until */
634 Datum validUntil_datum
; /* same, as timestamptz Datum */
635 bool validUntil_null
;
636 DefElem
*dpassword
= NULL
;
637 DefElem
*dissuper
= NULL
;
638 DefElem
*dinherit
= NULL
;
639 DefElem
*dcreaterole
= NULL
;
640 DefElem
*dcreatedb
= NULL
;
641 DefElem
*dcanlogin
= NULL
;
642 DefElem
*disreplication
= NULL
;
643 DefElem
*dconnlimit
= NULL
;
644 DefElem
*drolemembers
= NULL
;
645 DefElem
*dvalidUntil
= NULL
;
646 DefElem
*dbypassRLS
= NULL
;
648 Oid currentUserId
= GetUserId();
649 GrantRoleOptions popt
;
651 check_rolespec_name(stmt
->role
,
652 _("Cannot alter reserved roles."));
654 /* Extract options from the statement node tree */
655 foreach(option
, stmt
->options
)
657 DefElem
*defel
= (DefElem
*) lfirst(option
);
659 if (strcmp(defel
->defname
, "password") == 0)
662 errorConflictingDefElem(defel
, pstate
);
665 else if (strcmp(defel
->defname
, "superuser") == 0)
668 errorConflictingDefElem(defel
, pstate
);
671 else if (strcmp(defel
->defname
, "inherit") == 0)
674 errorConflictingDefElem(defel
, pstate
);
677 else if (strcmp(defel
->defname
, "createrole") == 0)
680 errorConflictingDefElem(defel
, pstate
);
683 else if (strcmp(defel
->defname
, "createdb") == 0)
686 errorConflictingDefElem(defel
, pstate
);
689 else if (strcmp(defel
->defname
, "canlogin") == 0)
692 errorConflictingDefElem(defel
, pstate
);
695 else if (strcmp(defel
->defname
, "isreplication") == 0)
698 errorConflictingDefElem(defel
, pstate
);
699 disreplication
= defel
;
701 else if (strcmp(defel
->defname
, "connectionlimit") == 0)
704 errorConflictingDefElem(defel
, pstate
);
707 else if (strcmp(defel
->defname
, "rolemembers") == 0 &&
711 errorConflictingDefElem(defel
, pstate
);
712 drolemembers
= defel
;
714 else if (strcmp(defel
->defname
, "validUntil") == 0)
717 errorConflictingDefElem(defel
, pstate
);
720 else if (strcmp(defel
->defname
, "bypassrls") == 0)
723 errorConflictingDefElem(defel
, pstate
);
727 elog(ERROR
, "option \"%s\" not recognized",
731 if (dpassword
&& dpassword
->arg
)
732 password
= strVal(dpassword
->arg
);
735 connlimit
= intVal(dconnlimit
->arg
);
738 (errcode(ERRCODE_INVALID_PARAMETER_VALUE
),
739 errmsg("invalid connection limit: %d", connlimit
)));
742 validUntil
= strVal(dvalidUntil
->arg
);
745 * Scan the pg_authid relation to be certain the user exists.
747 pg_authid_rel
= table_open(AuthIdRelationId
, RowExclusiveLock
);
748 pg_authid_dsc
= RelationGetDescr(pg_authid_rel
);
750 tuple
= get_rolespec_tuple(stmt
->role
);
751 authform
= (Form_pg_authid
) GETSTRUCT(tuple
);
752 rolename
= pstrdup(NameStr(authform
->rolname
));
753 roleid
= authform
->oid
;
755 /* To mess with a superuser in any way you gotta be superuser. */
756 if (!superuser() && authform
->rolsuper
)
758 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
759 errmsg("permission denied to alter role"),
760 errdetail("Only roles with the %s attribute may alter roles with the %s attribute.",
761 "SUPERUSER", "SUPERUSER")));
762 if (!superuser() && dissuper
)
764 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
765 errmsg("permission denied to alter role"),
766 errdetail("Only roles with the %s attribute may change the %s attribute.",
767 "SUPERUSER", "SUPERUSER")));
770 * Most changes to a role require that you both have CREATEROLE privileges
771 * and also ADMIN OPTION on the role.
773 if (!have_createrole_privilege() ||
774 !is_admin_of_role(GetUserId(), roleid
))
776 /* things an unprivileged user certainly can't do */
777 if (dinherit
|| dcreaterole
|| dcreatedb
|| dcanlogin
|| dconnlimit
||
778 dvalidUntil
|| disreplication
|| dbypassRLS
)
780 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
781 errmsg("permission denied to alter role"),
782 errdetail("Only roles with the %s attribute and the %s option on role \"%s\" may alter this role.",
783 "CREATEROLE", "ADMIN", rolename
)));
785 /* an unprivileged user can change their own password */
786 if (dpassword
&& roleid
!= currentUserId
)
788 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
789 errmsg("permission denied to alter role"),
790 errdetail("To change another role's password, the current user must have the %s attribute and the %s option on the role.",
791 "CREATEROLE", "ADMIN")));
793 else if (!superuser())
796 * Even if you have both CREATEROLE and ADMIN OPTION on a role, you
797 * can only change the CREATEDB, REPLICATION, or BYPASSRLS attributes
798 * if they are set for your own role (or you are the superuser).
800 if (dcreatedb
&& !have_createdb_privilege())
802 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
803 errmsg("permission denied to alter role"),
804 errdetail("Only roles with the %s attribute may change the %s attribute.",
805 "CREATEDB", "CREATEDB")));
806 if (disreplication
&& !has_rolreplication(currentUserId
))
808 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
809 errmsg("permission denied to alter role"),
810 errdetail("Only roles with the %s attribute may change the %s attribute.",
811 "REPLICATION", "REPLICATION")));
812 if (dbypassRLS
&& !has_bypassrls_privilege(currentUserId
))
814 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
815 errmsg("permission denied to alter role"),
816 errdetail("Only roles with the %s attribute may change the %s attribute.",
817 "BYPASSRLS", "BYPASSRLS")));
820 /* To add or drop members, you need ADMIN OPTION. */
821 if (drolemembers
&& !is_admin_of_role(currentUserId
, roleid
))
823 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
824 errmsg("permission denied to alter role"),
825 errdetail("Only roles with the %s option on role \"%s\" may add or drop members.",
826 "ADMIN", rolename
)));
828 /* Convert validuntil to internal form */
831 validUntil_datum
= DirectFunctionCall3(timestamptz_in
,
832 CStringGetDatum(validUntil
),
833 ObjectIdGetDatum(InvalidOid
),
835 validUntil_null
= false;
839 /* fetch existing setting in case hook needs it */
840 validUntil_datum
= SysCacheGetAttr(AUTHNAME
, tuple
,
841 Anum_pg_authid_rolvaliduntil
,
846 * Call the password checking hook if there is one defined
848 if (check_password_hook
&& password
)
849 (*check_password_hook
) (rolename
,
851 get_password_type(password
),
856 * Build an updated tuple, perusing the information just obtained
860 * issuper/createrole/etc
864 bool should_be_super
= boolVal(dissuper
->arg
);
866 if (!should_be_super
&& roleid
== BOOTSTRAP_SUPERUSERID
)
868 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
869 errmsg("permission denied to alter role"),
870 errdetail("The bootstrap superuser must have the %s attribute.",
873 new_record
[Anum_pg_authid_rolsuper
- 1] = BoolGetDatum(should_be_super
);
874 new_record_repl
[Anum_pg_authid_rolsuper
- 1] = true;
879 new_record
[Anum_pg_authid_rolinherit
- 1] = BoolGetDatum(boolVal(dinherit
->arg
));
880 new_record_repl
[Anum_pg_authid_rolinherit
- 1] = true;
885 new_record
[Anum_pg_authid_rolcreaterole
- 1] = BoolGetDatum(boolVal(dcreaterole
->arg
));
886 new_record_repl
[Anum_pg_authid_rolcreaterole
- 1] = true;
891 new_record
[Anum_pg_authid_rolcreatedb
- 1] = BoolGetDatum(boolVal(dcreatedb
->arg
));
892 new_record_repl
[Anum_pg_authid_rolcreatedb
- 1] = true;
897 new_record
[Anum_pg_authid_rolcanlogin
- 1] = BoolGetDatum(boolVal(dcanlogin
->arg
));
898 new_record_repl
[Anum_pg_authid_rolcanlogin
- 1] = true;
903 new_record
[Anum_pg_authid_rolreplication
- 1] = BoolGetDatum(boolVal(disreplication
->arg
));
904 new_record_repl
[Anum_pg_authid_rolreplication
- 1] = true;
909 new_record
[Anum_pg_authid_rolconnlimit
- 1] = Int32GetDatum(connlimit
);
910 new_record_repl
[Anum_pg_authid_rolconnlimit
- 1] = true;
917 const char *logdetail
= NULL
;
919 /* Like in CREATE USER, don't allow an empty password. */
920 if (password
[0] == '\0' ||
921 plain_crypt_verify(rolename
, password
, "", &logdetail
) == STATUS_OK
)
924 (errmsg("empty string is not a valid password, clearing password")));
925 new_record_nulls
[Anum_pg_authid_rolpassword
- 1] = true;
929 /* Encrypt the password to the requested format. */
930 shadow_pass
= encrypt_password(Password_encryption
, rolename
,
932 new_record
[Anum_pg_authid_rolpassword
- 1] =
933 CStringGetTextDatum(shadow_pass
);
935 new_record_repl
[Anum_pg_authid_rolpassword
- 1] = true;
939 if (dpassword
&& dpassword
->arg
== NULL
)
941 new_record_repl
[Anum_pg_authid_rolpassword
- 1] = true;
942 new_record_nulls
[Anum_pg_authid_rolpassword
- 1] = true;
946 new_record
[Anum_pg_authid_rolvaliduntil
- 1] = validUntil_datum
;
947 new_record_nulls
[Anum_pg_authid_rolvaliduntil
- 1] = validUntil_null
;
948 new_record_repl
[Anum_pg_authid_rolvaliduntil
- 1] = true;
952 new_record
[Anum_pg_authid_rolbypassrls
- 1] = BoolGetDatum(boolVal(dbypassRLS
->arg
));
953 new_record_repl
[Anum_pg_authid_rolbypassrls
- 1] = true;
956 new_tuple
= heap_modify_tuple(tuple
, pg_authid_dsc
, new_record
,
957 new_record_nulls
, new_record_repl
);
958 CatalogTupleUpdate(pg_authid_rel
, &tuple
->t_self
, new_tuple
);
960 InvokeObjectPostAlterHook(AuthIdRelationId
, roleid
, 0);
962 ReleaseSysCache(tuple
);
963 heap_freetuple(new_tuple
);
965 InitGrantRoleOptions(&popt
);
968 * Advance command counter so we can see new record; else tests in
969 * AddRoleMems may fail.
973 List
*rolemembers
= (List
*) drolemembers
->arg
;
975 CommandCounterIncrement();
977 if (stmt
->action
== +1) /* add members to role */
978 AddRoleMems(currentUserId
, rolename
, roleid
,
979 rolemembers
, roleSpecsToIds(rolemembers
),
981 else if (stmt
->action
== -1) /* drop members from role */
982 DelRoleMems(currentUserId
, rolename
, roleid
,
983 rolemembers
, roleSpecsToIds(rolemembers
),
984 InvalidOid
, &popt
, DROP_RESTRICT
);
988 * Close pg_authid, but keep lock till commit.
990 table_close(pg_authid_rel
, NoLock
);
1000 AlterRoleSet(AlterRoleSetStmt
*stmt
)
1002 HeapTuple roletuple
;
1003 Form_pg_authid roleform
;
1004 Oid databaseid
= InvalidOid
;
1005 Oid roleid
= InvalidOid
;
1009 check_rolespec_name(stmt
->role
,
1010 _("Cannot alter reserved roles."));
1012 roletuple
= get_rolespec_tuple(stmt
->role
);
1013 roleform
= (Form_pg_authid
) GETSTRUCT(roletuple
);
1014 roleid
= roleform
->oid
;
1017 * Obtain a lock on the role and make sure it didn't go away in the
1020 shdepLockAndCheckObject(AuthIdRelationId
, roleid
);
1023 * To mess with a superuser you gotta be superuser; otherwise you need
1024 * CREATEROLE plus admin option on the target role; unless you're just
1025 * trying to change your own settings
1027 if (roleform
->rolsuper
)
1031 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
1032 errmsg("permission denied to alter role"),
1033 errdetail("Only roles with the %s attribute may alter roles with the %s attribute.",
1034 "SUPERUSER", "SUPERUSER")));
1038 if ((!have_createrole_privilege() ||
1039 !is_admin_of_role(GetUserId(), roleid
))
1040 && roleid
!= GetUserId())
1042 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
1043 errmsg("permission denied to alter role"),
1044 errdetail("Only roles with the %s attribute and the %s option on role \"%s\" may alter this role.",
1045 "CREATEROLE", "ADMIN", NameStr(roleform
->rolname
))));
1048 ReleaseSysCache(roletuple
);
1051 /* look up and lock the database, if specified */
1052 if (stmt
->database
!= NULL
)
1054 databaseid
= get_database_oid(stmt
->database
, false);
1055 shdepLockAndCheckObject(DatabaseRelationId
, databaseid
);
1060 * If no role is specified, then this is effectively the same as
1061 * ALTER DATABASE ... SET, so use the same permission check.
1063 if (!object_ownercheck(DatabaseRelationId
, databaseid
, GetUserId()))
1064 aclcheck_error(ACLCHECK_NOT_OWNER
, OBJECT_DATABASE
,
1069 if (!stmt
->role
&& !stmt
->database
)
1071 /* Must be superuser to alter settings globally. */
1074 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
1075 errmsg("permission denied to alter setting"),
1076 errdetail("Only roles with the %s attribute may alter settings globally.",
1080 AlterSetting(databaseid
, roleid
, stmt
->setstmt
);
1090 DropRole(DropRoleStmt
*stmt
)
1092 Relation pg_authid_rel
,
1093 pg_auth_members_rel
;
1095 List
*role_oids
= NIL
;
1097 if (!have_createrole_privilege())
1099 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
1100 errmsg("permission denied to drop role"),
1101 errdetail("Only roles with the %s attribute and the %s option on the target roles may drop roles.",
1102 "CREATEROLE", "ADMIN")));
1105 * Scan the pg_authid relation to find the Oid of the role(s) to be
1106 * deleted and perform preliminary permissions and sanity checks.
1108 pg_authid_rel
= table_open(AuthIdRelationId
, RowExclusiveLock
);
1109 pg_auth_members_rel
= table_open(AuthMemRelationId
, RowExclusiveLock
);
1111 foreach(item
, stmt
->roles
)
1113 RoleSpec
*rolspec
= lfirst(item
);
1117 Form_pg_authid roleform
;
1118 ScanKeyData scankey
;
1122 if (rolspec
->roletype
!= ROLESPEC_CSTRING
)
1124 (errcode(ERRCODE_INVALID_PARAMETER_VALUE
),
1125 errmsg("cannot use special role specifier in DROP ROLE")));
1126 role
= rolspec
->rolename
;
1128 tuple
= SearchSysCache1(AUTHNAME
, PointerGetDatum(role
));
1129 if (!HeapTupleIsValid(tuple
))
1131 if (!stmt
->missing_ok
)
1134 (errcode(ERRCODE_UNDEFINED_OBJECT
),
1135 errmsg("role \"%s\" does not exist", role
)));
1140 (errmsg("role \"%s\" does not exist, skipping",
1147 roleform
= (Form_pg_authid
) GETSTRUCT(tuple
);
1148 roleid
= roleform
->oid
;
1150 if (roleid
== GetUserId())
1152 (errcode(ERRCODE_OBJECT_IN_USE
),
1153 errmsg("current user cannot be dropped")));
1154 if (roleid
== GetOuterUserId())
1156 (errcode(ERRCODE_OBJECT_IN_USE
),
1157 errmsg("current user cannot be dropped")));
1158 if (roleid
== GetSessionUserId())
1160 (errcode(ERRCODE_OBJECT_IN_USE
),
1161 errmsg("session user cannot be dropped")));
1164 * For safety's sake, we allow createrole holders to drop ordinary
1165 * roles but not superuser roles, and only if they also have ADMIN
1168 if (roleform
->rolsuper
&& !superuser())
1170 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
1171 errmsg("permission denied to drop role"),
1172 errdetail("Only roles with the %s attribute may drop roles with the %s attribute.",
1173 "SUPERUSER", "SUPERUSER")));
1174 if (!is_admin_of_role(GetUserId(), roleid
))
1176 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
1177 errmsg("permission denied to drop role"),
1178 errdetail("Only roles with the %s attribute and the %s option on role \"%s\" may drop this role.",
1179 "CREATEROLE", "ADMIN", NameStr(roleform
->rolname
))));
1181 /* DROP hook for the role being removed */
1182 InvokeObjectDropHook(AuthIdRelationId
, roleid
, 0);
1184 /* Don't leak the syscache tuple */
1185 ReleaseSysCache(tuple
);
1188 * Lock the role, so nobody can add dependencies to her while we drop
1189 * her. We keep the lock until the end of transaction.
1191 LockSharedObject(AuthIdRelationId
, roleid
, 0, AccessExclusiveLock
);
1194 * If there is a pg_auth_members entry that has one of the roles to be
1195 * dropped as the roleid or member, it should be silently removed, but
1196 * if there is a pg_auth_members entry that has one of the roles to be
1197 * dropped as the grantor, the operation should fail.
1199 * It's possible, however, that a single pg_auth_members entry could
1200 * fall into multiple categories - e.g. the user could do "GRANT foo
1201 * TO bar GRANTED BY baz" and then "DROP ROLE baz, bar". We want such
1202 * an operation to succeed regardless of the order in which the
1203 * to-be-dropped roles are passed to DROP ROLE.
1205 * To make that work, we remove all pg_auth_members entries that can
1206 * be silently removed in this loop, and then below we'll make a
1207 * second pass over the list of roles to be removed and check for any
1208 * remaining dependencies.
1210 ScanKeyInit(&scankey
,
1211 Anum_pg_auth_members_roleid
,
1212 BTEqualStrategyNumber
, F_OIDEQ
,
1213 ObjectIdGetDatum(roleid
));
1215 sscan
= systable_beginscan(pg_auth_members_rel
, AuthMemRoleMemIndexId
,
1216 true, NULL
, 1, &scankey
);
1218 while (HeapTupleIsValid(tmp_tuple
= systable_getnext(sscan
)))
1220 Form_pg_auth_members authmem_form
;
1222 authmem_form
= (Form_pg_auth_members
) GETSTRUCT(tmp_tuple
);
1223 deleteSharedDependencyRecordsFor(AuthMemRelationId
,
1224 authmem_form
->oid
, 0);
1225 CatalogTupleDelete(pg_auth_members_rel
, &tmp_tuple
->t_self
);
1228 systable_endscan(sscan
);
1230 ScanKeyInit(&scankey
,
1231 Anum_pg_auth_members_member
,
1232 BTEqualStrategyNumber
, F_OIDEQ
,
1233 ObjectIdGetDatum(roleid
));
1235 sscan
= systable_beginscan(pg_auth_members_rel
, AuthMemMemRoleIndexId
,
1236 true, NULL
, 1, &scankey
);
1238 while (HeapTupleIsValid(tmp_tuple
= systable_getnext(sscan
)))
1240 Form_pg_auth_members authmem_form
;
1242 authmem_form
= (Form_pg_auth_members
) GETSTRUCT(tmp_tuple
);
1243 deleteSharedDependencyRecordsFor(AuthMemRelationId
,
1244 authmem_form
->oid
, 0);
1245 CatalogTupleDelete(pg_auth_members_rel
, &tmp_tuple
->t_self
);
1248 systable_endscan(sscan
);
1251 * Advance command counter so that later iterations of this loop will
1252 * see the changes already made. This is essential if, for example,
1253 * we are trying to drop both a role and one of its direct members ---
1254 * we'll get an error if we try to delete the linking pg_auth_members
1255 * tuple twice. (We do not need a CCI between the two delete loops
1256 * above, because it's not allowed for a role to directly contain
1259 CommandCounterIncrement();
1261 /* Looks tentatively OK, add it to the list if not there yet. */
1262 role_oids
= list_append_unique_oid(role_oids
, roleid
);
1266 * Second pass over the roles to be removed.
1268 foreach(item
, role_oids
)
1270 Oid roleid
= lfirst_oid(item
);
1272 Form_pg_authid roleform
;
1277 * Re-find the pg_authid tuple.
1279 * Since we've taken a lock on the role OID, it shouldn't be possible
1280 * for the tuple to have been deleted -- or for that matter updated --
1281 * unless the user is manually modifying the system catalogs.
1283 tuple
= SearchSysCache1(AUTHOID
, ObjectIdGetDatum(roleid
));
1284 if (!HeapTupleIsValid(tuple
))
1285 elog(ERROR
, "could not find tuple for role %u", roleid
);
1286 roleform
= (Form_pg_authid
) GETSTRUCT(tuple
);
1289 * Check for pg_shdepend entries depending on this role.
1291 * This needs to happen after we've completed removing any
1292 * pg_auth_members entries that can be removed silently, in order to
1293 * avoid spurious failures. See notes above for more details.
1295 if (checkSharedDependencies(AuthIdRelationId
, roleid
,
1296 &detail
, &detail_log
))
1298 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST
),
1299 errmsg("role \"%s\" cannot be dropped because some objects depend on it",
1300 NameStr(roleform
->rolname
)),
1301 errdetail_internal("%s", detail
),
1302 errdetail_log("%s", detail_log
)));
1305 * Remove the role from the pg_authid table
1307 CatalogTupleDelete(pg_authid_rel
, &tuple
->t_self
);
1309 ReleaseSysCache(tuple
);
1312 * Remove any comments or security labels on this role.
1314 DeleteSharedComments(roleid
, AuthIdRelationId
);
1315 DeleteSharedSecurityLabel(roleid
, AuthIdRelationId
);
1318 * Remove settings for this role.
1320 DropSetting(InvalidOid
, roleid
);
1324 * Now we can clean up; but keep locks until commit.
1326 table_close(pg_auth_members_rel
, NoLock
);
1327 table_close(pg_authid_rel
, NoLock
);
1334 RenameRole(const char *oldname
, const char *newname
)
1342 Datum repl_val
[Natts_pg_authid
];
1343 bool repl_null
[Natts_pg_authid
];
1344 bool repl_repl
[Natts_pg_authid
];
1347 ObjectAddress address
;
1348 Form_pg_authid authform
;
1350 rel
= table_open(AuthIdRelationId
, RowExclusiveLock
);
1351 dsc
= RelationGetDescr(rel
);
1353 oldtuple
= SearchSysCache1(AUTHNAME
, CStringGetDatum(oldname
));
1354 if (!HeapTupleIsValid(oldtuple
))
1356 (errcode(ERRCODE_UNDEFINED_OBJECT
),
1357 errmsg("role \"%s\" does not exist", oldname
)));
1360 * XXX Client applications probably store the session user somewhere, so
1361 * renaming it could cause confusion. On the other hand, there may not be
1362 * an actual problem besides a little confusion, so think about this and
1363 * decide. Same for SET ROLE ... we don't restrict renaming the current
1364 * effective userid, though.
1367 authform
= (Form_pg_authid
) GETSTRUCT(oldtuple
);
1368 roleid
= authform
->oid
;
1370 if (roleid
== GetSessionUserId())
1372 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
1373 errmsg("session user cannot be renamed")));
1374 if (roleid
== GetOuterUserId())
1376 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
1377 errmsg("current user cannot be renamed")));
1380 * Check that the user is not trying to rename a system role and not
1381 * trying to rename a role into the reserved "pg_" namespace.
1383 if (IsReservedName(NameStr(authform
->rolname
)))
1385 (errcode(ERRCODE_RESERVED_NAME
),
1386 errmsg("role name \"%s\" is reserved",
1387 NameStr(authform
->rolname
)),
1388 errdetail("Role names starting with \"pg_\" are reserved.")));
1390 if (IsReservedName(newname
))
1392 (errcode(ERRCODE_RESERVED_NAME
),
1393 errmsg("role name \"%s\" is reserved",
1395 errdetail("Role names starting with \"pg_\" are reserved.")));
1398 * If built with appropriate switch, whine when regression-testing
1399 * conventions for role names are violated.
1401 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
1402 if (strncmp(newname
, "regress_", 8) != 0)
1403 elog(WARNING
, "roles created by regression test cases should have names starting with \"regress_\"");
1406 /* make sure the new name doesn't exist */
1407 if (SearchSysCacheExists1(AUTHNAME
, CStringGetDatum(newname
)))
1409 (errcode(ERRCODE_DUPLICATE_OBJECT
),
1410 errmsg("role \"%s\" already exists", newname
)));
1413 * Only superusers can mess with superusers. Otherwise, a user with
1414 * CREATEROLE can rename a role for which they have ADMIN OPTION.
1416 if (authform
->rolsuper
)
1420 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
1421 errmsg("permission denied to rename role"),
1422 errdetail("Only roles with the %s attribute may rename roles with the %s attribute.",
1423 "SUPERUSER", "SUPERUSER")));
1427 if (!have_createrole_privilege() ||
1428 !is_admin_of_role(GetUserId(), roleid
))
1430 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
1431 errmsg("permission denied to rename role"),
1432 errdetail("Only roles with the %s attribute and the %s option on role \"%s\" may rename this role.",
1433 "CREATEROLE", "ADMIN", NameStr(authform
->rolname
))));
1436 /* OK, construct the modified tuple */
1437 for (i
= 0; i
< Natts_pg_authid
; i
++)
1438 repl_repl
[i
] = false;
1440 repl_repl
[Anum_pg_authid_rolname
- 1] = true;
1441 repl_val
[Anum_pg_authid_rolname
- 1] = DirectFunctionCall1(namein
,
1442 CStringGetDatum(newname
));
1443 repl_null
[Anum_pg_authid_rolname
- 1] = false;
1445 datum
= heap_getattr(oldtuple
, Anum_pg_authid_rolpassword
, dsc
, &isnull
);
1447 if (!isnull
&& get_password_type(TextDatumGetCString(datum
)) == PASSWORD_TYPE_MD5
)
1449 /* MD5 uses the username as salt, so just clear it on a rename */
1450 repl_repl
[Anum_pg_authid_rolpassword
- 1] = true;
1451 repl_null
[Anum_pg_authid_rolpassword
- 1] = true;
1454 (errmsg("MD5 password cleared because of role rename")));
1457 newtuple
= heap_modify_tuple(oldtuple
, dsc
, repl_val
, repl_null
, repl_repl
);
1458 CatalogTupleUpdate(rel
, &oldtuple
->t_self
, newtuple
);
1460 InvokeObjectPostAlterHook(AuthIdRelationId
, roleid
, 0);
1462 ObjectAddressSet(address
, AuthIdRelationId
, roleid
);
1464 ReleaseSysCache(oldtuple
);
1467 * Close pg_authid, but keep lock till commit.
1469 table_close(rel
, NoLock
);
1477 * Grant/Revoke roles to/from roles
1480 GrantRole(ParseState
*pstate
, GrantRoleStmt
*stmt
)
1482 Relation pg_authid_rel
;
1486 GrantRoleOptions popt
;
1487 Oid currentUserId
= GetUserId();
1489 /* Parse options list. */
1490 InitGrantRoleOptions(&popt
);
1491 foreach(item
, stmt
->opt
)
1493 DefElem
*opt
= (DefElem
*) lfirst(item
);
1494 char *optval
= defGetString(opt
);
1496 if (strcmp(opt
->defname
, "admin") == 0)
1498 popt
.specified
|= GRANT_ROLE_SPECIFIED_ADMIN
;
1500 if (parse_bool(optval
, &popt
.admin
))
1503 else if (strcmp(opt
->defname
, "inherit") == 0)
1505 popt
.specified
|= GRANT_ROLE_SPECIFIED_INHERIT
;
1506 if (parse_bool(optval
, &popt
.inherit
))
1509 else if (strcmp(opt
->defname
, "set") == 0)
1511 popt
.specified
|= GRANT_ROLE_SPECIFIED_SET
;
1512 if (parse_bool(optval
, &popt
.set
))
1517 errcode(ERRCODE_SYNTAX_ERROR
),
1518 errmsg("unrecognized role option \"%s\"", opt
->defname
),
1519 parser_errposition(pstate
, opt
->location
));
1522 (errcode(ERRCODE_INVALID_PARAMETER_VALUE
),
1523 errmsg("unrecognized value for role option \"%s\": \"%s\"",
1524 opt
->defname
, optval
),
1525 parser_errposition(pstate
, opt
->location
)));
1528 /* Lookup OID of grantor, if specified. */
1530 grantor
= get_rolespec_oid(stmt
->grantor
, false);
1532 grantor
= InvalidOid
;
1534 grantee_ids
= roleSpecsToIds(stmt
->grantee_roles
);
1536 /* AccessShareLock is enough since we aren't modifying pg_authid */
1537 pg_authid_rel
= table_open(AuthIdRelationId
, AccessShareLock
);
1540 * Step through all of the granted roles and add, update, or remove
1541 * entries in pg_auth_members as appropriate. If stmt->is_grant is true,
1542 * we are adding new grants or, if they already exist, updating options on
1543 * those grants. If stmt->is_grant is false, we are revoking grants or
1544 * removing options from them.
1546 foreach(item
, stmt
->granted_roles
)
1548 AccessPriv
*priv
= (AccessPriv
*) lfirst(item
);
1549 char *rolename
= priv
->priv_name
;
1552 /* Must reject priv(columns) and ALL PRIVILEGES(columns) */
1553 if (rolename
== NULL
|| priv
->cols
!= NIL
)
1555 (errcode(ERRCODE_INVALID_GRANT_OPERATION
),
1556 errmsg("column names cannot be included in GRANT/REVOKE ROLE")));
1558 roleid
= get_role_oid(rolename
, false);
1559 check_role_membership_authorization(currentUserId
,
1560 roleid
, stmt
->is_grant
);
1562 AddRoleMems(currentUserId
, rolename
, roleid
,
1563 stmt
->grantee_roles
, grantee_ids
,
1566 DelRoleMems(currentUserId
, rolename
, roleid
,
1567 stmt
->grantee_roles
, grantee_ids
,
1568 grantor
, &popt
, stmt
->behavior
);
1572 * Close pg_authid, but keep lock till commit.
1574 table_close(pg_authid_rel
, NoLock
);
1580 * Drop the objects owned by a given list of roles.
1583 DropOwnedObjects(DropOwnedStmt
*stmt
)
1585 List
*role_ids
= roleSpecsToIds(stmt
->roles
);
1588 /* Check privileges */
1589 foreach(cell
, role_ids
)
1591 Oid roleid
= lfirst_oid(cell
);
1593 if (!has_privs_of_role(GetUserId(), roleid
))
1595 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
1596 errmsg("permission denied to drop objects"),
1597 errdetail("Only roles with privileges of role \"%s\" may drop objects owned by it.",
1598 GetUserNameFromId(roleid
, false))));
1602 shdepDropOwned(role_ids
, stmt
->behavior
);
1606 * ReassignOwnedObjects
1608 * Give the objects owned by a given list of roles away to another user.
1611 ReassignOwnedObjects(ReassignOwnedStmt
*stmt
)
1613 List
*role_ids
= roleSpecsToIds(stmt
->roles
);
1617 /* Check privileges */
1618 foreach(cell
, role_ids
)
1620 Oid roleid
= lfirst_oid(cell
);
1622 if (!has_privs_of_role(GetUserId(), roleid
))
1624 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
1625 errmsg("permission denied to reassign objects"),
1626 errdetail("Only roles with privileges of role \"%s\" may reassign objects owned by it.",
1627 GetUserNameFromId(roleid
, false))));
1630 /* Must have privileges on the receiving side too */
1631 newrole
= get_rolespec_oid(stmt
->newrole
, false);
1633 if (!has_privs_of_role(GetUserId(), newrole
))
1635 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
1636 errmsg("permission denied to reassign objects"),
1637 errdetail("Only roles with privileges of role \"%s\" may reassign objects to it.",
1638 GetUserNameFromId(newrole
, false))));
1641 shdepReassignOwned(role_ids
, newrole
);
1647 * Given a list of RoleSpecs, generate a list of role OIDs in the same order.
1649 * ROLESPEC_PUBLIC is not allowed.
1652 roleSpecsToIds(List
*memberNames
)
1657 foreach(l
, memberNames
)
1659 RoleSpec
*rolespec
= lfirst_node(RoleSpec
, l
);
1662 roleid
= get_rolespec_oid(rolespec
, false);
1663 result
= lappend_oid(result
, roleid
);
1669 * AddRoleMems -- Add given members to the specified role
1671 * currentUserId: OID of role performing the operation
1672 * rolename: name of role to add to (used only for error messages)
1673 * roleid: OID of role to add to
1674 * memberSpecs: list of RoleSpec of roles to add (used only for error messages)
1675 * memberIds: OIDs of roles to add
1676 * grantorId: OID that should be recorded as having granted the membership
1677 * (InvalidOid if not set explicitly)
1678 * popt: information about grant options
1681 AddRoleMems(Oid currentUserId
, const char *rolename
, Oid roleid
,
1682 List
*memberSpecs
, List
*memberIds
,
1683 Oid grantorId
, GrantRoleOptions
*popt
)
1685 Relation pg_authmem_rel
;
1686 TupleDesc pg_authmem_dsc
;
1690 Assert(list_length(memberSpecs
) == list_length(memberIds
));
1692 /* Validate grantor (and resolve implicit grantor if not specified). */
1693 grantorId
= check_role_grantor(currentUserId
, roleid
, grantorId
, true);
1695 pg_authmem_rel
= table_open(AuthMemRelationId
, RowExclusiveLock
);
1696 pg_authmem_dsc
= RelationGetDescr(pg_authmem_rel
);
1699 * Only allow changes to this role by one backend at a time, so that we
1700 * can check integrity constraints like the lack of circular ADMIN OPTION
1701 * grants without fear of race conditions.
1703 LockSharedObject(AuthIdRelationId
, roleid
, 0,
1704 ShareUpdateExclusiveLock
);
1706 /* Preliminary sanity checks. */
1707 forboth(specitem
, memberSpecs
, iditem
, memberIds
)
1709 RoleSpec
*memberRole
= lfirst_node(RoleSpec
, specitem
);
1710 Oid memberid
= lfirst_oid(iditem
);
1713 * pg_database_owner is never a role member. Lifting this restriction
1714 * would require a policy decision about membership loops. One could
1715 * prevent loops, which would include making "ALTER DATABASE x OWNER
1716 * TO proposed_datdba" fail if is_member_of_role(pg_database_owner,
1717 * proposed_datdba). Hence, gaining a membership could reduce what a
1718 * role could do. Alternately, one could allow these memberships to
1719 * complete loops. A role could then have actual WITH ADMIN OPTION on
1720 * itself, prompting a decision about is_admin_of_role() treatment of
1723 * Lifting this restriction also has policy implications for ownership
1724 * of shared objects (databases and tablespaces). We allow such
1725 * ownership, but we might find cause to ban it in the future.
1726 * Designing such a ban would more troublesome if the design had to
1727 * address pg_database_owner being a member of role FOO that owns a
1728 * shared object. (The effect of such ownership is that any owner of
1729 * another database can act as the owner of affected shared objects.)
1731 if (memberid
== ROLE_PG_DATABASE_OWNER
)
1733 errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
1734 errmsg("role \"%s\" cannot be a member of any role",
1735 get_rolespec_name(memberRole
)));
1738 * Refuse creation of membership loops, including the trivial case
1739 * where a role is made a member of itself. We do this by checking to
1740 * see if the target role is already a member of the proposed member
1741 * role. We have to ignore possible superuserness, however, else we
1742 * could never grant membership in a superuser-privileged role.
1744 if (is_member_of_role_nosuper(roleid
, memberid
))
1746 (errcode(ERRCODE_INVALID_GRANT_OPERATION
),
1747 errmsg("role \"%s\" is a member of role \"%s\"",
1748 rolename
, get_rolespec_name(memberRole
))));
1752 * Disallow attempts to grant ADMIN OPTION back to a user who granted it
1753 * to you, similar to what check_circularity does for ACLs. We want the
1754 * chains of grants to remain acyclic, so that it's always possible to use
1755 * REVOKE .. CASCADE to clean up all grants that depend on the one being
1758 * NB: This check might look redundant with the check for membership loops
1759 * above, but it isn't. That's checking for role-member loop (e.g. A is a
1760 * member of B and B is a member of A) while this is checking for a
1761 * member-grantor loop (e.g. A gave ADMIN OPTION on X to B and now B, who
1762 * has no other source of ADMIN OPTION on X, tries to give ADMIN OPTION on
1765 if (popt
->admin
&& grantorId
!= BOOTSTRAP_SUPERUSERID
)
1768 RevokeRoleGrantAction
*actions
;
1771 /* Get the list of members for this role. */
1772 memlist
= SearchSysCacheList1(AUTHMEMROLEMEM
,
1773 ObjectIdGetDatum(roleid
));
1776 * Figure out what would happen if we removed all existing grants to
1777 * every role to which we've been asked to make a new grant.
1779 actions
= initialize_revoke_actions(memlist
);
1780 foreach(iditem
, memberIds
)
1782 Oid memberid
= lfirst_oid(iditem
);
1784 if (memberid
== BOOTSTRAP_SUPERUSERID
)
1786 (errcode(ERRCODE_INVALID_GRANT_OPERATION
),
1787 errmsg("%s option cannot be granted back to your own grantor",
1789 plan_member_revoke(memlist
, actions
, memberid
);
1793 * If the result would be that the grantor role would no longer have
1794 * the ability to perform the grant, then the proposed grant would
1795 * create a circularity.
1797 for (i
= 0; i
< memlist
->n_members
; ++i
)
1799 HeapTuple authmem_tuple
;
1800 Form_pg_auth_members authmem_form
;
1802 authmem_tuple
= &memlist
->members
[i
]->tuple
;
1803 authmem_form
= (Form_pg_auth_members
) GETSTRUCT(authmem_tuple
);
1805 if (actions
[i
] == RRG_NOOP
&&
1806 authmem_form
->member
== grantorId
&&
1807 authmem_form
->admin_option
)
1810 if (i
>= memlist
->n_members
)
1812 (errcode(ERRCODE_INVALID_GRANT_OPERATION
),
1813 errmsg("%s option cannot be granted back to your own grantor",
1816 ReleaseSysCacheList(memlist
);
1819 /* Now perform the catalog updates. */
1820 forboth(specitem
, memberSpecs
, iditem
, memberIds
)
1822 RoleSpec
*memberRole
= lfirst_node(RoleSpec
, specitem
);
1823 Oid memberid
= lfirst_oid(iditem
);
1824 HeapTuple authmem_tuple
;
1826 Datum new_record
[Natts_pg_auth_members
] = {0};
1827 bool new_record_nulls
[Natts_pg_auth_members
] = {0};
1828 bool new_record_repl
[Natts_pg_auth_members
] = {0};
1830 /* Common initialization for possible insert or update */
1831 new_record
[Anum_pg_auth_members_roleid
- 1] =
1832 ObjectIdGetDatum(roleid
);
1833 new_record
[Anum_pg_auth_members_member
- 1] =
1834 ObjectIdGetDatum(memberid
);
1835 new_record
[Anum_pg_auth_members_grantor
- 1] =
1836 ObjectIdGetDatum(grantorId
);
1838 /* Find any existing tuple */
1839 authmem_tuple
= SearchSysCache3(AUTHMEMROLEMEM
,
1840 ObjectIdGetDatum(roleid
),
1841 ObjectIdGetDatum(memberid
),
1842 ObjectIdGetDatum(grantorId
));
1845 * If we found a tuple, update it with new option values, unless there
1846 * are no changes, in which case issue a WARNING.
1848 * If we didn't find a tuple, just insert one.
1850 if (HeapTupleIsValid(authmem_tuple
))
1852 Form_pg_auth_members authmem_form
;
1853 bool at_least_one_change
= false;
1855 authmem_form
= (Form_pg_auth_members
) GETSTRUCT(authmem_tuple
);
1857 if ((popt
->specified
& GRANT_ROLE_SPECIFIED_ADMIN
) != 0
1858 && authmem_form
->admin_option
!= popt
->admin
)
1860 new_record
[Anum_pg_auth_members_admin_option
- 1] =
1861 BoolGetDatum(popt
->admin
);
1862 new_record_repl
[Anum_pg_auth_members_admin_option
- 1] =
1864 at_least_one_change
= true;
1867 if ((popt
->specified
& GRANT_ROLE_SPECIFIED_INHERIT
) != 0
1868 && authmem_form
->inherit_option
!= popt
->inherit
)
1870 new_record
[Anum_pg_auth_members_inherit_option
- 1] =
1871 BoolGetDatum(popt
->inherit
);
1872 new_record_repl
[Anum_pg_auth_members_inherit_option
- 1] =
1874 at_least_one_change
= true;
1877 if ((popt
->specified
& GRANT_ROLE_SPECIFIED_SET
) != 0
1878 && authmem_form
->set_option
!= popt
->set
)
1880 new_record
[Anum_pg_auth_members_set_option
- 1] =
1881 BoolGetDatum(popt
->set
);
1882 new_record_repl
[Anum_pg_auth_members_set_option
- 1] =
1884 at_least_one_change
= true;
1887 if (!at_least_one_change
)
1890 (errmsg("role \"%s\" has already been granted membership in role \"%s\" by role \"%s\"",
1891 get_rolespec_name(memberRole
), rolename
,
1892 GetUserNameFromId(grantorId
, false))));
1893 ReleaseSysCache(authmem_tuple
);
1897 tuple
= heap_modify_tuple(authmem_tuple
, pg_authmem_dsc
,
1899 new_record_nulls
, new_record_repl
);
1900 CatalogTupleUpdate(pg_authmem_rel
, &tuple
->t_self
, tuple
);
1902 ReleaseSysCache(authmem_tuple
);
1907 Oid
*newmembers
= palloc(sizeof(Oid
));
1910 * The values for these options can be taken directly from 'popt'.
1911 * Either they were specified, or the defaults as set by
1912 * InitGrantRoleOptions are correct.
1914 new_record
[Anum_pg_auth_members_admin_option
- 1] =
1915 BoolGetDatum(popt
->admin
);
1916 new_record
[Anum_pg_auth_members_set_option
- 1] =
1917 BoolGetDatum(popt
->set
);
1920 * If the user specified a value for the inherit option, use
1921 * whatever was specified. Otherwise, set the default value based
1922 * on the role-level property.
1924 if ((popt
->specified
& GRANT_ROLE_SPECIFIED_INHERIT
) != 0)
1925 new_record
[Anum_pg_auth_members_inherit_option
- 1] =
1930 Form_pg_authid mrform
;
1932 mrtup
= SearchSysCache1(AUTHOID
, ObjectIdGetDatum(memberid
));
1933 if (!HeapTupleIsValid(mrtup
))
1934 elog(ERROR
, "cache lookup failed for role %u", memberid
);
1935 mrform
= (Form_pg_authid
) GETSTRUCT(mrtup
);
1936 new_record
[Anum_pg_auth_members_inherit_option
- 1] =
1938 ReleaseSysCache(mrtup
);
1941 /* get an OID for the new row and insert it */
1942 objectId
= GetNewOidWithIndex(pg_authmem_rel
, AuthMemOidIndexId
,
1943 Anum_pg_auth_members_oid
);
1944 new_record
[Anum_pg_auth_members_oid
- 1] = objectId
;
1945 tuple
= heap_form_tuple(pg_authmem_dsc
,
1946 new_record
, new_record_nulls
);
1947 CatalogTupleInsert(pg_authmem_rel
, tuple
);
1949 /* updateAclDependencies wants to pfree array inputs */
1950 newmembers
[0] = grantorId
;
1951 updateAclDependencies(AuthMemRelationId
, objectId
,
1957 /* CCI after each change, in case there are duplicates in list */
1958 CommandCounterIncrement();
1962 * Close pg_authmem, but keep lock till commit.
1964 table_close(pg_authmem_rel
, NoLock
);
1968 * DelRoleMems -- Remove given members from the specified role
1970 * rolename: name of role to del from (used only for error messages)
1971 * roleid: OID of role to del from
1972 * memberSpecs: list of RoleSpec of roles to del (used only for error messages)
1973 * memberIds: OIDs of roles to del
1974 * grantorId: who is revoking the membership
1975 * popt: information about grant options
1976 * behavior: RESTRICT or CASCADE behavior for recursive removal
1979 DelRoleMems(Oid currentUserId
, const char *rolename
, Oid roleid
,
1980 List
*memberSpecs
, List
*memberIds
,
1981 Oid grantorId
, GrantRoleOptions
*popt
, DropBehavior behavior
)
1983 Relation pg_authmem_rel
;
1984 TupleDesc pg_authmem_dsc
;
1988 RevokeRoleGrantAction
*actions
;
1991 Assert(list_length(memberSpecs
) == list_length(memberIds
));
1993 /* Validate grantor (and resolve implicit grantor if not specified). */
1994 grantorId
= check_role_grantor(currentUserId
, roleid
, grantorId
, false);
1996 pg_authmem_rel
= table_open(AuthMemRelationId
, RowExclusiveLock
);
1997 pg_authmem_dsc
= RelationGetDescr(pg_authmem_rel
);
2000 * Only allow changes to this role by one backend at a time, so that we
2001 * can check for things like dependent privileges without fear of race
2004 LockSharedObject(AuthIdRelationId
, roleid
, 0,
2005 ShareUpdateExclusiveLock
);
2007 memlist
= SearchSysCacheList1(AUTHMEMROLEMEM
, ObjectIdGetDatum(roleid
));
2008 actions
= initialize_revoke_actions(memlist
);
2011 * We may need to recurse to dependent privileges if DROP_CASCADE was
2012 * specified, or refuse to perform the operation if dependent privileges
2013 * exist and DROP_RESTRICT was specified. plan_single_revoke() will figure
2014 * out what to do with each catalog tuple.
2016 forboth(specitem
, memberSpecs
, iditem
, memberIds
)
2018 RoleSpec
*memberRole
= lfirst(specitem
);
2019 Oid memberid
= lfirst_oid(iditem
);
2021 if (!plan_single_revoke(memlist
, actions
, memberid
, grantorId
,
2025 (errmsg("role \"%s\" has not been granted membership in role \"%s\" by role \"%s\"",
2026 get_rolespec_name(memberRole
), rolename
,
2027 GetUserNameFromId(grantorId
, false))));
2033 * We now know what to do with each catalog tuple: it should either be
2034 * left alone, deleted, or just have the admin_option flag cleared.
2035 * Perform the appropriate action in each case.
2037 for (i
= 0; i
< memlist
->n_members
; ++i
)
2039 HeapTuple authmem_tuple
;
2040 Form_pg_auth_members authmem_form
;
2042 if (actions
[i
] == RRG_NOOP
)
2045 authmem_tuple
= &memlist
->members
[i
]->tuple
;
2046 authmem_form
= (Form_pg_auth_members
) GETSTRUCT(authmem_tuple
);
2048 if (actions
[i
] == RRG_DELETE_GRANT
)
2051 * Remove the entry altogether, after first removing its
2054 deleteSharedDependencyRecordsFor(AuthMemRelationId
,
2055 authmem_form
->oid
, 0);
2056 CatalogTupleDelete(pg_authmem_rel
, &authmem_tuple
->t_self
);
2060 /* Just turn off the specified option */
2062 Datum new_record
[Natts_pg_auth_members
] = {0};
2063 bool new_record_nulls
[Natts_pg_auth_members
] = {0};
2064 bool new_record_repl
[Natts_pg_auth_members
] = {0};
2066 /* Build a tuple to update with */
2067 if (actions
[i
] == RRG_REMOVE_ADMIN_OPTION
)
2069 new_record
[Anum_pg_auth_members_admin_option
- 1] =
2070 BoolGetDatum(false);
2071 new_record_repl
[Anum_pg_auth_members_admin_option
- 1] =
2074 else if (actions
[i
] == RRG_REMOVE_INHERIT_OPTION
)
2076 new_record
[Anum_pg_auth_members_inherit_option
- 1] =
2077 BoolGetDatum(false);
2078 new_record_repl
[Anum_pg_auth_members_inherit_option
- 1] =
2081 else if (actions
[i
] == RRG_REMOVE_SET_OPTION
)
2083 new_record
[Anum_pg_auth_members_set_option
- 1] =
2084 BoolGetDatum(false);
2085 new_record_repl
[Anum_pg_auth_members_set_option
- 1] =
2089 elog(ERROR
, "unknown role revoke action");
2091 tuple
= heap_modify_tuple(authmem_tuple
, pg_authmem_dsc
,
2093 new_record_nulls
, new_record_repl
);
2094 CatalogTupleUpdate(pg_authmem_rel
, &tuple
->t_self
, tuple
);
2098 ReleaseSysCacheList(memlist
);
2101 * Close pg_authmem, but keep lock till commit.
2103 table_close(pg_authmem_rel
, NoLock
);
2107 * Check that currentUserId has permission to modify the membership list for
2108 * roleid. Throw an error if not.
2111 check_role_membership_authorization(Oid currentUserId
, Oid roleid
,
2115 * The charter of pg_database_owner is to have exactly one, implicit,
2116 * situation-dependent member. There's no technical need for this
2117 * restriction. (One could lift it and take the further step of making
2118 * object_ownercheck(DatabaseRelationId, ...) equivalent to
2119 * has_privs_of_role(roleid, ROLE_PG_DATABASE_OWNER), in which case
2120 * explicit, situation-independent members could act as the owner of any
2123 if (is_grant
&& roleid
== ROLE_PG_DATABASE_OWNER
)
2125 errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
2126 errmsg("role \"%s\" cannot have explicit members",
2127 GetUserNameFromId(roleid
, false)));
2129 /* To mess with a superuser role, you gotta be superuser. */
2130 if (superuser_arg(roleid
))
2132 if (!superuser_arg(currentUserId
))
2136 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
2137 errmsg("permission denied to grant role \"%s\"",
2138 GetUserNameFromId(roleid
, false)),
2139 errdetail("Only roles with the %s attribute may grant roles with the %s attribute.",
2140 "SUPERUSER", "SUPERUSER")));
2143 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
2144 errmsg("permission denied to revoke role \"%s\"",
2145 GetUserNameFromId(roleid
, false)),
2146 errdetail("Only roles with the %s attribute may revoke roles with the %s attribute.",
2147 "SUPERUSER", "SUPERUSER")));
2153 * Otherwise, must have admin option on the role to be changed.
2155 if (!is_admin_of_role(currentUserId
, roleid
))
2159 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
2160 errmsg("permission denied to grant role \"%s\"",
2161 GetUserNameFromId(roleid
, false)),
2162 errdetail("Only roles with the %s option on role \"%s\" may grant this role.",
2163 "ADMIN", GetUserNameFromId(roleid
, false))));
2166 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
2167 errmsg("permission denied to revoke role \"%s\"",
2168 GetUserNameFromId(roleid
, false)),
2169 errdetail("Only roles with the %s option on role \"%s\" may revoke this role.",
2170 "ADMIN", GetUserNameFromId(roleid
, false))));
2176 * Sanity-check, or infer, the grantor for a GRANT or REVOKE statement
2179 * The grantor must always be either a role with ADMIN OPTION on the role in
2180 * which membership is being granted, or the bootstrap superuser. This is
2181 * similar to the restriction enforced by select_best_grantor, except that
2182 * roles don't have owners, so we regard the bootstrap superuser as the
2185 * If the grantor was not explicitly specified by the user, grantorId should
2186 * be passed as InvalidOid, and this function will infer the user to be
2187 * recorded as the grantor. In many cases, this will be the current user, but
2188 * things get more complicated when the current user doesn't possess ADMIN
2189 * OPTION on the role but rather relies on having SUPERUSER privileges, or
2190 * on inheriting the privileges of a role which does have ADMIN OPTION. See
2191 * below for details.
2193 * If the grantor was specified by the user, then it must be a user that
2194 * can legally be recorded as the grantor, as per the rule stated above.
2195 * This is an integrity constraint, not a permissions check, and thus even
2196 * superusers are subject to this restriction. However, there is also a
2197 * permissions check: to specify a role as the grantor, the current user
2198 * must possess the privileges of that role. Superusers will always pass
2199 * this check, but for non-superusers it may lead to an error.
2201 * The return value is the OID to be regarded as the grantor when executing
2205 check_role_grantor(Oid currentUserId
, Oid roleid
, Oid grantorId
, bool is_grant
)
2207 /* If the grantor ID was not specified, pick one to use. */
2208 if (!OidIsValid(grantorId
))
2211 * Grants where the grantor is recorded as the bootstrap superuser do
2212 * not depend on any other existing grants, so always default to this
2213 * interpretation when possible.
2215 if (superuser_arg(currentUserId
))
2216 return BOOTSTRAP_SUPERUSERID
;
2219 * Otherwise, the grantor must either have ADMIN OPTION on the role or
2220 * inherit the privileges of a role which does. In the former case,
2221 * record the grantor as the current user; in the latter, pick one of
2222 * the roles that is "most directly" inherited by the current role
2223 * (i.e. fewest "hops").
2225 * (We shouldn't fail to find a best grantor, because we've already
2226 * established that the current user has permission to perform the
2229 grantorId
= select_best_admin(currentUserId
, roleid
);
2230 if (!OidIsValid(grantorId
))
2231 elog(ERROR
, "no possible grantors");
2236 * If an explicit grantor is specified, it must be a role whose privileges
2237 * the current user possesses.
2239 * It should also be a role that has ADMIN OPTION on the target role, but
2240 * we check this condition only in case of GRANT. For REVOKE, no matching
2241 * grant should exist anyway, but if it somehow does, let the user get rid
2246 if (!has_privs_of_role(currentUserId
, grantorId
))
2248 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
2249 errmsg("permission denied to grant privileges as role \"%s\"",
2250 GetUserNameFromId(grantorId
, false)),
2251 errdetail("Only roles with privileges of role \"%s\" may grant privileges as this role.",
2252 GetUserNameFromId(grantorId
, false))));
2254 if (grantorId
!= BOOTSTRAP_SUPERUSERID
&&
2255 select_best_admin(grantorId
, roleid
) != grantorId
)
2257 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
2258 errmsg("permission denied to grant privileges as role \"%s\"",
2259 GetUserNameFromId(grantorId
, false)),
2260 errdetail("The grantor must have the %s option on role \"%s\".",
2261 "ADMIN", GetUserNameFromId(roleid
, false))));
2265 if (!has_privs_of_role(currentUserId
, grantorId
))
2267 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE
),
2268 errmsg("permission denied to revoke privileges granted by role \"%s\"",
2269 GetUserNameFromId(grantorId
, false)),
2270 errdetail("Only roles with privileges of role \"%s\" may revoke privileges granted by this role.",
2271 GetUserNameFromId(grantorId
, false))));
2275 * If a grantor was specified explicitly, always attribute the grant to
2276 * that role (unless we error out above).
2282 * Initialize an array of RevokeRoleGrantAction objects.
2284 * 'memlist' should be a list of all grants for the target role.
2286 * This constructs an array indicating that no actions are to be performed;
2287 * that is, every element is initially RRG_NOOP.
2289 static RevokeRoleGrantAction
*
2290 initialize_revoke_actions(CatCList
*memlist
)
2292 RevokeRoleGrantAction
*result
;
2295 if (memlist
->n_members
== 0)
2298 result
= palloc(sizeof(RevokeRoleGrantAction
) * memlist
->n_members
);
2299 for (i
= 0; i
< memlist
->n_members
; i
++)
2300 result
[i
] = RRG_NOOP
;
2305 * Figure out what we would need to do in order to revoke a grant, or just the
2306 * admin option on a grant, given that there might be dependent privileges.
2308 * 'memlist' should be a list of all grants for the target role.
2310 * Whatever actions prove to be necessary will be signalled by updating
2313 * If behavior is DROP_RESTRICT, an error will occur if there are dependent
2314 * role membership grants; if DROP_CASCADE, those grants will be scheduled
2317 * The return value is true if the matching grant was found in the list,
2321 plan_single_revoke(CatCList
*memlist
, RevokeRoleGrantAction
*actions
,
2322 Oid member
, Oid grantor
, GrantRoleOptions
*popt
,
2323 DropBehavior behavior
)
2328 * If popt.specified == 0, we're revoking the grant entirely; otherwise,
2329 * we expect just one bit to be set, and we're revoking the corresponding
2330 * option. As of this writing, there's no syntax that would allow for an
2331 * attempt to revoke multiple options at once, and the logic below
2332 * wouldn't work properly if such syntax were added, so assert that our
2333 * caller isn't trying to do that.
2335 Assert(pg_popcount32(popt
->specified
) <= 1);
2337 for (i
= 0; i
< memlist
->n_members
; ++i
)
2339 HeapTuple authmem_tuple
;
2340 Form_pg_auth_members authmem_form
;
2342 authmem_tuple
= &memlist
->members
[i
]->tuple
;
2343 authmem_form
= (Form_pg_auth_members
) GETSTRUCT(authmem_tuple
);
2345 if (authmem_form
->member
== member
&&
2346 authmem_form
->grantor
== grantor
)
2348 if ((popt
->specified
& GRANT_ROLE_SPECIFIED_INHERIT
) != 0)
2351 * Revoking the INHERIT option doesn't change anything for
2352 * dependent privileges, so we don't need to recurse.
2354 actions
[i
] = RRG_REMOVE_INHERIT_OPTION
;
2356 else if ((popt
->specified
& GRANT_ROLE_SPECIFIED_SET
) != 0)
2358 /* Here too, no need to recurse. */
2359 actions
[i
] = RRG_REMOVE_SET_OPTION
;
2363 bool revoke_admin_option_only
;
2366 * Revoking the grant entirely, or ADMIN option on a grant,
2367 * implicates dependent privileges, so we may need to recurse.
2369 revoke_admin_option_only
=
2370 (popt
->specified
& GRANT_ROLE_SPECIFIED_ADMIN
) != 0;
2371 plan_recursive_revoke(memlist
, actions
, i
,
2372 revoke_admin_option_only
, behavior
);
2382 * Figure out what we would need to do in order to revoke all grants to
2383 * a given member, given that there might be dependent privileges.
2385 * 'memlist' should be a list of all grants for the target role.
2387 * Whatever actions prove to be necessary will be signalled by updating
2391 plan_member_revoke(CatCList
*memlist
, RevokeRoleGrantAction
*actions
,
2396 for (i
= 0; i
< memlist
->n_members
; ++i
)
2398 HeapTuple authmem_tuple
;
2399 Form_pg_auth_members authmem_form
;
2401 authmem_tuple
= &memlist
->members
[i
]->tuple
;
2402 authmem_form
= (Form_pg_auth_members
) GETSTRUCT(authmem_tuple
);
2404 if (authmem_form
->member
== member
)
2405 plan_recursive_revoke(memlist
, actions
, i
, false, DROP_CASCADE
);
2410 * Workhorse for figuring out recursive revocation of role grants.
2412 * This is similar to what recursive_revoke() does for ACLs.
2415 plan_recursive_revoke(CatCList
*memlist
, RevokeRoleGrantAction
*actions
,
2417 bool revoke_admin_option_only
, DropBehavior behavior
)
2419 bool would_still_have_admin_option
= false;
2420 HeapTuple authmem_tuple
;
2421 Form_pg_auth_members authmem_form
;
2424 /* If it's already been done, we can just return. */
2425 if (actions
[index
] == RRG_DELETE_GRANT
)
2427 if (actions
[index
] == RRG_REMOVE_ADMIN_OPTION
&&
2428 revoke_admin_option_only
)
2431 /* Locate tuple data. */
2432 authmem_tuple
= &memlist
->members
[index
]->tuple
;
2433 authmem_form
= (Form_pg_auth_members
) GETSTRUCT(authmem_tuple
);
2436 * If the existing tuple does not have admin_option set, then we do not
2437 * need to recurse. If we're just supposed to clear that bit we don't need
2438 * to do anything at all; if we're supposed to remove the grant, we need
2439 * to do something, but only to the tuple, and not any others.
2441 if (!revoke_admin_option_only
)
2443 actions
[index
] = RRG_DELETE_GRANT
;
2444 if (!authmem_form
->admin_option
)
2449 if (!authmem_form
->admin_option
)
2451 actions
[index
] = RRG_REMOVE_ADMIN_OPTION
;
2454 /* Determine whether the member would still have ADMIN OPTION. */
2455 for (i
= 0; i
< memlist
->n_members
; ++i
)
2457 HeapTuple am_cascade_tuple
;
2458 Form_pg_auth_members am_cascade_form
;
2460 am_cascade_tuple
= &memlist
->members
[i
]->tuple
;
2461 am_cascade_form
= (Form_pg_auth_members
) GETSTRUCT(am_cascade_tuple
);
2463 if (am_cascade_form
->member
== authmem_form
->member
&&
2464 am_cascade_form
->admin_option
&& actions
[i
] == RRG_NOOP
)
2466 would_still_have_admin_option
= true;
2471 /* If the member would still have ADMIN OPTION, we need not recurse. */
2472 if (would_still_have_admin_option
)
2476 * Recurse to grants that are not yet slated for deletion which have this
2477 * member as the grantor.
2479 for (i
= 0; i
< memlist
->n_members
; ++i
)
2481 HeapTuple am_cascade_tuple
;
2482 Form_pg_auth_members am_cascade_form
;
2484 am_cascade_tuple
= &memlist
->members
[i
]->tuple
;
2485 am_cascade_form
= (Form_pg_auth_members
) GETSTRUCT(am_cascade_tuple
);
2487 if (am_cascade_form
->grantor
== authmem_form
->member
&&
2488 actions
[i
] != RRG_DELETE_GRANT
)
2490 if (behavior
== DROP_RESTRICT
)
2492 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST
),
2493 errmsg("dependent privileges exist"),
2494 errhint("Use CASCADE to revoke them too.")));
2496 plan_recursive_revoke(memlist
, actions
, i
, false, behavior
);
2502 * Initialize a GrantRoleOptions object with default values.
2505 InitGrantRoleOptions(GrantRoleOptions
*popt
)
2507 popt
->specified
= 0;
2508 popt
->admin
= false;
2509 popt
->inherit
= false;
2514 * GUC check_hook for createrole_self_grant
2517 check_createrole_self_grant(char **newval
, void **extra
, GucSource source
)
2522 unsigned options
= 0;
2525 /* Need a modifiable copy of string */
2526 rawstring
= pstrdup(*newval
);
2528 if (!SplitIdentifierString(rawstring
, ',', &elemlist
))
2530 /* syntax error in list */
2531 GUC_check_errdetail("List syntax is invalid.");
2533 list_free(elemlist
);
2537 foreach(l
, elemlist
)
2539 char *tok
= (char *) lfirst(l
);
2541 if (pg_strcasecmp(tok
, "SET") == 0)
2542 options
|= GRANT_ROLE_SPECIFIED_SET
;
2543 else if (pg_strcasecmp(tok
, "INHERIT") == 0)
2544 options
|= GRANT_ROLE_SPECIFIED_INHERIT
;
2547 GUC_check_errdetail("Unrecognized key word: \"%s\".", tok
);
2549 list_free(elemlist
);
2555 list_free(elemlist
);
2557 result
= (unsigned *) guc_malloc(LOG
, sizeof(unsigned));
2565 * GUC assign_hook for createrole_self_grant
2568 assign_createrole_self_grant(const char *newval
, void *extra
)
2570 unsigned options
= *(unsigned *) extra
;
2572 createrole_self_grant_enabled
= (options
!= 0);
2573 createrole_self_grant_options
.specified
= GRANT_ROLE_SPECIFIED_ADMIN
2574 | GRANT_ROLE_SPECIFIED_INHERIT
2575 | GRANT_ROLE_SPECIFIED_SET
;
2576 createrole_self_grant_options
.admin
= false;
2577 createrole_self_grant_options
.inherit
=
2578 (options
& GRANT_ROLE_SPECIFIED_INHERIT
) != 0;
2579 createrole_self_grant_options
.set
=
2580 (options
& GRANT_ROLE_SPECIFIED_SET
) != 0;