PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
user.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * user.c
4 * Commands for manipulating roles (formerly called users).
5 *
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 * src/backend/commands/user.c
10 *
11 *-------------------------------------------------------------------------
12 */
13#include "postgres.h"
14
15#include "access/genam.h"
16#include "access/htup_details.h"
17#include "access/table.h"
18#include "access/xact.h"
20#include "catalog/catalog.h"
21#include "catalog/dependency.h"
22#include "catalog/indexing.h"
25#include "catalog/pg_authid.h"
26#include "catalog/pg_database.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 "lib/qunique.h"
34#include "libpq/crypt.h"
35#include "miscadmin.h"
36#include "storage/lmgr.h"
37#include "utils/acl.h"
38#include "utils/builtins.h"
39#include "utils/catcache.h"
40#include "utils/fmgroids.h"
41#include "utils/syscache.h"
42#include "utils/varlena.h"
43
44/*
45 * Removing a role grant - or the admin option on it - might recurse to
46 * dependent grants. We use these values to reason about what would need to
47 * be done in such cases.
48 *
49 * RRG_NOOP indicates a grant that would not need to be altered by the
50 * operation.
51 *
52 * RRG_REMOVE_ADMIN_OPTION indicates a grant that would need to have
53 * admin_option set to false by the operation.
54 *
55 * Similarly, RRG_REMOVE_INHERIT_OPTION and RRG_REMOVE_SET_OPTION indicate
56 * grants that would need to have the corresponding options set to false.
57 *
58 * RRG_DELETE_GRANT indicates a grant that would need to be removed entirely
59 * by the operation.
60 */
61typedef enum
62{
69
70/* Potentially set by pg_upgrade_support functions */
72
73typedef struct
74{
75 unsigned specified;
76 bool admin;
77 bool inherit;
78 bool set;
80
81#define GRANT_ROLE_SPECIFIED_ADMIN 0x0001
82#define GRANT_ROLE_SPECIFIED_INHERIT 0x0002
83#define GRANT_ROLE_SPECIFIED_SET 0x0004
84
85/* GUC parameters */
90
91/* Hook to check passwords in CreateRole() and AlterRole() */
93
94static void AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
95 List *memberSpecs, List *memberIds,
96 Oid grantorId, GrantRoleOptions *popt);
97static void DelRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
98 List *memberSpecs, List *memberIds,
99 Oid grantorId, GrantRoleOptions *popt,
100 DropBehavior behavior);
101static void check_role_membership_authorization(Oid currentUserId, Oid roleid,
102 bool is_grant);
103static Oid check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId,
104 bool is_grant);
106static bool plan_single_revoke(CatCList *memlist,
107 RevokeRoleGrantAction *actions,
108 Oid member, Oid grantor,
109 GrantRoleOptions *popt,
110 DropBehavior behavior);
111static void plan_member_revoke(CatCList *memlist,
112 RevokeRoleGrantAction *actions, Oid member);
113static void plan_recursive_revoke(CatCList *memlist,
114 RevokeRoleGrantAction *actions,
115 int index,
116 bool revoke_admin_option_only,
117 DropBehavior behavior);
118static void InitGrantRoleOptions(GrantRoleOptions *popt);
119
120
121/* Check if current user has createrole privileges */
122static bool
124{
126}
127
128
129/*
130 * CREATE ROLE
131 */
132Oid
134{
135 Relation pg_authid_rel;
136 TupleDesc pg_authid_dsc;
137 HeapTuple tuple;
138 Datum new_record[Natts_pg_authid] = {0};
139 bool new_record_nulls[Natts_pg_authid] = {0};
140 Oid currentUserId = GetUserId();
141 Oid roleid;
142 ListCell *item;
144 char *password = NULL; /* user password */
145 bool issuper = false; /* Make the user a superuser? */
146 bool inherit = true; /* Auto inherit privileges? */
147 bool createrole = false; /* Can this user create roles? */
148 bool createdb = false; /* Can the user create databases? */
149 bool canlogin = false; /* Can this user login? */
150 bool isreplication = false; /* Is this a replication role? */
151 bool bypassrls = false; /* Is this a row security enabled role? */
152 int connlimit = -1; /* maximum connections allowed */
153 List *addroleto = NIL; /* roles to make this a member of */
154 List *rolemembers = NIL; /* roles to be members of this role */
155 List *adminmembers = NIL; /* roles to be admins of this role */
156 char *validUntil = NULL; /* time the login is valid until */
157 Datum validUntil_datum; /* same, as timestamptz Datum */
158 bool validUntil_null;
159 DefElem *dpassword = NULL;
160 DefElem *dissuper = NULL;
161 DefElem *dinherit = NULL;
162 DefElem *dcreaterole = NULL;
163 DefElem *dcreatedb = NULL;
164 DefElem *dcanlogin = NULL;
165 DefElem *disreplication = NULL;
166 DefElem *dconnlimit = NULL;
167 DefElem *daddroleto = NULL;
168 DefElem *drolemembers = NULL;
169 DefElem *dadminmembers = NULL;
170 DefElem *dvalidUntil = NULL;
171 DefElem *dbypassRLS = NULL;
172 GrantRoleOptions popt;
173
174 /* The defaults can vary depending on the original statement type */
175 switch (stmt->stmt_type)
176 {
177 case ROLESTMT_ROLE:
178 break;
179 case ROLESTMT_USER:
180 canlogin = true;
181 /* may eventually want inherit to default to false here */
182 break;
183 case ROLESTMT_GROUP:
184 break;
185 }
186
187 /* Extract options from the statement node tree */
188 foreach(option, stmt->options)
189 {
190 DefElem *defel = (DefElem *) lfirst(option);
191
192 if (strcmp(defel->defname, "password") == 0)
193 {
194 if (dpassword)
195 errorConflictingDefElem(defel, pstate);
196 dpassword = defel;
197 }
198 else if (strcmp(defel->defname, "sysid") == 0)
199 {
201 (errmsg("SYSID can no longer be specified")));
202 }
203 else if (strcmp(defel->defname, "superuser") == 0)
204 {
205 if (dissuper)
206 errorConflictingDefElem(defel, pstate);
207 dissuper = defel;
208 }
209 else if (strcmp(defel->defname, "inherit") == 0)
210 {
211 if (dinherit)
212 errorConflictingDefElem(defel, pstate);
213 dinherit = defel;
214 }
215 else if (strcmp(defel->defname, "createrole") == 0)
216 {
217 if (dcreaterole)
218 errorConflictingDefElem(defel, pstate);
219 dcreaterole = defel;
220 }
221 else if (strcmp(defel->defname, "createdb") == 0)
222 {
223 if (dcreatedb)
224 errorConflictingDefElem(defel, pstate);
225 dcreatedb = defel;
226 }
227 else if (strcmp(defel->defname, "canlogin") == 0)
228 {
229 if (dcanlogin)
230 errorConflictingDefElem(defel, pstate);
231 dcanlogin = defel;
232 }
233 else if (strcmp(defel->defname, "isreplication") == 0)
234 {
235 if (disreplication)
236 errorConflictingDefElem(defel, pstate);
237 disreplication = defel;
238 }
239 else if (strcmp(defel->defname, "connectionlimit") == 0)
240 {
241 if (dconnlimit)
242 errorConflictingDefElem(defel, pstate);
243 dconnlimit = defel;
244 }
245 else if (strcmp(defel->defname, "addroleto") == 0)
246 {
247 if (daddroleto)
248 errorConflictingDefElem(defel, pstate);
249 daddroleto = defel;
250 }
251 else if (strcmp(defel->defname, "rolemembers") == 0)
252 {
253 if (drolemembers)
254 errorConflictingDefElem(defel, pstate);
255 drolemembers = defel;
256 }
257 else if (strcmp(defel->defname, "adminmembers") == 0)
258 {
259 if (dadminmembers)
260 errorConflictingDefElem(defel, pstate);
261 dadminmembers = defel;
262 }
263 else if (strcmp(defel->defname, "validUntil") == 0)
264 {
265 if (dvalidUntil)
266 errorConflictingDefElem(defel, pstate);
267 dvalidUntil = defel;
268 }
269 else if (strcmp(defel->defname, "bypassrls") == 0)
270 {
271 if (dbypassRLS)
272 errorConflictingDefElem(defel, pstate);
273 dbypassRLS = defel;
274 }
275 else
276 elog(ERROR, "option \"%s\" not recognized",
277 defel->defname);
278 }
279
280 if (dpassword && dpassword->arg)
281 password = strVal(dpassword->arg);
282 if (dissuper)
283 issuper = boolVal(dissuper->arg);
284 if (dinherit)
285 inherit = boolVal(dinherit->arg);
286 if (dcreaterole)
287 createrole = boolVal(dcreaterole->arg);
288 if (dcreatedb)
289 createdb = boolVal(dcreatedb->arg);
290 if (dcanlogin)
291 canlogin = boolVal(dcanlogin->arg);
292 if (disreplication)
293 isreplication = boolVal(disreplication->arg);
294 if (dconnlimit)
295 {
296 connlimit = intVal(dconnlimit->arg);
297 if (connlimit < -1)
299 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
300 errmsg("invalid connection limit: %d", connlimit)));
301 }
302 if (daddroleto)
303 addroleto = (List *) daddroleto->arg;
304 if (drolemembers)
305 rolemembers = (List *) drolemembers->arg;
306 if (dadminmembers)
307 adminmembers = (List *) dadminmembers->arg;
308 if (dvalidUntil)
309 validUntil = strVal(dvalidUntil->arg);
310 if (dbypassRLS)
311 bypassrls = boolVal(dbypassRLS->arg);
312
313 /* Check some permissions first */
314 if (!superuser_arg(currentUserId))
315 {
316 if (!has_createrole_privilege(currentUserId))
318 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
319 errmsg("permission denied to create role"),
320 errdetail("Only roles with the %s attribute may create roles.",
321 "CREATEROLE")));
322 if (issuper)
324 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
325 errmsg("permission denied to create role"),
326 errdetail("Only roles with the %s attribute may create roles with the %s attribute.",
327 "SUPERUSER", "SUPERUSER")));
330 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
331 errmsg("permission denied to create role"),
332 errdetail("Only roles with the %s attribute may create roles with the %s attribute.",
333 "CREATEDB", "CREATEDB")));
334 if (isreplication && !has_rolreplication(currentUserId))
336 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
337 errmsg("permission denied to create role"),
338 errdetail("Only roles with the %s attribute may create roles with the %s attribute.",
339 "REPLICATION", "REPLICATION")));
340 if (bypassrls && !has_bypassrls_privilege(currentUserId))
342 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
343 errmsg("permission denied to create role"),
344 errdetail("Only roles with the %s attribute may create roles with the %s attribute.",
345 "BYPASSRLS", "BYPASSRLS")));
346 }
347
348 /*
349 * Check that the user is not trying to create a role in the reserved
350 * "pg_" namespace.
351 */
352 if (IsReservedName(stmt->role))
354 (errcode(ERRCODE_RESERVED_NAME),
355 errmsg("role name \"%s\" is reserved",
356 stmt->role),
357 errdetail("Role names starting with \"pg_\" are reserved.")));
358
359 /*
360 * If built with appropriate switch, whine when regression-testing
361 * conventions for role names are violated.
362 */
363#ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
364 if (strncmp(stmt->role, "regress_", 8) != 0)
365 elog(WARNING, "roles created by regression test cases should have names starting with \"regress_\"");
366#endif
367
368 /*
369 * Check the pg_authid relation to be certain the role doesn't already
370 * exist.
371 */
372 pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
373 pg_authid_dsc = RelationGetDescr(pg_authid_rel);
374
375 if (OidIsValid(get_role_oid(stmt->role, true)))
378 errmsg("role \"%s\" already exists",
379 stmt->role)));
380
381 /* Convert validuntil to internal form */
382 if (validUntil)
383 {
384 validUntil_datum = DirectFunctionCall3(timestamptz_in,
385 CStringGetDatum(validUntil),
387 Int32GetDatum(-1));
388 validUntil_null = false;
389 }
390 else
391 {
392 validUntil_datum = (Datum) 0;
393 validUntil_null = true;
394 }
395
396 /*
397 * Call the password checking hook if there is one defined
398 */
400 (*check_password_hook) (stmt->role,
401 password,
403 validUntil_datum,
404 validUntil_null);
405
406 /*
407 * Build a tuple to insert
408 */
409 new_record[Anum_pg_authid_rolname - 1] =
411 new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper);
412 new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit);
413 new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole);
414 new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb);
415 new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin);
416 new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication);
417 new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
418
419 if (password)
420 {
421 char *shadow_pass;
422 const char *logdetail = NULL;
423
424 /*
425 * Don't allow an empty password. Libpq treats an empty password the
426 * same as no password at all, and won't even try to authenticate. But
427 * other clients might, so allowing it would be confusing. By clearing
428 * the password when an empty string is specified, the account is
429 * consistently locked for all clients.
430 *
431 * Note that this only covers passwords stored in the database itself.
432 * There are also checks in the authentication code, to forbid an
433 * empty password from being used with authentication methods that
434 * fetch the password from an external system, like LDAP or PAM.
435 */
436 if (password[0] == '\0' ||
437 plain_crypt_verify(stmt->role, password, "", &logdetail) == STATUS_OK)
438 {
440 (errmsg("empty string is not a valid password, clearing password")));
441 new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
442 }
443 else
444 {
445 /* Encrypt the password to the requested format. */
446 shadow_pass = encrypt_password(Password_encryption, stmt->role,
447 password);
448 new_record[Anum_pg_authid_rolpassword - 1] =
449 CStringGetTextDatum(shadow_pass);
450 }
451 }
452 else
453 new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
454
455 new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
456 new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
457
458 new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(bypassrls);
459
460 /*
461 * pg_largeobject_metadata contains pg_authid.oid's, so we use the
462 * binary-upgrade override.
463 */
464 if (IsBinaryUpgrade)
465 {
468 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
469 errmsg("pg_authid OID value not set when in binary upgrade mode")));
470
473 }
474 else
475 {
476 roleid = GetNewOidWithIndex(pg_authid_rel, AuthIdOidIndexId,
477 Anum_pg_authid_oid);
478 }
479
480 new_record[Anum_pg_authid_oid - 1] = ObjectIdGetDatum(roleid);
481
482 tuple = heap_form_tuple(pg_authid_dsc, new_record, new_record_nulls);
483
484 /*
485 * Insert new record in the pg_authid table
486 */
487 CatalogTupleInsert(pg_authid_rel, tuple);
488
489 /*
490 * Advance command counter so we can see new record; else tests in
491 * AddRoleMems may fail.
492 */
494
495 /* Default grant. */
497
498 /*
499 * Add the new role to the specified existing roles.
500 */
501 if (addroleto)
502 {
503 RoleSpec *thisrole = makeNode(RoleSpec);
504 List *thisrole_list = list_make1(thisrole);
505 List *thisrole_oidlist = list_make1_oid(roleid);
506
507 thisrole->roletype = ROLESPEC_CSTRING;
508 thisrole->rolename = stmt->role;
509 thisrole->location = -1;
510
511 foreach(item, addroleto)
512 {
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);
518
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,
522 thisrole_list,
523 thisrole_oidlist,
524 InvalidOid, &popt);
525
526 ReleaseSysCache(oldroletup);
527 }
528 }
529
530 /*
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.
534 *
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.
539 */
540 if (!superuser())
541 {
542 RoleSpec *current_role = makeNode(RoleSpec);
543 GrantRoleOptions poptself;
544 List *memberSpecs;
545 List *memberIds = list_make1_oid(currentUserId);
546
547 current_role->roletype = ROLESPEC_CURRENT_ROLE;
548 current_role->location = -1;
549 memberSpecs = list_make1(current_role);
550
554 poptself.admin = true;
555 poptself.inherit = false;
556 poptself.set = false;
557
558 AddRoleMems(BOOTSTRAP_SUPERUSERID, stmt->role, roleid,
559 memberSpecs, memberIds,
560 BOOTSTRAP_SUPERUSERID, &poptself);
561
562 /*
563 * We must make the implicit grant visible to the code below, else the
564 * additional grants will fail.
565 */
567
568 /*
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.
576 */
578 AddRoleMems(currentUserId, stmt->role, roleid,
579 memberSpecs, memberIds,
580 currentUserId, &createrole_self_grant_options);
581 }
582
583 /*
584 * Add the specified members to this new role. adminmembers get the admin
585 * option, rolemembers don't.
586 *
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.
589 */
590 AddRoleMems(currentUserId, stmt->role, roleid,
591 rolemembers, roleSpecsToIds(rolemembers),
592 InvalidOid, &popt);
594 popt.admin = true;
595 AddRoleMems(currentUserId, stmt->role, roleid,
596 adminmembers, roleSpecsToIds(adminmembers),
597 InvalidOid, &popt);
598
599 /* Post creation hook for new role */
600 InvokeObjectPostCreateHook(AuthIdRelationId, roleid, 0);
601
602 /*
603 * Close pg_authid, but keep lock till commit.
604 */
605 table_close(pg_authid_rel, NoLock);
606
607 return roleid;
608}
609
610
611/*
612 * ALTER ROLE
613 *
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.
617 */
618Oid
620{
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;
626 HeapTuple tuple,
627 new_tuple;
628 Form_pg_authid authform;
630 char *rolename;
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;
647 Oid roleid;
648 Oid currentUserId = GetUserId();
649 GrantRoleOptions popt;
650
652 _("Cannot alter reserved roles."));
653
654 /* Extract options from the statement node tree */
655 foreach(option, stmt->options)
656 {
657 DefElem *defel = (DefElem *) lfirst(option);
658
659 if (strcmp(defel->defname, "password") == 0)
660 {
661 if (dpassword)
662 errorConflictingDefElem(defel, pstate);
663 dpassword = defel;
664 }
665 else if (strcmp(defel->defname, "superuser") == 0)
666 {
667 if (dissuper)
668 errorConflictingDefElem(defel, pstate);
669 dissuper = defel;
670 }
671 else if (strcmp(defel->defname, "inherit") == 0)
672 {
673 if (dinherit)
674 errorConflictingDefElem(defel, pstate);
675 dinherit = defel;
676 }
677 else if (strcmp(defel->defname, "createrole") == 0)
678 {
679 if (dcreaterole)
680 errorConflictingDefElem(defel, pstate);
681 dcreaterole = defel;
682 }
683 else if (strcmp(defel->defname, "createdb") == 0)
684 {
685 if (dcreatedb)
686 errorConflictingDefElem(defel, pstate);
687 dcreatedb = defel;
688 }
689 else if (strcmp(defel->defname, "canlogin") == 0)
690 {
691 if (dcanlogin)
692 errorConflictingDefElem(defel, pstate);
693 dcanlogin = defel;
694 }
695 else if (strcmp(defel->defname, "isreplication") == 0)
696 {
697 if (disreplication)
698 errorConflictingDefElem(defel, pstate);
699 disreplication = defel;
700 }
701 else if (strcmp(defel->defname, "connectionlimit") == 0)
702 {
703 if (dconnlimit)
704 errorConflictingDefElem(defel, pstate);
705 dconnlimit = defel;
706 }
707 else if (strcmp(defel->defname, "rolemembers") == 0 &&
708 stmt->action != 0)
709 {
710 if (drolemembers)
711 errorConflictingDefElem(defel, pstate);
712 drolemembers = defel;
713 }
714 else if (strcmp(defel->defname, "validUntil") == 0)
715 {
716 if (dvalidUntil)
717 errorConflictingDefElem(defel, pstate);
718 dvalidUntil = defel;
719 }
720 else if (strcmp(defel->defname, "bypassrls") == 0)
721 {
722 if (dbypassRLS)
723 errorConflictingDefElem(defel, pstate);
724 dbypassRLS = defel;
725 }
726 else
727 elog(ERROR, "option \"%s\" not recognized",
728 defel->defname);
729 }
730
731 if (dpassword && dpassword->arg)
732 password = strVal(dpassword->arg);
733 if (dconnlimit)
734 {
735 connlimit = intVal(dconnlimit->arg);
736 if (connlimit < -1)
738 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
739 errmsg("invalid connection limit: %d", connlimit)));
740 }
741 if (dvalidUntil)
742 validUntil = strVal(dvalidUntil->arg);
743
744 /*
745 * Scan the pg_authid relation to be certain the user exists.
746 */
747 pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
748 pg_authid_dsc = RelationGetDescr(pg_authid_rel);
749
750 tuple = get_rolespec_tuple(stmt->role);
751 authform = (Form_pg_authid) GETSTRUCT(tuple);
752 rolename = pstrdup(NameStr(authform->rolname));
753 roleid = authform->oid;
754
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")));
768
769 /*
770 * Most changes to a role require that you both have CREATEROLE privileges
771 * and also ADMIN OPTION on the role.
772 */
774 !is_admin_of_role(GetUserId(), roleid))
775 {
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)));
784
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")));
792 }
793 else if (!superuser())
794 {
795 /*
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).
799 */
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")));
818 }
819
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)));
827
828 /* Convert validuntil to internal form */
829 if (dvalidUntil)
830 {
831 validUntil_datum = DirectFunctionCall3(timestamptz_in,
832 CStringGetDatum(validUntil),
834 Int32GetDatum(-1));
835 validUntil_null = false;
836 }
837 else
838 {
839 /* fetch existing setting in case hook needs it */
840 validUntil_datum = SysCacheGetAttr(AUTHNAME, tuple,
841 Anum_pg_authid_rolvaliduntil,
842 &validUntil_null);
843 }
844
845 /*
846 * Call the password checking hook if there is one defined
847 */
849 (*check_password_hook) (rolename,
850 password,
852 validUntil_datum,
853 validUntil_null);
854
855 /*
856 * Build an updated tuple, perusing the information just obtained
857 */
858
859 /*
860 * issuper/createrole/etc
861 */
862 if (dissuper)
863 {
864 bool should_be_super = boolVal(dissuper->arg);
865
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.",
871 "SUPERUSER")));
872
873 new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(should_be_super);
874 new_record_repl[Anum_pg_authid_rolsuper - 1] = true;
875 }
876
877 if (dinherit)
878 {
879 new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(boolVal(dinherit->arg));
880 new_record_repl[Anum_pg_authid_rolinherit - 1] = true;
881 }
882
883 if (dcreaterole)
884 {
885 new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(boolVal(dcreaterole->arg));
886 new_record_repl[Anum_pg_authid_rolcreaterole - 1] = true;
887 }
888
889 if (dcreatedb)
890 {
891 new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(boolVal(dcreatedb->arg));
892 new_record_repl[Anum_pg_authid_rolcreatedb - 1] = true;
893 }
894
895 if (dcanlogin)
896 {
897 new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(boolVal(dcanlogin->arg));
898 new_record_repl[Anum_pg_authid_rolcanlogin - 1] = true;
899 }
900
901 if (disreplication)
902 {
903 new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(boolVal(disreplication->arg));
904 new_record_repl[Anum_pg_authid_rolreplication - 1] = true;
905 }
906
907 if (dconnlimit)
908 {
909 new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
910 new_record_repl[Anum_pg_authid_rolconnlimit - 1] = true;
911 }
912
913 /* password */
914 if (password)
915 {
916 char *shadow_pass;
917 const char *logdetail = NULL;
918
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)
922 {
924 (errmsg("empty string is not a valid password, clearing password")));
925 new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
926 }
927 else
928 {
929 /* Encrypt the password to the requested format. */
930 shadow_pass = encrypt_password(Password_encryption, rolename,
931 password);
932 new_record[Anum_pg_authid_rolpassword - 1] =
933 CStringGetTextDatum(shadow_pass);
934 }
935 new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
936 }
937
938 /* unset password */
939 if (dpassword && dpassword->arg == NULL)
940 {
941 new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
942 new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
943 }
944
945 /* valid until */
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;
949
950 if (dbypassRLS)
951 {
952 new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(boolVal(dbypassRLS->arg));
953 new_record_repl[Anum_pg_authid_rolbypassrls - 1] = true;
954 }
955
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);
959
960 InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
961
962 ReleaseSysCache(tuple);
963 heap_freetuple(new_tuple);
964
966
967 /*
968 * Advance command counter so we can see new record; else tests in
969 * AddRoleMems may fail.
970 */
971 if (drolemembers)
972 {
973 List *rolemembers = (List *) drolemembers->arg;
974
976
977 if (stmt->action == +1) /* add members to role */
978 AddRoleMems(currentUserId, rolename, roleid,
979 rolemembers, roleSpecsToIds(rolemembers),
980 InvalidOid, &popt);
981 else if (stmt->action == -1) /* drop members from role */
982 DelRoleMems(currentUserId, rolename, roleid,
983 rolemembers, roleSpecsToIds(rolemembers),
984 InvalidOid, &popt, DROP_RESTRICT);
985 }
986
987 /*
988 * Close pg_authid, but keep lock till commit.
989 */
990 table_close(pg_authid_rel, NoLock);
991
992 return roleid;
993}
994
995
996/*
997 * ALTER ROLE ... SET
998 */
999Oid
1001{
1002 HeapTuple roletuple;
1003 Form_pg_authid roleform;
1004 Oid databaseid = InvalidOid;
1005 Oid roleid = InvalidOid;
1006
1007 if (stmt->role)
1008 {
1010 _("Cannot alter reserved roles."));
1011
1012 roletuple = get_rolespec_tuple(stmt->role);
1013 roleform = (Form_pg_authid) GETSTRUCT(roletuple);
1014 roleid = roleform->oid;
1015
1016 /*
1017 * Obtain a lock on the role and make sure it didn't go away in the
1018 * meantime.
1019 */
1020 shdepLockAndCheckObject(AuthIdRelationId, roleid);
1021
1022 /*
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
1026 */
1027 if (roleform->rolsuper)
1028 {
1029 if (!superuser())
1030 ereport(ERROR,
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")));
1035 }
1036 else
1037 {
1038 if ((!have_createrole_privilege() ||
1039 !is_admin_of_role(GetUserId(), roleid))
1040 && roleid != GetUserId())
1041 ereport(ERROR,
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))));
1046 }
1047
1048 ReleaseSysCache(roletuple);
1049 }
1050
1051 /* look up and lock the database, if specified */
1052 if (stmt->database != NULL)
1053 {
1054 databaseid = get_database_oid(stmt->database, false);
1055 shdepLockAndCheckObject(DatabaseRelationId, databaseid);
1056
1057 if (!stmt->role)
1058 {
1059 /*
1060 * If no role is specified, then this is effectively the same as
1061 * ALTER DATABASE ... SET, so use the same permission check.
1062 */
1063 if (!object_ownercheck(DatabaseRelationId, databaseid, GetUserId()))
1065 stmt->database);
1066 }
1067 }
1068
1069 if (!stmt->role && !stmt->database)
1070 {
1071 /* Must be superuser to alter settings globally. */
1072 if (!superuser())
1073 ereport(ERROR,
1074 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1075 errmsg("permission denied to alter setting"),
1076 errdetail("Only roles with the %s attribute may alter settings globally.",
1077 "SUPERUSER")));
1078 }
1079
1080 AlterSetting(databaseid, roleid, stmt->setstmt);
1081
1082 return roleid;
1083}
1084
1085
1086/*
1087 * DROP ROLE
1088 */
1089void
1091{
1092 Relation pg_authid_rel,
1093 pg_auth_members_rel;
1094 ListCell *item;
1095 List *role_oids = NIL;
1096
1098 ereport(ERROR,
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")));
1103
1104 /*
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.
1107 */
1108 pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
1109 pg_auth_members_rel = table_open(AuthMemRelationId, RowExclusiveLock);
1110
1111 foreach(item, stmt->roles)
1112 {
1113 RoleSpec *rolspec = lfirst(item);
1114 char *role;
1115 HeapTuple tuple,
1116 tmp_tuple;
1117 Form_pg_authid roleform;
1118 ScanKeyData scankey;
1119 SysScanDesc sscan;
1120 Oid roleid;
1121
1122 if (rolspec->roletype != ROLESPEC_CSTRING)
1123 ereport(ERROR,
1124 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1125 errmsg("cannot use special role specifier in DROP ROLE")));
1126 role = rolspec->rolename;
1127
1128 tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
1129 if (!HeapTupleIsValid(tuple))
1130 {
1131 if (!stmt->missing_ok)
1132 {
1133 ereport(ERROR,
1134 (errcode(ERRCODE_UNDEFINED_OBJECT),
1135 errmsg("role \"%s\" does not exist", role)));
1136 }
1137 else
1138 {
1140 (errmsg("role \"%s\" does not exist, skipping",
1141 role)));
1142 }
1143
1144 continue;
1145 }
1146
1147 roleform = (Form_pg_authid) GETSTRUCT(tuple);
1148 roleid = roleform->oid;
1149
1150 if (roleid == GetUserId())
1151 ereport(ERROR,
1152 (errcode(ERRCODE_OBJECT_IN_USE),
1153 errmsg("current user cannot be dropped")));
1154 if (roleid == GetOuterUserId())
1155 ereport(ERROR,
1156 (errcode(ERRCODE_OBJECT_IN_USE),
1157 errmsg("current user cannot be dropped")));
1158 if (roleid == GetSessionUserId())
1159 ereport(ERROR,
1160 (errcode(ERRCODE_OBJECT_IN_USE),
1161 errmsg("session user cannot be dropped")));
1162
1163 /*
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
1166 * OPTION.
1167 */
1168 if (roleform->rolsuper && !superuser())
1169 ereport(ERROR,
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))
1175 ereport(ERROR,
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))));
1180
1181 /* DROP hook for the role being removed */
1182 InvokeObjectDropHook(AuthIdRelationId, roleid, 0);
1183
1184 /* Don't leak the syscache tuple */
1185 ReleaseSysCache(tuple);
1186
1187 /*
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.
1190 */
1191 LockSharedObject(AuthIdRelationId, roleid, 0, AccessExclusiveLock);
1192
1193 /*
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.
1198 *
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.
1204 *
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.
1209 */
1210 ScanKeyInit(&scankey,
1211 Anum_pg_auth_members_roleid,
1212 BTEqualStrategyNumber, F_OIDEQ,
1213 ObjectIdGetDatum(roleid));
1214
1215 sscan = systable_beginscan(pg_auth_members_rel, AuthMemRoleMemIndexId,
1216 true, NULL, 1, &scankey);
1217
1218 while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
1219 {
1220 Form_pg_auth_members authmem_form;
1221
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);
1226 }
1227
1228 systable_endscan(sscan);
1229
1230 ScanKeyInit(&scankey,
1231 Anum_pg_auth_members_member,
1232 BTEqualStrategyNumber, F_OIDEQ,
1233 ObjectIdGetDatum(roleid));
1234
1235 sscan = systable_beginscan(pg_auth_members_rel, AuthMemMemRoleIndexId,
1236 true, NULL, 1, &scankey);
1237
1238 while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
1239 {
1240 Form_pg_auth_members authmem_form;
1241
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);
1246 }
1247
1248 systable_endscan(sscan);
1249
1250 /*
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
1257 * itself.)
1258 */
1260
1261 /* Looks tentatively OK, add it to the list if not there yet. */
1262 role_oids = list_append_unique_oid(role_oids, roleid);
1263 }
1264
1265 /*
1266 * Second pass over the roles to be removed.
1267 */
1268 foreach(item, role_oids)
1269 {
1270 Oid roleid = lfirst_oid(item);
1271 HeapTuple tuple;
1272 Form_pg_authid roleform;
1273 char *detail;
1274 char *detail_log;
1275
1276 /*
1277 * Re-find the pg_authid tuple.
1278 *
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.
1282 */
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);
1287
1288 /*
1289 * Check for pg_shdepend entries depending on this role.
1290 *
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.
1294 */
1295 if (checkSharedDependencies(AuthIdRelationId, roleid,
1296 &detail, &detail_log))
1297 ereport(ERROR,
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)));
1303
1304 /*
1305 * Remove the role from the pg_authid table
1306 */
1307 CatalogTupleDelete(pg_authid_rel, &tuple->t_self);
1308
1309 ReleaseSysCache(tuple);
1310
1311 /*
1312 * Remove any comments or security labels on this role.
1313 */
1314 DeleteSharedComments(roleid, AuthIdRelationId);
1315 DeleteSharedSecurityLabel(roleid, AuthIdRelationId);
1316
1317 /*
1318 * Remove settings for this role.
1319 */
1320 DropSetting(InvalidOid, roleid);
1321 }
1322
1323 /*
1324 * Now we can clean up; but keep locks until commit.
1325 */
1326 table_close(pg_auth_members_rel, NoLock);
1327 table_close(pg_authid_rel, NoLock);
1328}
1329
1330/*
1331 * Rename role
1332 */
1334RenameRole(const char *oldname, const char *newname)
1335{
1336 HeapTuple oldtuple,
1337 newtuple;
1338 TupleDesc dsc;
1339 Relation rel;
1340 Datum datum;
1341 bool isnull;
1342 Datum repl_val[Natts_pg_authid];
1343 bool repl_null[Natts_pg_authid];
1344 bool repl_repl[Natts_pg_authid];
1345 int i;
1346 Oid roleid;
1347 ObjectAddress address;
1348 Form_pg_authid authform;
1349
1350 rel = table_open(AuthIdRelationId, RowExclusiveLock);
1351 dsc = RelationGetDescr(rel);
1352
1353 oldtuple = SearchSysCache1(AUTHNAME, CStringGetDatum(oldname));
1354 if (!HeapTupleIsValid(oldtuple))
1355 ereport(ERROR,
1356 (errcode(ERRCODE_UNDEFINED_OBJECT),
1357 errmsg("role \"%s\" does not exist", oldname)));
1358
1359 /*
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.
1365 */
1366
1367 authform = (Form_pg_authid) GETSTRUCT(oldtuple);
1368 roleid = authform->oid;
1369
1370 if (roleid == GetSessionUserId())
1371 ereport(ERROR,
1372 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1373 errmsg("session user cannot be renamed")));
1374 if (roleid == GetOuterUserId())
1375 ereport(ERROR,
1376 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1377 errmsg("current user cannot be renamed")));
1378
1379 /*
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.
1382 */
1383 if (IsReservedName(NameStr(authform->rolname)))
1384 ereport(ERROR,
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.")));
1389
1390 if (IsReservedName(newname))
1391 ereport(ERROR,
1392 (errcode(ERRCODE_RESERVED_NAME),
1393 errmsg("role name \"%s\" is reserved",
1394 newname),
1395 errdetail("Role names starting with \"pg_\" are reserved.")));
1396
1397 /*
1398 * If built with appropriate switch, whine when regression-testing
1399 * conventions for role names are violated.
1400 */
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_\"");
1404#endif
1405
1406 /* make sure the new name doesn't exist */
1407 if (SearchSysCacheExists1(AUTHNAME, CStringGetDatum(newname)))
1408 ereport(ERROR,
1410 errmsg("role \"%s\" already exists", newname)));
1411
1412 /*
1413 * Only superusers can mess with superusers. Otherwise, a user with
1414 * CREATEROLE can rename a role for which they have ADMIN OPTION.
1415 */
1416 if (authform->rolsuper)
1417 {
1418 if (!superuser())
1419 ereport(ERROR,
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")));
1424 }
1425 else
1426 {
1428 !is_admin_of_role(GetUserId(), roleid))
1429 ereport(ERROR,
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))));
1434 }
1435
1436 /* OK, construct the modified tuple */
1437 for (i = 0; i < Natts_pg_authid; i++)
1438 repl_repl[i] = false;
1439
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;
1444
1445 datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull);
1446
1448 {
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;
1452
1454 (errmsg("MD5 password cleared because of role rename")));
1455 }
1456
1457 newtuple = heap_modify_tuple(oldtuple, dsc, repl_val, repl_null, repl_repl);
1458 CatalogTupleUpdate(rel, &oldtuple->t_self, newtuple);
1459
1460 InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
1461
1462 ObjectAddressSet(address, AuthIdRelationId, roleid);
1463
1464 ReleaseSysCache(oldtuple);
1465
1466 /*
1467 * Close pg_authid, but keep lock till commit.
1468 */
1469 table_close(rel, NoLock);
1470
1471 return address;
1472}
1473
1474/*
1475 * GrantRoleStmt
1476 *
1477 * Grant/Revoke roles to/from roles
1478 */
1479void
1481{
1482 Relation pg_authid_rel;
1483 Oid grantor;
1484 List *grantee_ids;
1485 ListCell *item;
1486 GrantRoleOptions popt;
1487 Oid currentUserId = GetUserId();
1488
1489 /* Parse options list. */
1490 InitGrantRoleOptions(&popt);
1491 foreach(item, stmt->opt)
1492 {
1493 DefElem *opt = (DefElem *) lfirst(item);
1494 char *optval = defGetString(opt);
1495
1496 if (strcmp(opt->defname, "admin") == 0)
1497 {
1499
1500 if (parse_bool(optval, &popt.admin))
1501 continue;
1502 }
1503 else if (strcmp(opt->defname, "inherit") == 0)
1504 {
1506 if (parse_bool(optval, &popt.inherit))
1507 continue;
1508 }
1509 else if (strcmp(opt->defname, "set") == 0)
1510 {
1512 if (parse_bool(optval, &popt.set))
1513 continue;
1514 }
1515 else
1516 ereport(ERROR,
1517 errcode(ERRCODE_SYNTAX_ERROR),
1518 errmsg("unrecognized role option \"%s\"", opt->defname),
1519 parser_errposition(pstate, opt->location));
1520
1521 ereport(ERROR,
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)));
1526 }
1527
1528 /* Lookup OID of grantor, if specified. */
1529 if (stmt->grantor)
1530 grantor = get_rolespec_oid(stmt->grantor, false);
1531 else
1532 grantor = InvalidOid;
1533
1534 grantee_ids = roleSpecsToIds(stmt->grantee_roles);
1535
1536 /* AccessShareLock is enough since we aren't modifying pg_authid */
1537 pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
1538
1539 /*
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.
1545 */
1546 foreach(item, stmt->granted_roles)
1547 {
1548 AccessPriv *priv = (AccessPriv *) lfirst(item);
1549 char *rolename = priv->priv_name;
1550 Oid roleid;
1551
1552 /* Must reject priv(columns) and ALL PRIVILEGES(columns) */
1553 if (rolename == NULL || priv->cols != NIL)
1554 ereport(ERROR,
1555 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1556 errmsg("column names cannot be included in GRANT/REVOKE ROLE")));
1557
1558 roleid = get_role_oid(rolename, false);
1560 roleid, stmt->is_grant);
1561 if (stmt->is_grant)
1562 AddRoleMems(currentUserId, rolename, roleid,
1563 stmt->grantee_roles, grantee_ids,
1564 grantor, &popt);
1565 else
1566 DelRoleMems(currentUserId, rolename, roleid,
1567 stmt->grantee_roles, grantee_ids,
1568 grantor, &popt, stmt->behavior);
1569 }
1570
1571 /*
1572 * Close pg_authid, but keep lock till commit.
1573 */
1574 table_close(pg_authid_rel, NoLock);
1575}
1576
1577/*
1578 * DropOwnedObjects
1579 *
1580 * Drop the objects owned by a given list of roles.
1581 */
1582void
1584{
1585 List *role_ids = roleSpecsToIds(stmt->roles);
1586 ListCell *cell;
1587
1588 /* Check privileges */
1589 foreach(cell, role_ids)
1590 {
1591 Oid roleid = lfirst_oid(cell);
1592
1593 if (!has_privs_of_role(GetUserId(), roleid))
1594 ereport(ERROR,
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))));
1599 }
1600
1601 /* Ok, do it */
1602 shdepDropOwned(role_ids, stmt->behavior);
1603}
1604
1605/*
1606 * ReassignOwnedObjects
1607 *
1608 * Give the objects owned by a given list of roles away to another user.
1609 */
1610void
1612{
1613 List *role_ids = roleSpecsToIds(stmt->roles);
1614 ListCell *cell;
1615 Oid newrole;
1616
1617 /* Check privileges */
1618 foreach(cell, role_ids)
1619 {
1620 Oid roleid = lfirst_oid(cell);
1621
1622 if (!has_privs_of_role(GetUserId(), roleid))
1623 ereport(ERROR,
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))));
1628 }
1629
1630 /* Must have privileges on the receiving side too */
1631 newrole = get_rolespec_oid(stmt->newrole, false);
1632
1633 if (!has_privs_of_role(GetUserId(), newrole))
1634 ereport(ERROR,
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))));
1639
1640 /* Ok, do it */
1641 shdepReassignOwned(role_ids, newrole);
1642}
1643
1644/*
1645 * roleSpecsToIds
1646 *
1647 * Given a list of RoleSpecs, generate a list of role OIDs in the same order.
1648 *
1649 * ROLESPEC_PUBLIC is not allowed.
1650 */
1651List *
1653{
1654 List *result = NIL;
1655 ListCell *l;
1656
1657 foreach(l, memberNames)
1658 {
1659 RoleSpec *rolespec = lfirst_node(RoleSpec, l);
1660 Oid roleid;
1661
1662 roleid = get_rolespec_oid(rolespec, false);
1663 result = lappend_oid(result, roleid);
1664 }
1665 return result;
1666}
1667
1668/*
1669 * AddRoleMems -- Add given members to the specified role
1670 *
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
1679 */
1680static void
1681AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
1682 List *memberSpecs, List *memberIds,
1683 Oid grantorId, GrantRoleOptions *popt)
1684{
1685 Relation pg_authmem_rel;
1686 TupleDesc pg_authmem_dsc;
1687 ListCell *specitem;
1688 ListCell *iditem;
1689
1690 Assert(list_length(memberSpecs) == list_length(memberIds));
1691
1692 /* Validate grantor (and resolve implicit grantor if not specified). */
1693 grantorId = check_role_grantor(currentUserId, roleid, grantorId, true);
1694
1695 pg_authmem_rel = table_open(AuthMemRelationId, RowExclusiveLock);
1696 pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
1697
1698 /*
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.
1702 */
1703 LockSharedObject(AuthIdRelationId, roleid, 0,
1705
1706 /* Preliminary sanity checks. */
1707 forboth(specitem, memberSpecs, iditem, memberIds)
1708 {
1709 RoleSpec *memberRole = lfirst_node(RoleSpec, specitem);
1710 Oid memberid = lfirst_oid(iditem);
1711
1712 /*
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
1721 * the case.
1722 *
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.)
1730 */
1731 if (memberid == ROLE_PG_DATABASE_OWNER)
1732 ereport(ERROR,
1733 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1734 errmsg("role \"%s\" cannot be a member of any role",
1735 get_rolespec_name(memberRole)));
1736
1737 /*
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.
1743 */
1744 if (is_member_of_role_nosuper(roleid, memberid))
1745 ereport(ERROR,
1746 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1747 errmsg("role \"%s\" is a member of role \"%s\"",
1748 rolename, get_rolespec_name(memberRole))));
1749 }
1750
1751 /*
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
1756 * revoked.
1757 *
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
1763 * X back to A).
1764 */
1765 if (popt->admin && grantorId != BOOTSTRAP_SUPERUSERID)
1766 {
1767 CatCList *memlist;
1768 RevokeRoleGrantAction *actions;
1769 int i;
1770
1771 /* Get the list of members for this role. */
1772 memlist = SearchSysCacheList1(AUTHMEMROLEMEM,
1773 ObjectIdGetDatum(roleid));
1774
1775 /*
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.
1778 */
1779 actions = initialize_revoke_actions(memlist);
1780 foreach(iditem, memberIds)
1781 {
1782 Oid memberid = lfirst_oid(iditem);
1783
1784 if (memberid == BOOTSTRAP_SUPERUSERID)
1785 ereport(ERROR,
1786 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1787 errmsg("%s option cannot be granted back to your own grantor",
1788 "ADMIN")));
1789 plan_member_revoke(memlist, actions, memberid);
1790 }
1791
1792 /*
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.
1796 */
1797 for (i = 0; i < memlist->n_members; ++i)
1798 {
1799 HeapTuple authmem_tuple;
1800 Form_pg_auth_members authmem_form;
1801
1802 authmem_tuple = &memlist->members[i]->tuple;
1803 authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
1804
1805 if (actions[i] == RRG_NOOP &&
1806 authmem_form->member == grantorId &&
1807 authmem_form->admin_option)
1808 break;
1809 }
1810 if (i >= memlist->n_members)
1811 ereport(ERROR,
1812 (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1813 errmsg("%s option cannot be granted back to your own grantor",
1814 "ADMIN")));
1815
1816 ReleaseSysCacheList(memlist);
1817 }
1818
1819 /* Now perform the catalog updates. */
1820 forboth(specitem, memberSpecs, iditem, memberIds)
1821 {
1822 RoleSpec *memberRole = lfirst_node(RoleSpec, specitem);
1823 Oid memberid = lfirst_oid(iditem);
1824 HeapTuple authmem_tuple;
1825 HeapTuple 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};
1829
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);
1837
1838 /* Find any existing tuple */
1839 authmem_tuple = SearchSysCache3(AUTHMEMROLEMEM,
1840 ObjectIdGetDatum(roleid),
1841 ObjectIdGetDatum(memberid),
1842 ObjectIdGetDatum(grantorId));
1843
1844 /*
1845 * If we found a tuple, update it with new option values, unless there
1846 * are no changes, in which case issue a WARNING.
1847 *
1848 * If we didn't find a tuple, just insert one.
1849 */
1850 if (HeapTupleIsValid(authmem_tuple))
1851 {
1852 Form_pg_auth_members authmem_form;
1853 bool at_least_one_change = false;
1854
1855 authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
1856
1857 if ((popt->specified & GRANT_ROLE_SPECIFIED_ADMIN) != 0
1858 && authmem_form->admin_option != popt->admin)
1859 {
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] =
1863 true;
1864 at_least_one_change = true;
1865 }
1866
1867 if ((popt->specified & GRANT_ROLE_SPECIFIED_INHERIT) != 0
1868 && authmem_form->inherit_option != popt->inherit)
1869 {
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] =
1873 true;
1874 at_least_one_change = true;
1875 }
1876
1877 if ((popt->specified & GRANT_ROLE_SPECIFIED_SET) != 0
1878 && authmem_form->set_option != popt->set)
1879 {
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] =
1883 true;
1884 at_least_one_change = true;
1885 }
1886
1887 if (!at_least_one_change)
1888 {
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);
1894 continue;
1895 }
1896
1897 tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
1898 new_record,
1899 new_record_nulls, new_record_repl);
1900 CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple);
1901
1902 ReleaseSysCache(authmem_tuple);
1903 }
1904 else
1905 {
1906 Oid objectId;
1907 Oid *newmembers = (Oid *) palloc(3 * sizeof(Oid));
1908 int nnewmembers;
1909
1910 /*
1911 * The values for these options can be taken directly from 'popt'.
1912 * Either they were specified, or the defaults as set by
1913 * InitGrantRoleOptions are correct.
1914 */
1915 new_record[Anum_pg_auth_members_admin_option - 1] =
1916 BoolGetDatum(popt->admin);
1917 new_record[Anum_pg_auth_members_set_option - 1] =
1918 BoolGetDatum(popt->set);
1919
1920 /*
1921 * If the user specified a value for the inherit option, use
1922 * whatever was specified. Otherwise, set the default value based
1923 * on the role-level property.
1924 */
1925 if ((popt->specified & GRANT_ROLE_SPECIFIED_INHERIT) != 0)
1926 new_record[Anum_pg_auth_members_inherit_option - 1] =
1927 popt->inherit;
1928 else
1929 {
1930 HeapTuple mrtup;
1931 Form_pg_authid mrform;
1932
1933 mrtup = SearchSysCache1(AUTHOID, ObjectIdGetDatum(memberid));
1934 if (!HeapTupleIsValid(mrtup))
1935 elog(ERROR, "cache lookup failed for role %u", memberid);
1936 mrform = (Form_pg_authid) GETSTRUCT(mrtup);
1937 new_record[Anum_pg_auth_members_inherit_option - 1] =
1938 mrform->rolinherit;
1939 ReleaseSysCache(mrtup);
1940 }
1941
1942 /* get an OID for the new row and insert it */
1943 objectId = GetNewOidWithIndex(pg_authmem_rel, AuthMemOidIndexId,
1944 Anum_pg_auth_members_oid);
1945 new_record[Anum_pg_auth_members_oid - 1] = objectId;
1946 tuple = heap_form_tuple(pg_authmem_dsc,
1947 new_record, new_record_nulls);
1948 CatalogTupleInsert(pg_authmem_rel, tuple);
1949
1950 /*
1951 * Record dependencies on the roleid, member, and grantor, as if a
1952 * pg_auth_members entry were an object ACL.
1953 * updateAclDependencies() requires an input array that is
1954 * palloc'd (it will free it), sorted, and de-duped.
1955 */
1956 newmembers[0] = roleid;
1957 newmembers[1] = memberid;
1958 newmembers[2] = grantorId;
1959 qsort(newmembers, 3, sizeof(Oid), oid_cmp);
1960 nnewmembers = qunique(newmembers, 3, sizeof(Oid), oid_cmp);
1961
1962 updateAclDependencies(AuthMemRelationId, objectId,
1963 0, InvalidOid,
1964 0, NULL,
1965 nnewmembers, newmembers);
1966 }
1967
1968 /* CCI after each change, in case there are duplicates in list */
1970 }
1971
1972 /*
1973 * Close pg_authmem, but keep lock till commit.
1974 */
1975 table_close(pg_authmem_rel, NoLock);
1976}
1977
1978/*
1979 * DelRoleMems -- Remove given members from the specified role
1980 *
1981 * rolename: name of role to del from (used only for error messages)
1982 * roleid: OID of role to del from
1983 * memberSpecs: list of RoleSpec of roles to del (used only for error messages)
1984 * memberIds: OIDs of roles to del
1985 * grantorId: who is revoking the membership
1986 * popt: information about grant options
1987 * behavior: RESTRICT or CASCADE behavior for recursive removal
1988 */
1989static void
1990DelRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
1991 List *memberSpecs, List *memberIds,
1992 Oid grantorId, GrantRoleOptions *popt, DropBehavior behavior)
1993{
1994 Relation pg_authmem_rel;
1995 TupleDesc pg_authmem_dsc;
1996 ListCell *specitem;
1997 ListCell *iditem;
1998 CatCList *memlist;
1999 RevokeRoleGrantAction *actions;
2000 int i;
2001
2002 Assert(list_length(memberSpecs) == list_length(memberIds));
2003
2004 /* Validate grantor (and resolve implicit grantor if not specified). */
2005 grantorId = check_role_grantor(currentUserId, roleid, grantorId, false);
2006
2007 pg_authmem_rel = table_open(AuthMemRelationId, RowExclusiveLock);
2008 pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
2009
2010 /*
2011 * Only allow changes to this role by one backend at a time, so that we
2012 * can check for things like dependent privileges without fear of race
2013 * conditions.
2014 */
2015 LockSharedObject(AuthIdRelationId, roleid, 0,
2017
2018 memlist = SearchSysCacheList1(AUTHMEMROLEMEM, ObjectIdGetDatum(roleid));
2019 actions = initialize_revoke_actions(memlist);
2020
2021 /*
2022 * We may need to recurse to dependent privileges if DROP_CASCADE was
2023 * specified, or refuse to perform the operation if dependent privileges
2024 * exist and DROP_RESTRICT was specified. plan_single_revoke() will figure
2025 * out what to do with each catalog tuple.
2026 */
2027 forboth(specitem, memberSpecs, iditem, memberIds)
2028 {
2029 RoleSpec *memberRole = lfirst(specitem);
2030 Oid memberid = lfirst_oid(iditem);
2031
2032 if (!plan_single_revoke(memlist, actions, memberid, grantorId,
2033 popt, behavior))
2034 {
2036 (errmsg("role \"%s\" has not been granted membership in role \"%s\" by role \"%s\"",
2037 get_rolespec_name(memberRole), rolename,
2038 GetUserNameFromId(grantorId, false))));
2039 continue;
2040 }
2041 }
2042
2043 /*
2044 * We now know what to do with each catalog tuple: it should either be
2045 * left alone, deleted, or just have the admin_option flag cleared.
2046 * Perform the appropriate action in each case.
2047 */
2048 for (i = 0; i < memlist->n_members; ++i)
2049 {
2050 HeapTuple authmem_tuple;
2051 Form_pg_auth_members authmem_form;
2052
2053 if (actions[i] == RRG_NOOP)
2054 continue;
2055
2056 authmem_tuple = &memlist->members[i]->tuple;
2057 authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
2058
2059 if (actions[i] == RRG_DELETE_GRANT)
2060 {
2061 /*
2062 * Remove the entry altogether, after first removing its
2063 * dependencies
2064 */
2065 deleteSharedDependencyRecordsFor(AuthMemRelationId,
2066 authmem_form->oid, 0);
2067 CatalogTupleDelete(pg_authmem_rel, &authmem_tuple->t_self);
2068 }
2069 else
2070 {
2071 /* Just turn off the specified option */
2072 HeapTuple tuple;
2073 Datum new_record[Natts_pg_auth_members] = {0};
2074 bool new_record_nulls[Natts_pg_auth_members] = {0};
2075 bool new_record_repl[Natts_pg_auth_members] = {0};
2076
2077 /* Build a tuple to update with */
2078 if (actions[i] == RRG_REMOVE_ADMIN_OPTION)
2079 {
2080 new_record[Anum_pg_auth_members_admin_option - 1] =
2081 BoolGetDatum(false);
2082 new_record_repl[Anum_pg_auth_members_admin_option - 1] =
2083 true;
2084 }
2085 else if (actions[i] == RRG_REMOVE_INHERIT_OPTION)
2086 {
2087 new_record[Anum_pg_auth_members_inherit_option - 1] =
2088 BoolGetDatum(false);
2089 new_record_repl[Anum_pg_auth_members_inherit_option - 1] =
2090 true;
2091 }
2092 else if (actions[i] == RRG_REMOVE_SET_OPTION)
2093 {
2094 new_record[Anum_pg_auth_members_set_option - 1] =
2095 BoolGetDatum(false);
2096 new_record_repl[Anum_pg_auth_members_set_option - 1] =
2097 true;
2098 }
2099 else
2100 elog(ERROR, "unknown role revoke action");
2101
2102 tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
2103 new_record,
2104 new_record_nulls, new_record_repl);
2105 CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple);
2106 }
2107 }
2108
2109 ReleaseSysCacheList(memlist);
2110
2111 /*
2112 * Close pg_authmem, but keep lock till commit.
2113 */
2114 table_close(pg_authmem_rel, NoLock);
2115}
2116
2117/*
2118 * Check that currentUserId has permission to modify the membership list for
2119 * roleid. Throw an error if not.
2120 */
2121static void
2123 bool is_grant)
2124{
2125 /*
2126 * The charter of pg_database_owner is to have exactly one, implicit,
2127 * situation-dependent member. There's no technical need for this
2128 * restriction. (One could lift it and take the further step of making
2129 * object_ownercheck(DatabaseRelationId, ...) equivalent to
2130 * has_privs_of_role(roleid, ROLE_PG_DATABASE_OWNER), in which case
2131 * explicit, situation-independent members could act as the owner of any
2132 * database.)
2133 */
2134 if (is_grant && roleid == ROLE_PG_DATABASE_OWNER)
2135 ereport(ERROR,
2136 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2137 errmsg("role \"%s\" cannot have explicit members",
2138 GetUserNameFromId(roleid, false)));
2139
2140 /* To mess with a superuser role, you gotta be superuser. */
2141 if (superuser_arg(roleid))
2142 {
2143 if (!superuser_arg(currentUserId))
2144 {
2145 if (is_grant)
2146 ereport(ERROR,
2147 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2148 errmsg("permission denied to grant role \"%s\"",
2149 GetUserNameFromId(roleid, false)),
2150 errdetail("Only roles with the %s attribute may grant roles with the %s attribute.",
2151 "SUPERUSER", "SUPERUSER")));
2152 else
2153 ereport(ERROR,
2154 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2155 errmsg("permission denied to revoke role \"%s\"",
2156 GetUserNameFromId(roleid, false)),
2157 errdetail("Only roles with the %s attribute may revoke roles with the %s attribute.",
2158 "SUPERUSER", "SUPERUSER")));
2159 }
2160 }
2161 else
2162 {
2163 /*
2164 * Otherwise, must have admin option on the role to be changed.
2165 */
2166 if (!is_admin_of_role(currentUserId, roleid))
2167 {
2168 if (is_grant)
2169 ereport(ERROR,
2170 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2171 errmsg("permission denied to grant role \"%s\"",
2172 GetUserNameFromId(roleid, false)),
2173 errdetail("Only roles with the %s option on role \"%s\" may grant this role.",
2174 "ADMIN", GetUserNameFromId(roleid, false))));
2175 else
2176 ereport(ERROR,
2177 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2178 errmsg("permission denied to revoke role \"%s\"",
2179 GetUserNameFromId(roleid, false)),
2180 errdetail("Only roles with the %s option on role \"%s\" may revoke this role.",
2181 "ADMIN", GetUserNameFromId(roleid, false))));
2182 }
2183 }
2184}
2185
2186/*
2187 * Sanity-check, or infer, the grantor for a GRANT or REVOKE statement
2188 * targeting a role.
2189 *
2190 * The grantor must always be either a role with ADMIN OPTION on the role in
2191 * which membership is being granted, or the bootstrap superuser. This is
2192 * similar to the restriction enforced by select_best_grantor, except that
2193 * roles don't have owners, so we regard the bootstrap superuser as the
2194 * implicit owner.
2195 *
2196 * If the grantor was not explicitly specified by the user, grantorId should
2197 * be passed as InvalidOid, and this function will infer the user to be
2198 * recorded as the grantor. In many cases, this will be the current user, but
2199 * things get more complicated when the current user doesn't possess ADMIN
2200 * OPTION on the role but rather relies on having SUPERUSER privileges, or
2201 * on inheriting the privileges of a role which does have ADMIN OPTION. See
2202 * below for details.
2203 *
2204 * If the grantor was specified by the user, then it must be a user that
2205 * can legally be recorded as the grantor, as per the rule stated above.
2206 * This is an integrity constraint, not a permissions check, and thus even
2207 * superusers are subject to this restriction. However, there is also a
2208 * permissions check: to specify a role as the grantor, the current user
2209 * must possess the privileges of that role. Superusers will always pass
2210 * this check, but for non-superusers it may lead to an error.
2211 *
2212 * The return value is the OID to be regarded as the grantor when executing
2213 * the operation.
2214 */
2215static Oid
2216check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId, bool is_grant)
2217{
2218 /* If the grantor ID was not specified, pick one to use. */
2219 if (!OidIsValid(grantorId))
2220 {
2221 /*
2222 * Grants where the grantor is recorded as the bootstrap superuser do
2223 * not depend on any other existing grants, so always default to this
2224 * interpretation when possible.
2225 */
2226 if (superuser_arg(currentUserId))
2227 return BOOTSTRAP_SUPERUSERID;
2228
2229 /*
2230 * Otherwise, the grantor must either have ADMIN OPTION on the role or
2231 * inherit the privileges of a role which does. In the former case,
2232 * record the grantor as the current user; in the latter, pick one of
2233 * the roles that is "most directly" inherited by the current role
2234 * (i.e. fewest "hops").
2235 *
2236 * (We shouldn't fail to find a best grantor, because we've already
2237 * established that the current user has permission to perform the
2238 * operation.)
2239 */
2240 grantorId = select_best_admin(currentUserId, roleid);
2241 if (!OidIsValid(grantorId))
2242 elog(ERROR, "no possible grantors");
2243 return grantorId;
2244 }
2245
2246 /*
2247 * If an explicit grantor is specified, it must be a role whose privileges
2248 * the current user possesses.
2249 *
2250 * It should also be a role that has ADMIN OPTION on the target role, but
2251 * we check this condition only in case of GRANT. For REVOKE, no matching
2252 * grant should exist anyway, but if it somehow does, let the user get rid
2253 * of it.
2254 */
2255 if (is_grant)
2256 {
2257 if (!has_privs_of_role(currentUserId, grantorId))
2258 ereport(ERROR,
2259 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2260 errmsg("permission denied to grant privileges as role \"%s\"",
2261 GetUserNameFromId(grantorId, false)),
2262 errdetail("Only roles with privileges of role \"%s\" may grant privileges as this role.",
2263 GetUserNameFromId(grantorId, false))));
2264
2265 if (grantorId != BOOTSTRAP_SUPERUSERID &&
2266 select_best_admin(grantorId, roleid) != grantorId)
2267 ereport(ERROR,
2268 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2269 errmsg("permission denied to grant privileges as role \"%s\"",
2270 GetUserNameFromId(grantorId, false)),
2271 errdetail("The grantor must have the %s option on role \"%s\".",
2272 "ADMIN", GetUserNameFromId(roleid, false))));
2273 }
2274 else
2275 {
2276 if (!has_privs_of_role(currentUserId, grantorId))
2277 ereport(ERROR,
2278 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2279 errmsg("permission denied to revoke privileges granted by role \"%s\"",
2280 GetUserNameFromId(grantorId, false)),
2281 errdetail("Only roles with privileges of role \"%s\" may revoke privileges granted by this role.",
2282 GetUserNameFromId(grantorId, false))));
2283 }
2284
2285 /*
2286 * If a grantor was specified explicitly, always attribute the grant to
2287 * that role (unless we error out above).
2288 */
2289 return grantorId;
2290}
2291
2292/*
2293 * Initialize an array of RevokeRoleGrantAction objects.
2294 *
2295 * 'memlist' should be a list of all grants for the target role.
2296 *
2297 * This constructs an array indicating that no actions are to be performed;
2298 * that is, every element is initially RRG_NOOP.
2299 */
2300static RevokeRoleGrantAction *
2302{
2303 RevokeRoleGrantAction *result;
2304 int i;
2305
2306 if (memlist->n_members == 0)
2307 return NULL;
2308
2309 result = palloc(sizeof(RevokeRoleGrantAction) * memlist->n_members);
2310 for (i = 0; i < memlist->n_members; i++)
2311 result[i] = RRG_NOOP;
2312 return result;
2313}
2314
2315/*
2316 * Figure out what we would need to do in order to revoke a grant, or just the
2317 * admin option on a grant, given that there might be dependent privileges.
2318 *
2319 * 'memlist' should be a list of all grants for the target role.
2320 *
2321 * Whatever actions prove to be necessary will be signalled by updating
2322 * 'actions'.
2323 *
2324 * If behavior is DROP_RESTRICT, an error will occur if there are dependent
2325 * role membership grants; if DROP_CASCADE, those grants will be scheduled
2326 * for deletion.
2327 *
2328 * The return value is true if the matching grant was found in the list,
2329 * and false if not.
2330 */
2331static bool
2333 Oid member, Oid grantor, GrantRoleOptions *popt,
2334 DropBehavior behavior)
2335{
2336 int i;
2337
2338 /*
2339 * If popt.specified == 0, we're revoking the grant entirely; otherwise,
2340 * we expect just one bit to be set, and we're revoking the corresponding
2341 * option. As of this writing, there's no syntax that would allow for an
2342 * attempt to revoke multiple options at once, and the logic below
2343 * wouldn't work properly if such syntax were added, so assert that our
2344 * caller isn't trying to do that.
2345 */
2346 Assert(pg_popcount32(popt->specified) <= 1);
2347
2348 for (i = 0; i < memlist->n_members; ++i)
2349 {
2350 HeapTuple authmem_tuple;
2351 Form_pg_auth_members authmem_form;
2352
2353 authmem_tuple = &memlist->members[i]->tuple;
2354 authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
2355
2356 if (authmem_form->member == member &&
2357 authmem_form->grantor == grantor)
2358 {
2359 if ((popt->specified & GRANT_ROLE_SPECIFIED_INHERIT) != 0)
2360 {
2361 /*
2362 * Revoking the INHERIT option doesn't change anything for
2363 * dependent privileges, so we don't need to recurse.
2364 */
2365 actions[i] = RRG_REMOVE_INHERIT_OPTION;
2366 }
2367 else if ((popt->specified & GRANT_ROLE_SPECIFIED_SET) != 0)
2368 {
2369 /* Here too, no need to recurse. */
2370 actions[i] = RRG_REMOVE_SET_OPTION;
2371 }
2372 else
2373 {
2374 bool revoke_admin_option_only;
2375
2376 /*
2377 * Revoking the grant entirely, or ADMIN option on a grant,
2378 * implicates dependent privileges, so we may need to recurse.
2379 */
2380 revoke_admin_option_only =
2382 plan_recursive_revoke(memlist, actions, i,
2383 revoke_admin_option_only, behavior);
2384 }
2385 return true;
2386 }
2387 }
2388
2389 return false;
2390}
2391
2392/*
2393 * Figure out what we would need to do in order to revoke all grants to
2394 * a given member, given that there might be dependent privileges.
2395 *
2396 * 'memlist' should be a list of all grants for the target role.
2397 *
2398 * Whatever actions prove to be necessary will be signalled by updating
2399 * 'actions'.
2400 */
2401static void
2403 Oid member)
2404{
2405 int i;
2406
2407 for (i = 0; i < memlist->n_members; ++i)
2408 {
2409 HeapTuple authmem_tuple;
2410 Form_pg_auth_members authmem_form;
2411
2412 authmem_tuple = &memlist->members[i]->tuple;
2413 authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
2414
2415 if (authmem_form->member == member)
2416 plan_recursive_revoke(memlist, actions, i, false, DROP_CASCADE);
2417 }
2418}
2419
2420/*
2421 * Workhorse for figuring out recursive revocation of role grants.
2422 *
2423 * This is similar to what recursive_revoke() does for ACLs.
2424 */
2425static void
2427 int index,
2428 bool revoke_admin_option_only, DropBehavior behavior)
2429{
2430 bool would_still_have_admin_option = false;
2431 HeapTuple authmem_tuple;
2432 Form_pg_auth_members authmem_form;
2433 int i;
2434
2435 /* If it's already been done, we can just return. */
2436 if (actions[index] == RRG_DELETE_GRANT)
2437 return;
2438 if (actions[index] == RRG_REMOVE_ADMIN_OPTION &&
2439 revoke_admin_option_only)
2440 return;
2441
2442 /* Locate tuple data. */
2443 authmem_tuple = &memlist->members[index]->tuple;
2444 authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
2445
2446 /*
2447 * If the existing tuple does not have admin_option set, then we do not
2448 * need to recurse. If we're just supposed to clear that bit we don't need
2449 * to do anything at all; if we're supposed to remove the grant, we need
2450 * to do something, but only to the tuple, and not any others.
2451 */
2452 if (!revoke_admin_option_only)
2453 {
2454 actions[index] = RRG_DELETE_GRANT;
2455 if (!authmem_form->admin_option)
2456 return;
2457 }
2458 else
2459 {
2460 if (!authmem_form->admin_option)
2461 return;
2462 actions[index] = RRG_REMOVE_ADMIN_OPTION;
2463 }
2464
2465 /* Determine whether the member would still have ADMIN OPTION. */
2466 for (i = 0; i < memlist->n_members; ++i)
2467 {
2468 HeapTuple am_cascade_tuple;
2469 Form_pg_auth_members am_cascade_form;
2470
2471 am_cascade_tuple = &memlist->members[i]->tuple;
2472 am_cascade_form = (Form_pg_auth_members) GETSTRUCT(am_cascade_tuple);
2473
2474 if (am_cascade_form->member == authmem_form->member &&
2475 am_cascade_form->admin_option && actions[i] == RRG_NOOP)
2476 {
2477 would_still_have_admin_option = true;
2478 break;
2479 }
2480 }
2481
2482 /* If the member would still have ADMIN OPTION, we need not recurse. */
2483 if (would_still_have_admin_option)
2484 return;
2485
2486 /*
2487 * Recurse to grants that are not yet slated for deletion which have this
2488 * member as the grantor.
2489 */
2490 for (i = 0; i < memlist->n_members; ++i)
2491 {
2492 HeapTuple am_cascade_tuple;
2493 Form_pg_auth_members am_cascade_form;
2494
2495 am_cascade_tuple = &memlist->members[i]->tuple;
2496 am_cascade_form = (Form_pg_auth_members) GETSTRUCT(am_cascade_tuple);
2497
2498 if (am_cascade_form->grantor == authmem_form->member &&
2499 actions[i] != RRG_DELETE_GRANT)
2500 {
2501 if (behavior == DROP_RESTRICT)
2502 ereport(ERROR,
2503 (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
2504 errmsg("dependent privileges exist"),
2505 errhint("Use CASCADE to revoke them too.")));
2506
2507 plan_recursive_revoke(memlist, actions, i, false, behavior);
2508 }
2509 }
2510}
2511
2512/*
2513 * Initialize a GrantRoleOptions object with default values.
2514 */
2515static void
2517{
2518 popt->specified = 0;
2519 popt->admin = false;
2520 popt->inherit = false;
2521 popt->set = true;
2522}
2523
2524/*
2525 * GUC check_hook for createrole_self_grant
2526 */
2527bool
2529{
2530 char *rawstring;
2531 List *elemlist;
2532 ListCell *l;
2533 unsigned options = 0;
2534 unsigned *result;
2535
2536 /* Need a modifiable copy of string */
2537 rawstring = pstrdup(*newval);
2538
2539 if (!SplitIdentifierString(rawstring, ',', &elemlist))
2540 {
2541 /* syntax error in list */
2542 GUC_check_errdetail("List syntax is invalid.");
2543 pfree(rawstring);
2544 list_free(elemlist);
2545 return false;
2546 }
2547
2548 foreach(l, elemlist)
2549 {
2550 char *tok = (char *) lfirst(l);
2551
2552 if (pg_strcasecmp(tok, "SET") == 0)
2554 else if (pg_strcasecmp(tok, "INHERIT") == 0)
2556 else
2557 {
2558 GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
2559 pfree(rawstring);
2560 list_free(elemlist);
2561 return false;
2562 }
2563 }
2564
2565 pfree(rawstring);
2566 list_free(elemlist);
2567
2568 result = (unsigned *) guc_malloc(LOG, sizeof(unsigned));
2569 if (!result)
2570 return false;
2571 *result = options;
2572 *extra = result;
2573
2574 return true;
2575}
2576
2577/*
2578 * GUC assign_hook for createrole_self_grant
2579 */
2580void
2581assign_createrole_self_grant(const char *newval, void *extra)
2582{
2583 unsigned options = *(unsigned *) extra;
2584
2594}
bool is_admin_of_role(Oid member, Oid role)
Definition: acl.c:5398
Oid select_best_admin(Oid member, Oid role)
Definition: acl.c:5423
bool is_member_of_role_nosuper(Oid member, Oid role)
Definition: acl.c:5376
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5268
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5536
char * get_rolespec_name(const RoleSpec *role)
Definition: acl.c:5655
void check_rolespec_name(const RoleSpec *role, const char *detail_msg)
Definition: acl.c:5677
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5570
HeapTuple get_rolespec_tuple(const RoleSpec *role)
Definition: acl.c:5609
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
bool has_bypassrls_privilege(Oid roleid)
Definition: aclchk.c:4173
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2639
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4075
bool has_createrole_privilege(Oid roleid)
Definition: aclchk.c:4154
Datum timestamptz_in(PG_FUNCTION_ARGS)
Definition: timestamp.c:418
bool parse_bool(const char *value, bool *result)
Definition: bool.c:31
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:717
#define STATUS_OK
Definition: c.h:1140
#define OidIsValid(objectId)
Definition: c.h:746
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:450
bool IsReservedName(const char *name)
Definition: catalog.c:278
void DeleteSharedComments(Oid oid, Oid classoid)
Definition: comment.c:374
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char **logdetail)
Definition: crypt.c:256
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:90
char * encrypt_password(PasswordType target_type, const char *role, const char *password)
Definition: crypt.c:117
@ PASSWORD_TYPE_SCRAM_SHA_256
Definition: crypt.h:44
@ PASSWORD_TYPE_MD5
Definition: crypt.h:43
bool have_createdb_privilege(void)
Definition: dbcommands.c:2953
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:3141
Oid createdb(ParseState *pstate, const CreatedbStmt *stmt)
Definition: dbcommands.c:684
char * defGetString(DefElem *def)
Definition: define.c:35
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:371
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1231
int errdetail(const char *fmt,...)
Definition: elog.c:1204
int errhint(const char *fmt,...)
Definition: elog.c:1318
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
int errdetail_log(const char *fmt,...)
Definition: elog.c:1252
#define _(x)
Definition: elog.c:91
#define LOG
Definition: elog.h:31
#define WARNING
Definition: elog.h:36
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define NOTICE
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:149
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:682
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:686
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:388
bool IsBinaryUpgrade
Definition: globals.c:122
void * guc_malloc(int elevel, size_t size)
Definition: guc.c:638
#define newval
#define GUC_check_errdetail
Definition: guc.h:481
GucSource
Definition: guc.h:112
Assert(PointerIsAligned(start, uint64))
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1210
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1117
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1435
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:904
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
#define stmt
Definition: indent_codes.h:59
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
int i
Definition: isn.c:77
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:81
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
List * list_append_unique_oid(List *list, Oid datum)
Definition: list.c:1380
void list_free(List *list)
Definition: list.c:1546
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1082
#define NoLock
Definition: lockdefs.h:34
#define AccessExclusiveLock
Definition: lockdefs.h:43
#define AccessShareLock
Definition: lockdefs.h:36
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
#define RowExclusiveLock
Definition: lockdefs.h:38
char * pstrdup(const char *in)
Definition: mcxt.c:2321
void pfree(void *pointer)
Definition: mcxt.c:2146
void * palloc(Size size)
Definition: mcxt.c:1939
Oid GetOuterUserId(void)
Definition: miscinit.c:531
Oid GetUserId(void)
Definition: miscinit.c:520
Oid GetSessionUserId(void)
Definition: miscinit.c:559
bool has_rolreplication(Oid roleid)
Definition: miscinit.c:739
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition: miscinit.c:1039
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
#define makeNode(_type_)
Definition: nodes.h:161
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:173
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
#define InvokeObjectDropHook(classId, objectId, subId)
Definition: objectaccess.h:182
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
int oid_cmp(const void *p1, const void *p2)
Definition: oid.c:258
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:106
@ ROLESPEC_CSTRING
Definition: parsenodes.h:405
@ ROLESPEC_CURRENT_ROLE
Definition: parsenodes.h:406
DropBehavior
Definition: parsenodes.h:2389
@ DROP_CASCADE
Definition: parsenodes.h:2391
@ DROP_RESTRICT
Definition: parsenodes.h:2390
@ OBJECT_DATABASE
Definition: parsenodes.h:2326
@ ROLESTMT_ROLE
Definition: parsenodes.h:3170
@ ROLESTMT_USER
Definition: parsenodes.h:3171
@ ROLESTMT_GROUP
Definition: parsenodes.h:3172
FormData_pg_auth_members * Form_pg_auth_members
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
int pg_popcount32(uint32 word)
Definition: pg_bitutils.c:509
void DropSetting(Oid databaseid, Oid roleid)
void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
#define lfirst(lc)
Definition: pg_list.h:172
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
#define list_make1_oid(x1)
Definition: pg_list.h:242
#define list_make1(x1)
Definition: pg_list.h:212
#define lfirst_oid(lc)
Definition: pg_list.h:174
static char ** options
static rewind_source * source
Definition: pg_rewind.c:89
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:1047
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:491
bool checkSharedDependencies(Oid classId, Oid objectId, char **detail_msg, char **detail_log_msg)
Definition: pg_shdepend.c:676
void shdepDropOwned(List *roleids, DropBehavior behavior)
Definition: pg_shdepend.c:1342
void shdepLockAndCheckObject(Oid classId, Oid objectId)
Definition: pg_shdepend.c:1211
void shdepReassignOwned(List *roleids, Oid newrole)
Definition: pg_shdepend.c:1530
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define qsort(a, b, c, d)
Definition: port.h:479
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
uintptr_t Datum
Definition: postgres.h:69
static Datum BoolGetDatum(bool X)
Definition: postgres.h:107
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:355
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
#define InvalidOid
Definition: postgres_ext.h:35
unsigned int Oid
Definition: postgres_ext.h:30
static size_t qunique(void *array, size_t elements, size_t width, int(*compare)(const void *, const void *))
Definition: qunique.h:21
#define RelationGetDescr(relation)
Definition: rel.h:542
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void DeleteSharedSecurityLabel(Oid objectId, Oid classId)
Definition: seclabel.c:491
#define BTEqualStrategyNumber
Definition: stratnum.h:31
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:30
static char * password
Definition: streamutil.c:51
char * priv_name
Definition: parsenodes.h:2616
List * cols
Definition: parsenodes.h:2617
char * defname
Definition: parsenodes.h:826
ParseLoc location
Definition: parsenodes.h:830
Node * arg
Definition: parsenodes.h:827
unsigned specified
Definition: user.c:75
bool admin
Definition: user.c:76
bool set
Definition: user.c:78
bool inherit
Definition: user.c:77
ItemPointerData t_self
Definition: htup.h:65
Definition: pg_list.h:54
ParseLoc location
Definition: parsenodes.h:417
RoleSpecType roletype
Definition: parsenodes.h:415
char * rolename
Definition: parsenodes.h:416
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:180
int n_members
Definition: catcache.h:178
HeapTupleData tuple
Definition: catcache.h:123
Definition: type.h:96
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
bool superuser(void)
Definition: superuser.c:46
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:243
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:600
#define ReleaseSysCacheList(x)
Definition: syscache.h:134
#define SearchSysCacheList1(cacheId, key1)
Definition: syscache.h:127
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:100
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
static bool have_createrole_privilege(void)
Definition: user.c:123
ObjectAddress RenameRole(const char *oldname, const char *newname)
Definition: user.c:1334
#define GRANT_ROLE_SPECIFIED_ADMIN
Definition: user.c:81
static bool plan_single_revoke(CatCList *memlist, RevokeRoleGrantAction *actions, Oid member, Oid grantor, GrantRoleOptions *popt, DropBehavior behavior)
Definition: user.c:2332
static GrantRoleOptions createrole_self_grant_options
Definition: user.c:89
static void InitGrantRoleOptions(GrantRoleOptions *popt)
Definition: user.c:2516
static void plan_member_revoke(CatCList *memlist, RevokeRoleGrantAction *actions, Oid member)
Definition: user.c:2402
static void AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, Oid grantorId, GrantRoleOptions *popt)
Definition: user.c:1681
void ReassignOwnedObjects(ReassignOwnedStmt *stmt)
Definition: user.c:1611
Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
Definition: user.c:619
static bool createrole_self_grant_enabled
Definition: user.c:88
#define GRANT_ROLE_SPECIFIED_SET
Definition: user.c:83
Oid AlterRoleSet(AlterRoleSetStmt *stmt)
Definition: user.c:1000
static Oid check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId, bool is_grant)
Definition: user.c:2216
int Password_encryption
Definition: user.c:86
bool check_createrole_self_grant(char **newval, void **extra, GucSource source)
Definition: user.c:2528
void assign_createrole_self_grant(const char *newval, void *extra)
Definition: user.c:2581
static void check_role_membership_authorization(Oid currentUserId, Oid roleid, bool is_grant)
Definition: user.c:2122
Oid binary_upgrade_next_pg_authid_oid
Definition: user.c:71
#define GRANT_ROLE_SPECIFIED_INHERIT
Definition: user.c:82
void DropRole(DropRoleStmt *stmt)
Definition: user.c:1090
Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
Definition: user.c:133
void GrantRole(ParseState *pstate, GrantRoleStmt *stmt)
Definition: user.c:1480
List * roleSpecsToIds(List *memberNames)
Definition: user.c:1652
static void plan_recursive_revoke(CatCList *memlist, RevokeRoleGrantAction *actions, int index, bool revoke_admin_option_only, DropBehavior behavior)
Definition: user.c:2426
char * createrole_self_grant
Definition: user.c:87
check_password_hook_type check_password_hook
Definition: user.c:92
RevokeRoleGrantAction
Definition: user.c:62
@ RRG_REMOVE_SET_OPTION
Definition: user.c:66
@ RRG_NOOP
Definition: user.c:63
@ RRG_DELETE_GRANT
Definition: user.c:67
@ RRG_REMOVE_INHERIT_OPTION
Definition: user.c:65
@ RRG_REMOVE_ADMIN_OPTION
Definition: user.c:64
static RevokeRoleGrantAction * initialize_revoke_actions(CatCList *memlist)
Definition: user.c:2301
void DropOwnedObjects(DropOwnedStmt *stmt)
Definition: user.c:1583
static void DelRoleMems(Oid currentUserId, const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, Oid grantorId, GrantRoleOptions *popt, DropBehavior behavior)
Definition: user.c:1990
void(* check_password_hook_type)(const char *username, const char *shadow_pass, PasswordType password_type, Datum validuntil_time, bool validuntil_null)
Definition: user.h:25
#define boolVal(v)
Definition: value.h:81
#define intVal(v)
Definition: value.h:79
#define strVal(v)
Definition: value.h:82
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3525
void CommandCounterIncrement(void)
Definition: xact.c:1100