PostgreSQL Source Code  git master
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-2022, 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"
19 #include "catalog/binary_upgrade.h"
20 #include "catalog/catalog.h"
21 #include "catalog/dependency.h"
22 #include "catalog/indexing.h"
23 #include "catalog/objectaccess.h"
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 "libpq/crypt.h"
34 #include "miscadmin.h"
35 #include "storage/lmgr.h"
36 #include "utils/acl.h"
37 #include "utils/builtins.h"
38 #include "utils/catcache.h"
39 #include "utils/fmgroids.h"
40 #include "utils/syscache.h"
41 #include "utils/timestamp.h"
42 
43 /*
44  * Removing a role grant - or the admin option on it - might recurse to
45  * dependent grants. We use these values to reason about what would need to
46  * be done in such cases.
47  *
48  * RRG_NOOP indicates a grant that would not need to be altered by the
49  * operation.
50  *
51  * RRG_REMOVE_ADMIN_OPTION indicates a grant that would need to have
52  * admin_option set to false by the operation.
53  *
54  * Similarly, RRG_REMOVE_INHERIT_OPTION and RRG_REMOVE_SET_OPTION indicate
55  * grants that would need to have the corresponding options set to false.
56  *
57  * RRG_DELETE_GRANT indicates a grant that would need to be removed entirely
58  * by the operation.
59  */
60 typedef enum
61 {
68 
69 /* Potentially set by pg_upgrade_support functions */
71 
72 typedef struct
73 {
74  unsigned specified;
75  bool admin;
76  bool inherit;
77  bool set;
79 
80 #define GRANT_ROLE_SPECIFIED_ADMIN 0x0001
81 #define GRANT_ROLE_SPECIFIED_INHERIT 0x0002
82 #define GRANT_ROLE_SPECIFIED_SET 0x0004
83 
84 /* GUC parameter */
86 
87 /* Hook to check passwords in CreateRole() and AlterRole() */
89 
90 static void AddRoleMems(const char *rolename, Oid roleid,
91  List *memberSpecs, List *memberIds,
92  Oid grantorId, GrantRoleOptions *popt);
93 static void DelRoleMems(const char *rolename, Oid roleid,
94  List *memberSpecs, List *memberIds,
95  Oid grantorId, GrantRoleOptions *popt,
96  DropBehavior behavior);
97 static Oid check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId,
98  bool is_grant);
100 static bool plan_single_revoke(CatCList *memlist,
101  RevokeRoleGrantAction *actions,
102  Oid member, Oid grantor,
103  GrantRoleOptions *popt,
104  DropBehavior behavior);
105 static void plan_member_revoke(CatCList *memlist,
106  RevokeRoleGrantAction *actions, Oid member);
107 static void plan_recursive_revoke(CatCList *memlist,
108  RevokeRoleGrantAction *actions,
109  int index,
110  bool revoke_admin_option_only,
111  DropBehavior behavior);
112 static void InitGrantRoleOptions(GrantRoleOptions *popt);
113 
114 
115 /* Check if current user has createrole privileges */
116 static bool
118 {
120 }
121 
122 
123 /*
124  * CREATE ROLE
125  */
126 Oid
128 {
129  Relation pg_authid_rel;
130  TupleDesc pg_authid_dsc;
131  HeapTuple tuple;
132  Datum new_record[Natts_pg_authid] = {0};
133  bool new_record_nulls[Natts_pg_authid] = {0};
134  Oid roleid;
135  ListCell *item;
136  ListCell *option;
137  char *password = NULL; /* user password */
138  bool issuper = false; /* Make the user a superuser? */
139  bool inherit = true; /* Auto inherit privileges? */
140  bool createrole = false; /* Can this user create roles? */
141  bool createdb = false; /* Can the user create databases? */
142  bool canlogin = false; /* Can this user login? */
143  bool isreplication = false; /* Is this a replication role? */
144  bool bypassrls = false; /* Is this a row security enabled role? */
145  int connlimit = -1; /* maximum connections allowed */
146  List *addroleto = NIL; /* roles to make this a member of */
147  List *rolemembers = NIL; /* roles to be members of this role */
148  List *adminmembers = NIL; /* roles to be admins of this role */
149  char *validUntil = NULL; /* time the login is valid until */
150  Datum validUntil_datum; /* same, as timestamptz Datum */
151  bool validUntil_null;
152  DefElem *dpassword = NULL;
153  DefElem *dissuper = NULL;
154  DefElem *dinherit = NULL;
155  DefElem *dcreaterole = NULL;
156  DefElem *dcreatedb = NULL;
157  DefElem *dcanlogin = NULL;
158  DefElem *disreplication = NULL;
159  DefElem *dconnlimit = NULL;
160  DefElem *daddroleto = NULL;
161  DefElem *drolemembers = NULL;
162  DefElem *dadminmembers = NULL;
163  DefElem *dvalidUntil = NULL;
164  DefElem *dbypassRLS = NULL;
165  GrantRoleOptions popt;
166 
167  /* The defaults can vary depending on the original statement type */
168  switch (stmt->stmt_type)
169  {
170  case ROLESTMT_ROLE:
171  break;
172  case ROLESTMT_USER:
173  canlogin = true;
174  /* may eventually want inherit to default to false here */
175  break;
176  case ROLESTMT_GROUP:
177  break;
178  }
179 
180  /* Extract options from the statement node tree */
181  foreach(option, stmt->options)
182  {
183  DefElem *defel = (DefElem *) lfirst(option);
184 
185  if (strcmp(defel->defname, "password") == 0)
186  {
187  if (dpassword)
188  errorConflictingDefElem(defel, pstate);
189  dpassword = defel;
190  }
191  else if (strcmp(defel->defname, "sysid") == 0)
192  {
193  ereport(NOTICE,
194  (errmsg("SYSID can no longer be specified")));
195  }
196  else if (strcmp(defel->defname, "superuser") == 0)
197  {
198  if (dissuper)
199  errorConflictingDefElem(defel, pstate);
200  dissuper = defel;
201  }
202  else if (strcmp(defel->defname, "inherit") == 0)
203  {
204  if (dinherit)
205  errorConflictingDefElem(defel, pstate);
206  dinherit = defel;
207  }
208  else if (strcmp(defel->defname, "createrole") == 0)
209  {
210  if (dcreaterole)
211  errorConflictingDefElem(defel, pstate);
212  dcreaterole = defel;
213  }
214  else if (strcmp(defel->defname, "createdb") == 0)
215  {
216  if (dcreatedb)
217  errorConflictingDefElem(defel, pstate);
218  dcreatedb = defel;
219  }
220  else if (strcmp(defel->defname, "canlogin") == 0)
221  {
222  if (dcanlogin)
223  errorConflictingDefElem(defel, pstate);
224  dcanlogin = defel;
225  }
226  else if (strcmp(defel->defname, "isreplication") == 0)
227  {
228  if (disreplication)
229  errorConflictingDefElem(defel, pstate);
230  disreplication = defel;
231  }
232  else if (strcmp(defel->defname, "connectionlimit") == 0)
233  {
234  if (dconnlimit)
235  errorConflictingDefElem(defel, pstate);
236  dconnlimit = defel;
237  }
238  else if (strcmp(defel->defname, "addroleto") == 0)
239  {
240  if (daddroleto)
241  errorConflictingDefElem(defel, pstate);
242  daddroleto = defel;
243  }
244  else if (strcmp(defel->defname, "rolemembers") == 0)
245  {
246  if (drolemembers)
247  errorConflictingDefElem(defel, pstate);
248  drolemembers = defel;
249  }
250  else if (strcmp(defel->defname, "adminmembers") == 0)
251  {
252  if (dadminmembers)
253  errorConflictingDefElem(defel, pstate);
254  dadminmembers = defel;
255  }
256  else if (strcmp(defel->defname, "validUntil") == 0)
257  {
258  if (dvalidUntil)
259  errorConflictingDefElem(defel, pstate);
260  dvalidUntil = defel;
261  }
262  else if (strcmp(defel->defname, "bypassrls") == 0)
263  {
264  if (dbypassRLS)
265  errorConflictingDefElem(defel, pstate);
266  dbypassRLS = defel;
267  }
268  else
269  elog(ERROR, "option \"%s\" not recognized",
270  defel->defname);
271  }
272 
273  if (dpassword && dpassword->arg)
274  password = strVal(dpassword->arg);
275  if (dissuper)
276  issuper = boolVal(dissuper->arg);
277  if (dinherit)
278  inherit = boolVal(dinherit->arg);
279  if (dcreaterole)
280  createrole = boolVal(dcreaterole->arg);
281  if (dcreatedb)
282  createdb = boolVal(dcreatedb->arg);
283  if (dcanlogin)
284  canlogin = boolVal(dcanlogin->arg);
285  if (disreplication)
286  isreplication = boolVal(disreplication->arg);
287  if (dconnlimit)
288  {
289  connlimit = intVal(dconnlimit->arg);
290  if (connlimit < -1)
291  ereport(ERROR,
292  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
293  errmsg("invalid connection limit: %d", connlimit)));
294  }
295  if (daddroleto)
296  addroleto = (List *) daddroleto->arg;
297  if (drolemembers)
298  rolemembers = (List *) drolemembers->arg;
299  if (dadminmembers)
300  adminmembers = (List *) dadminmembers->arg;
301  if (dvalidUntil)
302  validUntil = strVal(dvalidUntil->arg);
303  if (dbypassRLS)
304  bypassrls = boolVal(dbypassRLS->arg);
305 
306  /* Check some permissions first */
307  if (issuper)
308  {
309  if (!superuser())
310  ereport(ERROR,
311  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
312  errmsg("must be superuser to create superusers")));
313  }
314  else if (isreplication)
315  {
316  if (!superuser())
317  ereport(ERROR,
318  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
319  errmsg("must be superuser to create replication users")));
320  }
321  else if (bypassrls)
322  {
323  if (!superuser())
324  ereport(ERROR,
325  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
326  errmsg("must be superuser to create bypassrls users")));
327  }
328  else
329  {
331  ereport(ERROR,
332  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
333  errmsg("permission denied to create role")));
334  }
335 
336  /*
337  * Check that the user is not trying to create a role in the reserved
338  * "pg_" namespace.
339  */
340  if (IsReservedName(stmt->role))
341  ereport(ERROR,
342  (errcode(ERRCODE_RESERVED_NAME),
343  errmsg("role name \"%s\" is reserved",
344  stmt->role),
345  errdetail("Role names starting with \"pg_\" are reserved.")));
346 
347  /*
348  * If built with appropriate switch, whine when regression-testing
349  * conventions for role names are violated.
350  */
351 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
352  if (strncmp(stmt->role, "regress_", 8) != 0)
353  elog(WARNING, "roles created by regression test cases should have names starting with \"regress_\"");
354 #endif
355 
356  /*
357  * Check the pg_authid relation to be certain the role doesn't already
358  * exist.
359  */
360  pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
361  pg_authid_dsc = RelationGetDescr(pg_authid_rel);
362 
363  if (OidIsValid(get_role_oid(stmt->role, true)))
364  ereport(ERROR,
366  errmsg("role \"%s\" already exists",
367  stmt->role)));
368 
369  /* Convert validuntil to internal form */
370  if (validUntil)
371  {
372  validUntil_datum = DirectFunctionCall3(timestamptz_in,
373  CStringGetDatum(validUntil),
375  Int32GetDatum(-1));
376  validUntil_null = false;
377  }
378  else
379  {
380  validUntil_datum = (Datum) 0;
381  validUntil_null = true;
382  }
383 
384  /*
385  * Call the password checking hook if there is one defined
386  */
388  (*check_password_hook) (stmt->role,
389  password,
391  validUntil_datum,
392  validUntil_null);
393 
394  /*
395  * Build a tuple to insert
396  */
397  new_record[Anum_pg_authid_rolname - 1] =
399  new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper);
400  new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit);
401  new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole);
402  new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb);
403  new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin);
404  new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication);
405  new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
406 
407  if (password)
408  {
409  char *shadow_pass;
410  const char *logdetail = NULL;
411 
412  /*
413  * Don't allow an empty password. Libpq treats an empty password the
414  * same as no password at all, and won't even try to authenticate. But
415  * other clients might, so allowing it would be confusing. By clearing
416  * the password when an empty string is specified, the account is
417  * consistently locked for all clients.
418  *
419  * Note that this only covers passwords stored in the database itself.
420  * There are also checks in the authentication code, to forbid an
421  * empty password from being used with authentication methods that
422  * fetch the password from an external system, like LDAP or PAM.
423  */
424  if (password[0] == '\0' ||
425  plain_crypt_verify(stmt->role, password, "", &logdetail) == STATUS_OK)
426  {
427  ereport(NOTICE,
428  (errmsg("empty string is not a valid password, clearing password")));
429  new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
430  }
431  else
432  {
433  /* Encrypt the password to the requested format. */
434  shadow_pass = encrypt_password(Password_encryption, stmt->role,
435  password);
436  new_record[Anum_pg_authid_rolpassword - 1] =
437  CStringGetTextDatum(shadow_pass);
438  }
439  }
440  else
441  new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
442 
443  new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
444  new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
445 
446  new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(bypassrls);
447 
448  /*
449  * pg_largeobject_metadata contains pg_authid.oid's, so we use the
450  * binary-upgrade override.
451  */
452  if (IsBinaryUpgrade)
453  {
455  ereport(ERROR,
456  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
457  errmsg("pg_authid OID value not set when in binary upgrade mode")));
458 
461  }
462  else
463  {
464  roleid = GetNewOidWithIndex(pg_authid_rel, AuthIdOidIndexId,
465  Anum_pg_authid_oid);
466  }
467 
468  new_record[Anum_pg_authid_oid - 1] = ObjectIdGetDatum(roleid);
469 
470  tuple = heap_form_tuple(pg_authid_dsc, new_record, new_record_nulls);
471 
472  /*
473  * Insert new record in the pg_authid table
474  */
475  CatalogTupleInsert(pg_authid_rel, tuple);
476 
477  /*
478  * Advance command counter so we can see new record; else tests in
479  * AddRoleMems may fail.
480  */
481  if (addroleto || adminmembers || rolemembers)
483 
484  /* Default grant. */
485  InitGrantRoleOptions(&popt);
486 
487  /*
488  * Add the new role to the specified existing roles.
489  */
490  if (addroleto)
491  {
492  RoleSpec *thisrole = makeNode(RoleSpec);
493  List *thisrole_list = list_make1(thisrole);
494  List *thisrole_oidlist = list_make1_oid(roleid);
495 
496  thisrole->roletype = ROLESPEC_CSTRING;
497  thisrole->rolename = stmt->role;
498  thisrole->location = -1;
499 
500  foreach(item, addroleto)
501  {
502  RoleSpec *oldrole = lfirst(item);
503  HeapTuple oldroletup = get_rolespec_tuple(oldrole);
504  Form_pg_authid oldroleform = (Form_pg_authid) GETSTRUCT(oldroletup);
505  Oid oldroleid = oldroleform->oid;
506  char *oldrolename = NameStr(oldroleform->rolname);
507 
508  AddRoleMems(oldrolename, oldroleid,
509  thisrole_list,
510  thisrole_oidlist,
511  InvalidOid, &popt);
512 
513  ReleaseSysCache(oldroletup);
514  }
515  }
516 
517  /*
518  * Add the specified members to this new role. adminmembers get the admin
519  * option, rolemembers don't.
520  */
521  AddRoleMems(stmt->role, roleid,
522  rolemembers, roleSpecsToIds(rolemembers),
523  InvalidOid, &popt);
525  popt.admin = true;
526  AddRoleMems(stmt->role, roleid,
527  adminmembers, roleSpecsToIds(adminmembers),
528  InvalidOid, &popt);
529 
530  /* Post creation hook for new role */
531  InvokeObjectPostCreateHook(AuthIdRelationId, roleid, 0);
532 
533  /*
534  * Close pg_authid, but keep lock till commit.
535  */
536  table_close(pg_authid_rel, NoLock);
537 
538  return roleid;
539 }
540 
541 
542 /*
543  * ALTER ROLE
544  *
545  * Note: the rolemembers option accepted here is intended to support the
546  * backwards-compatible ALTER GROUP syntax. Although it will work to say
547  * "ALTER ROLE role ROLE rolenames", we don't document it.
548  */
549 Oid
551 {
552  Datum new_record[Natts_pg_authid] = {0};
553  bool new_record_nulls[Natts_pg_authid] = {0};
554  bool new_record_repl[Natts_pg_authid] = {0};
555  Relation pg_authid_rel;
556  TupleDesc pg_authid_dsc;
557  HeapTuple tuple,
558  new_tuple;
559  Form_pg_authid authform;
560  ListCell *option;
561  char *rolename;
562  char *password = NULL; /* user password */
563  int connlimit = -1; /* maximum connections allowed */
564  char *validUntil = NULL; /* time the login is valid until */
565  Datum validUntil_datum; /* same, as timestamptz Datum */
566  bool validUntil_null;
567  DefElem *dpassword = NULL;
568  DefElem *dissuper = NULL;
569  DefElem *dinherit = NULL;
570  DefElem *dcreaterole = NULL;
571  DefElem *dcreatedb = NULL;
572  DefElem *dcanlogin = NULL;
573  DefElem *disreplication = NULL;
574  DefElem *dconnlimit = NULL;
575  DefElem *drolemembers = NULL;
576  DefElem *dvalidUntil = NULL;
577  DefElem *dbypassRLS = NULL;
578  Oid roleid;
579  GrantRoleOptions popt;
580 
582  _("Cannot alter reserved roles."));
583 
584  /* Extract options from the statement node tree */
585  foreach(option, stmt->options)
586  {
587  DefElem *defel = (DefElem *) lfirst(option);
588 
589  if (strcmp(defel->defname, "password") == 0)
590  {
591  if (dpassword)
592  errorConflictingDefElem(defel, pstate);
593  dpassword = defel;
594  }
595  else if (strcmp(defel->defname, "superuser") == 0)
596  {
597  if (dissuper)
598  errorConflictingDefElem(defel, pstate);
599  dissuper = defel;
600  }
601  else if (strcmp(defel->defname, "inherit") == 0)
602  {
603  if (dinherit)
604  errorConflictingDefElem(defel, pstate);
605  dinherit = defel;
606  }
607  else if (strcmp(defel->defname, "createrole") == 0)
608  {
609  if (dcreaterole)
610  errorConflictingDefElem(defel, pstate);
611  dcreaterole = defel;
612  }
613  else if (strcmp(defel->defname, "createdb") == 0)
614  {
615  if (dcreatedb)
616  errorConflictingDefElem(defel, pstate);
617  dcreatedb = defel;
618  }
619  else if (strcmp(defel->defname, "canlogin") == 0)
620  {
621  if (dcanlogin)
622  errorConflictingDefElem(defel, pstate);
623  dcanlogin = defel;
624  }
625  else if (strcmp(defel->defname, "isreplication") == 0)
626  {
627  if (disreplication)
628  errorConflictingDefElem(defel, pstate);
629  disreplication = defel;
630  }
631  else if (strcmp(defel->defname, "connectionlimit") == 0)
632  {
633  if (dconnlimit)
634  errorConflictingDefElem(defel, pstate);
635  dconnlimit = defel;
636  }
637  else if (strcmp(defel->defname, "rolemembers") == 0 &&
638  stmt->action != 0)
639  {
640  if (drolemembers)
641  errorConflictingDefElem(defel, pstate);
642  drolemembers = defel;
643  }
644  else if (strcmp(defel->defname, "validUntil") == 0)
645  {
646  if (dvalidUntil)
647  errorConflictingDefElem(defel, pstate);
648  dvalidUntil = defel;
649  }
650  else if (strcmp(defel->defname, "bypassrls") == 0)
651  {
652  if (dbypassRLS)
653  errorConflictingDefElem(defel, pstate);
654  dbypassRLS = defel;
655  }
656  else
657  elog(ERROR, "option \"%s\" not recognized",
658  defel->defname);
659  }
660 
661  if (dpassword && dpassword->arg)
662  password = strVal(dpassword->arg);
663  if (dconnlimit)
664  {
665  connlimit = intVal(dconnlimit->arg);
666  if (connlimit < -1)
667  ereport(ERROR,
668  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
669  errmsg("invalid connection limit: %d", connlimit)));
670  }
671  if (dvalidUntil)
672  validUntil = strVal(dvalidUntil->arg);
673 
674  /*
675  * Scan the pg_authid relation to be certain the user exists.
676  */
677  pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
678  pg_authid_dsc = RelationGetDescr(pg_authid_rel);
679 
680  tuple = get_rolespec_tuple(stmt->role);
681  authform = (Form_pg_authid) GETSTRUCT(tuple);
682  rolename = pstrdup(NameStr(authform->rolname));
683  roleid = authform->oid;
684 
685  /*
686  * To mess with a superuser or replication role in any way you gotta be
687  * superuser. We also insist on superuser to change the BYPASSRLS
688  * property. Otherwise, if you don't have createrole, you're only allowed
689  * to (1) change your own password or (2) add members to a role for which
690  * you have ADMIN OPTION.
691  */
692  if (authform->rolsuper || dissuper)
693  {
694  if (!superuser())
695  ereport(ERROR,
696  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
697  errmsg("must be superuser to alter superuser roles or change superuser attribute")));
698  }
699  else if (authform->rolreplication || disreplication)
700  {
701  if (!superuser())
702  ereport(ERROR,
703  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
704  errmsg("must be superuser to alter replication roles or change replication attribute")));
705  }
706  else if (dbypassRLS)
707  {
708  if (!superuser())
709  ereport(ERROR,
710  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
711  errmsg("must be superuser to change bypassrls attribute")));
712  }
713  else if (!have_createrole_privilege())
714  {
715  /* things you certainly can't do without CREATEROLE */
716  if (dinherit || dcreaterole || dcreatedb || dcanlogin || dconnlimit ||
717  dvalidUntil)
718  ereport(ERROR,
719  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
720  errmsg("permission denied")));
721 
722  /* without CREATEROLE, can only change your own password */
723  if (dpassword && roleid != GetUserId())
724  ereport(ERROR,
725  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
726  errmsg("must have CREATEROLE privilege to change another user's password")));
727 
728  /* without CREATEROLE, can only add members to roles you admin */
729  if (drolemembers && !is_admin_of_role(GetUserId(), roleid))
730  ereport(ERROR,
731  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
732  errmsg("must have admin option on role \"%s\" to add members",
733  rolename)));
734  }
735 
736  /* Convert validuntil to internal form */
737  if (dvalidUntil)
738  {
739  validUntil_datum = DirectFunctionCall3(timestamptz_in,
740  CStringGetDatum(validUntil),
742  Int32GetDatum(-1));
743  validUntil_null = false;
744  }
745  else
746  {
747  /* fetch existing setting in case hook needs it */
748  validUntil_datum = SysCacheGetAttr(AUTHNAME, tuple,
749  Anum_pg_authid_rolvaliduntil,
750  &validUntil_null);
751  }
752 
753  /*
754  * Call the password checking hook if there is one defined
755  */
757  (*check_password_hook) (rolename,
758  password,
760  validUntil_datum,
761  validUntil_null);
762 
763  /*
764  * Build an updated tuple, perusing the information just obtained
765  */
766 
767  /*
768  * issuper/createrole/etc
769  */
770  if (dissuper)
771  {
772  bool should_be_super = boolVal(dissuper->arg);
773 
774  if (!should_be_super && roleid == BOOTSTRAP_SUPERUSERID)
775  ereport(ERROR,
776  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
777  errmsg("permission denied: bootstrap user must be superuser")));
778 
779  new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(should_be_super);
780  new_record_repl[Anum_pg_authid_rolsuper - 1] = true;
781  }
782 
783  if (dinherit)
784  {
785  new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(boolVal(dinherit->arg));
786  new_record_repl[Anum_pg_authid_rolinherit - 1] = true;
787  }
788 
789  if (dcreaterole)
790  {
791  new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(boolVal(dcreaterole->arg));
792  new_record_repl[Anum_pg_authid_rolcreaterole - 1] = true;
793  }
794 
795  if (dcreatedb)
796  {
797  new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(boolVal(dcreatedb->arg));
798  new_record_repl[Anum_pg_authid_rolcreatedb - 1] = true;
799  }
800 
801  if (dcanlogin)
802  {
803  new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(boolVal(dcanlogin->arg));
804  new_record_repl[Anum_pg_authid_rolcanlogin - 1] = true;
805  }
806 
807  if (disreplication)
808  {
809  new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(boolVal(disreplication->arg));
810  new_record_repl[Anum_pg_authid_rolreplication - 1] = true;
811  }
812 
813  if (dconnlimit)
814  {
815  new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
816  new_record_repl[Anum_pg_authid_rolconnlimit - 1] = true;
817  }
818 
819  /* password */
820  if (password)
821  {
822  char *shadow_pass;
823  const char *logdetail = NULL;
824 
825  /* Like in CREATE USER, don't allow an empty password. */
826  if (password[0] == '\0' ||
827  plain_crypt_verify(rolename, password, "", &logdetail) == STATUS_OK)
828  {
829  ereport(NOTICE,
830  (errmsg("empty string is not a valid password, clearing password")));
831  new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
832  }
833  else
834  {
835  /* Encrypt the password to the requested format. */
836  shadow_pass = encrypt_password(Password_encryption, rolename,
837  password);
838  new_record[Anum_pg_authid_rolpassword - 1] =
839  CStringGetTextDatum(shadow_pass);
840  }
841  new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
842  }
843 
844  /* unset password */
845  if (dpassword && dpassword->arg == NULL)
846  {
847  new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
848  new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
849  }
850 
851  /* valid until */
852  new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
853  new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
854  new_record_repl[Anum_pg_authid_rolvaliduntil - 1] = true;
855 
856  if (dbypassRLS)
857  {
858  new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(boolVal(dbypassRLS->arg));
859  new_record_repl[Anum_pg_authid_rolbypassrls - 1] = true;
860  }
861 
862  new_tuple = heap_modify_tuple(tuple, pg_authid_dsc, new_record,
863  new_record_nulls, new_record_repl);
864  CatalogTupleUpdate(pg_authid_rel, &tuple->t_self, new_tuple);
865 
866  InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
867 
868  ReleaseSysCache(tuple);
869  heap_freetuple(new_tuple);
870 
871  InitGrantRoleOptions(&popt);
872 
873  /*
874  * Advance command counter so we can see new record; else tests in
875  * AddRoleMems may fail.
876  */
877  if (drolemembers)
878  {
879  List *rolemembers = (List *) drolemembers->arg;
880 
882 
883  if (stmt->action == +1) /* add members to role */
884  AddRoleMems(rolename, roleid,
885  rolemembers, roleSpecsToIds(rolemembers),
886  InvalidOid, &popt);
887  else if (stmt->action == -1) /* drop members from role */
888  DelRoleMems(rolename, roleid,
889  rolemembers, roleSpecsToIds(rolemembers),
890  InvalidOid, &popt, DROP_RESTRICT);
891  }
892 
893  /*
894  * Close pg_authid, but keep lock till commit.
895  */
896  table_close(pg_authid_rel, NoLock);
897 
898  return roleid;
899 }
900 
901 
902 /*
903  * ALTER ROLE ... SET
904  */
905 Oid
907 {
908  HeapTuple roletuple;
909  Form_pg_authid roleform;
910  Oid databaseid = InvalidOid;
911  Oid roleid = InvalidOid;
912 
913  if (stmt->role)
914  {
916  _("Cannot alter reserved roles."));
917 
918  roletuple = get_rolespec_tuple(stmt->role);
919  roleform = (Form_pg_authid) GETSTRUCT(roletuple);
920  roleid = roleform->oid;
921 
922  /*
923  * Obtain a lock on the role and make sure it didn't go away in the
924  * meantime.
925  */
926  shdepLockAndCheckObject(AuthIdRelationId, roleid);
927 
928  /*
929  * To mess with a superuser you gotta be superuser; else you need
930  * createrole, or just want to change your own settings
931  */
932  if (roleform->rolsuper)
933  {
934  if (!superuser())
935  ereport(ERROR,
936  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
937  errmsg("must be superuser to alter superusers")));
938  }
939  else
940  {
941  if (!have_createrole_privilege() && roleid != GetUserId())
942  ereport(ERROR,
943  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
944  errmsg("permission denied")));
945  }
946 
947  ReleaseSysCache(roletuple);
948  }
949 
950  /* look up and lock the database, if specified */
951  if (stmt->database != NULL)
952  {
953  databaseid = get_database_oid(stmt->database, false);
954  shdepLockAndCheckObject(DatabaseRelationId, databaseid);
955 
956  if (!stmt->role)
957  {
958  /*
959  * If no role is specified, then this is effectively the same as
960  * ALTER DATABASE ... SET, so use the same permission check.
961  */
962  if (!object_ownercheck(DatabaseRelationId, databaseid, GetUserId()))
964  stmt->database);
965  }
966  }
967 
968  if (!stmt->role && !stmt->database)
969  {
970  /* Must be superuser to alter settings globally. */
971  if (!superuser())
972  ereport(ERROR,
973  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
974  errmsg("must be superuser to alter settings globally")));
975  }
976 
977  AlterSetting(databaseid, roleid, stmt->setstmt);
978 
979  return roleid;
980 }
981 
982 
983 /*
984  * DROP ROLE
985  */
986 void
988 {
989  Relation pg_authid_rel,
990  pg_auth_members_rel;
991  ListCell *item;
992  List *role_addresses = NIL;
993 
995  ereport(ERROR,
996  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
997  errmsg("permission denied to drop role")));
998 
999  /*
1000  * Scan the pg_authid relation to find the Oid of the role(s) to be
1001  * deleted and perform preliminary permissions and sanity checks.
1002  */
1003  pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
1004  pg_auth_members_rel = table_open(AuthMemRelationId, RowExclusiveLock);
1005 
1006  foreach(item, stmt->roles)
1007  {
1008  RoleSpec *rolspec = lfirst(item);
1009  char *role;
1010  HeapTuple tuple,
1011  tmp_tuple;
1012  Form_pg_authid roleform;
1013  ScanKeyData scankey;
1014  SysScanDesc sscan;
1015  Oid roleid;
1016  ObjectAddress *role_address;
1017 
1018  if (rolspec->roletype != ROLESPEC_CSTRING)
1019  ereport(ERROR,
1020  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1021  errmsg("cannot use special role specifier in DROP ROLE")));
1022  role = rolspec->rolename;
1023 
1024  tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
1025  if (!HeapTupleIsValid(tuple))
1026  {
1027  if (!stmt->missing_ok)
1028  {
1029  ereport(ERROR,
1030  (errcode(ERRCODE_UNDEFINED_OBJECT),
1031  errmsg("role \"%s\" does not exist", role)));
1032  }
1033  else
1034  {
1035  ereport(NOTICE,
1036  (errmsg("role \"%s\" does not exist, skipping",
1037  role)));
1038  }
1039 
1040  continue;
1041  }
1042 
1043  roleform = (Form_pg_authid) GETSTRUCT(tuple);
1044  roleid = roleform->oid;
1045 
1046  if (roleid == GetUserId())
1047  ereport(ERROR,
1048  (errcode(ERRCODE_OBJECT_IN_USE),
1049  errmsg("current user cannot be dropped")));
1050  if (roleid == GetOuterUserId())
1051  ereport(ERROR,
1052  (errcode(ERRCODE_OBJECT_IN_USE),
1053  errmsg("current user cannot be dropped")));
1054  if (roleid == GetSessionUserId())
1055  ereport(ERROR,
1056  (errcode(ERRCODE_OBJECT_IN_USE),
1057  errmsg("session user cannot be dropped")));
1058 
1059  /*
1060  * For safety's sake, we allow createrole holders to drop ordinary
1061  * roles but not superuser roles. This is mainly to avoid the
1062  * scenario where you accidentally drop the last superuser.
1063  */
1064  if (roleform->rolsuper && !superuser())
1065  ereport(ERROR,
1066  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1067  errmsg("must be superuser to drop superusers")));
1068 
1069  /* DROP hook for the role being removed */
1070  InvokeObjectDropHook(AuthIdRelationId, roleid, 0);
1071 
1072  /* Don't leak the syscache tuple */
1073  ReleaseSysCache(tuple);
1074 
1075  /*
1076  * Lock the role, so nobody can add dependencies to her while we drop
1077  * her. We keep the lock until the end of transaction.
1078  */
1079  LockSharedObject(AuthIdRelationId, roleid, 0, AccessExclusiveLock);
1080 
1081  /*
1082  * If there is a pg_auth_members entry that has one of the roles to be
1083  * dropped as the roleid or member, it should be silently removed, but
1084  * if there is a pg_auth_members entry that has one of the roles to be
1085  * dropped as the grantor, the operation should fail.
1086  *
1087  * It's possible, however, that a single pg_auth_members entry could
1088  * fall into multiple categories - e.g. the user could do "GRANT foo
1089  * TO bar GRANTED BY baz" and then "DROP ROLE baz, bar". We want such
1090  * an operation to succeed regardless of the order in which the
1091  * to-be-dropped roles are passed to DROP ROLE.
1092  *
1093  * To make that work, we remove all pg_auth_members entries that can
1094  * be silently removed in this loop, and then below we'll make a
1095  * second pass over the list of roles to be removed and check for any
1096  * remaining dependencies.
1097  */
1098  ScanKeyInit(&scankey,
1099  Anum_pg_auth_members_roleid,
1100  BTEqualStrategyNumber, F_OIDEQ,
1101  ObjectIdGetDatum(roleid));
1102 
1103  sscan = systable_beginscan(pg_auth_members_rel, AuthMemRoleMemIndexId,
1104  true, NULL, 1, &scankey);
1105 
1106  while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
1107  {
1108  Form_pg_auth_members authmem_form;
1109 
1110  authmem_form = (Form_pg_auth_members) GETSTRUCT(tmp_tuple);
1111  deleteSharedDependencyRecordsFor(AuthMemRelationId,
1112  authmem_form->oid, 0);
1113  CatalogTupleDelete(pg_auth_members_rel, &tmp_tuple->t_self);
1114  }
1115 
1116  systable_endscan(sscan);
1117 
1118  ScanKeyInit(&scankey,
1119  Anum_pg_auth_members_member,
1120  BTEqualStrategyNumber, F_OIDEQ,
1121  ObjectIdGetDatum(roleid));
1122 
1123  sscan = systable_beginscan(pg_auth_members_rel, AuthMemMemRoleIndexId,
1124  true, NULL, 1, &scankey);
1125 
1126  while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
1127  {
1128  Form_pg_auth_members authmem_form;
1129 
1130  authmem_form = (Form_pg_auth_members) GETSTRUCT(tmp_tuple);
1131  deleteSharedDependencyRecordsFor(AuthMemRelationId,
1132  authmem_form->oid, 0);
1133  CatalogTupleDelete(pg_auth_members_rel, &tmp_tuple->t_self);
1134  }
1135 
1136  systable_endscan(sscan);
1137 
1138  /*
1139  * Advance command counter so that later iterations of this loop will
1140  * see the changes already made. This is essential if, for example,
1141  * we are trying to drop both a role and one of its direct members ---
1142  * we'll get an error if we try to delete the linking pg_auth_members
1143  * tuple twice. (We do not need a CCI between the two delete loops
1144  * above, because it's not allowed for a role to directly contain
1145  * itself.)
1146  */
1148 
1149  /* Looks tentatively OK, add it to the list. */
1150  role_address = palloc(sizeof(ObjectAddress));
1151  role_address->classId = AuthIdRelationId;
1152  role_address->objectId = roleid;
1153  role_address->objectSubId = 0;
1154  role_addresses = lappend(role_addresses, role_address);
1155  }
1156 
1157  /*
1158  * Second pass over the roles to be removed.
1159  */
1160  foreach(item, role_addresses)
1161  {
1162  ObjectAddress *role_address = lfirst(item);
1163  Oid roleid = role_address->objectId;
1164  HeapTuple tuple;
1165  Form_pg_authid roleform;
1166  char *detail;
1167  char *detail_log;
1168 
1169  /*
1170  * Re-find the pg_authid tuple.
1171  *
1172  * Since we've taken a lock on the role OID, it shouldn't be possible
1173  * for the tuple to have been deleted -- or for that matter updated --
1174  * unless the user is manually modifying the system catalogs.
1175  */
1176  tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
1177  if (!HeapTupleIsValid(tuple))
1178  elog(ERROR, "could not find tuple for role %u", roleid);
1179  roleform = (Form_pg_authid) GETSTRUCT(tuple);
1180 
1181  /*
1182  * Check for pg_shdepend entries depending on this role.
1183  *
1184  * This needs to happen after we've completed removing any
1185  * pg_auth_members entries that can be removed silently, in order to
1186  * avoid spurious failures. See notes above for more details.
1187  */
1188  if (checkSharedDependencies(AuthIdRelationId, roleid,
1189  &detail, &detail_log))
1190  ereport(ERROR,
1191  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1192  errmsg("role \"%s\" cannot be dropped because some objects depend on it",
1193  NameStr(roleform->rolname)),
1194  errdetail_internal("%s", detail),
1195  errdetail_log("%s", detail_log)));
1196 
1197  /*
1198  * Remove the role from the pg_authid table
1199  */
1200  CatalogTupleDelete(pg_authid_rel, &tuple->t_self);
1201 
1202  ReleaseSysCache(tuple);
1203 
1204  /*
1205  * Remove any comments or security labels on this role.
1206  */
1207  DeleteSharedComments(roleid, AuthIdRelationId);
1208  DeleteSharedSecurityLabel(roleid, AuthIdRelationId);
1209 
1210  /*
1211  * Remove settings for this role.
1212  */
1213  DropSetting(InvalidOid, roleid);
1214  }
1215 
1216  /*
1217  * Now we can clean up; but keep locks until commit.
1218  */
1219  table_close(pg_auth_members_rel, NoLock);
1220  table_close(pg_authid_rel, NoLock);
1221 }
1222 
1223 /*
1224  * Rename role
1225  */
1227 RenameRole(const char *oldname, const char *newname)
1228 {
1229  HeapTuple oldtuple,
1230  newtuple;
1231  TupleDesc dsc;
1232  Relation rel;
1233  Datum datum;
1234  bool isnull;
1235  Datum repl_val[Natts_pg_authid];
1236  bool repl_null[Natts_pg_authid];
1237  bool repl_repl[Natts_pg_authid];
1238  int i;
1239  Oid roleid;
1240  ObjectAddress address;
1241  Form_pg_authid authform;
1242 
1243  rel = table_open(AuthIdRelationId, RowExclusiveLock);
1244  dsc = RelationGetDescr(rel);
1245 
1246  oldtuple = SearchSysCache1(AUTHNAME, CStringGetDatum(oldname));
1247  if (!HeapTupleIsValid(oldtuple))
1248  ereport(ERROR,
1249  (errcode(ERRCODE_UNDEFINED_OBJECT),
1250  errmsg("role \"%s\" does not exist", oldname)));
1251 
1252  /*
1253  * XXX Client applications probably store the session user somewhere, so
1254  * renaming it could cause confusion. On the other hand, there may not be
1255  * an actual problem besides a little confusion, so think about this and
1256  * decide. Same for SET ROLE ... we don't restrict renaming the current
1257  * effective userid, though.
1258  */
1259 
1260  authform = (Form_pg_authid) GETSTRUCT(oldtuple);
1261  roleid = authform->oid;
1262 
1263  if (roleid == GetSessionUserId())
1264  ereport(ERROR,
1265  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1266  errmsg("session user cannot be renamed")));
1267  if (roleid == GetOuterUserId())
1268  ereport(ERROR,
1269  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1270  errmsg("current user cannot be renamed")));
1271 
1272  /*
1273  * Check that the user is not trying to rename a system role and not
1274  * trying to rename a role into the reserved "pg_" namespace.
1275  */
1276  if (IsReservedName(NameStr(authform->rolname)))
1277  ereport(ERROR,
1278  (errcode(ERRCODE_RESERVED_NAME),
1279  errmsg("role name \"%s\" is reserved",
1280  NameStr(authform->rolname)),
1281  errdetail("Role names starting with \"pg_\" are reserved.")));
1282 
1283  if (IsReservedName(newname))
1284  ereport(ERROR,
1285  (errcode(ERRCODE_RESERVED_NAME),
1286  errmsg("role name \"%s\" is reserved",
1287  newname),
1288  errdetail("Role names starting with \"pg_\" are reserved.")));
1289 
1290  /*
1291  * If built with appropriate switch, whine when regression-testing
1292  * conventions for role names are violated.
1293  */
1294 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
1295  if (strncmp(newname, "regress_", 8) != 0)
1296  elog(WARNING, "roles created by regression test cases should have names starting with \"regress_\"");
1297 #endif
1298 
1299  /* make sure the new name doesn't exist */
1301  ereport(ERROR,
1303  errmsg("role \"%s\" already exists", newname)));
1304 
1305  /*
1306  * createrole is enough privilege unless you want to mess with a superuser
1307  */
1308  if (((Form_pg_authid) GETSTRUCT(oldtuple))->rolsuper)
1309  {
1310  if (!superuser())
1311  ereport(ERROR,
1312  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1313  errmsg("must be superuser to rename superusers")));
1314  }
1315  else
1316  {
1318  ereport(ERROR,
1319  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1320  errmsg("permission denied to rename role")));
1321  }
1322 
1323  /* OK, construct the modified tuple */
1324  for (i = 0; i < Natts_pg_authid; i++)
1325  repl_repl[i] = false;
1326 
1327  repl_repl[Anum_pg_authid_rolname - 1] = true;
1328  repl_val[Anum_pg_authid_rolname - 1] = DirectFunctionCall1(namein,
1329  CStringGetDatum(newname));
1330  repl_null[Anum_pg_authid_rolname - 1] = false;
1331 
1332  datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull);
1333 
1334  if (!isnull && get_password_type(TextDatumGetCString(datum)) == PASSWORD_TYPE_MD5)
1335  {
1336  /* MD5 uses the username as salt, so just clear it on a rename */
1337  repl_repl[Anum_pg_authid_rolpassword - 1] = true;
1338  repl_null[Anum_pg_authid_rolpassword - 1] = true;
1339 
1340  ereport(NOTICE,
1341  (errmsg("MD5 password cleared because of role rename")));
1342  }
1343 
1344  newtuple = heap_modify_tuple(oldtuple, dsc, repl_val, repl_null, repl_repl);
1345  CatalogTupleUpdate(rel, &oldtuple->t_self, newtuple);
1346 
1347  InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
1348 
1349  ObjectAddressSet(address, AuthIdRelationId, roleid);
1350 
1351  ReleaseSysCache(oldtuple);
1352 
1353  /*
1354  * Close pg_authid, but keep lock till commit.
1355  */
1356  table_close(rel, NoLock);
1357 
1358  return address;
1359 }
1360 
1361 /*
1362  * GrantRoleStmt
1363  *
1364  * Grant/Revoke roles to/from roles
1365  */
1366 void
1368 {
1369  Relation pg_authid_rel;
1370  Oid grantor;
1371  List *grantee_ids;
1372  ListCell *item;
1373  GrantRoleOptions popt;
1374 
1375  /* Parse options list. */
1376  InitGrantRoleOptions(&popt);
1377  foreach(item, stmt->opt)
1378  {
1379  DefElem *opt = (DefElem *) lfirst(item);
1380  char *optval = defGetString(opt);
1381 
1382  if (strcmp(opt->defname, "admin") == 0)
1383  {
1385 
1386  if (parse_bool(optval, &popt.admin))
1387  continue;
1388  }
1389  else if (strcmp(opt->defname, "inherit") == 0)
1390  {
1392  if (parse_bool(optval, &popt.inherit))
1393  continue;
1394  }
1395  else if (strcmp(opt->defname, "set") == 0)
1396  {
1398  if (parse_bool(optval, &popt.set))
1399  continue;
1400  }
1401  else
1402  ereport(ERROR,
1403  errcode(ERRCODE_SYNTAX_ERROR),
1404  errmsg("unrecognized role option \"%s\"", opt->defname),
1405  parser_errposition(pstate, opt->location));
1406 
1407  ereport(ERROR,
1408  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1409  errmsg("unrecognized value for role option \"%s\": \"%s\"",
1410  opt->defname, optval),
1411  parser_errposition(pstate, opt->location)));
1412  }
1413 
1414  /* Lookup OID of grantor, if specified. */
1415  if (stmt->grantor)
1416  grantor = get_rolespec_oid(stmt->grantor, false);
1417  else
1418  grantor = InvalidOid;
1419 
1420  grantee_ids = roleSpecsToIds(stmt->grantee_roles);
1421 
1422  /* AccessShareLock is enough since we aren't modifying pg_authid */
1423  pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
1424 
1425  /*
1426  * Step through all of the granted roles and add, update, or remove
1427  * entries in pg_auth_members as appropriate. If stmt->is_grant is true,
1428  * we are adding new grants or, if they already exist, updating options
1429  * on those grants. If stmt->is_grant is false, we are revoking grants or
1430  * removing options from them.
1431  */
1432  foreach(item, stmt->granted_roles)
1433  {
1434  AccessPriv *priv = (AccessPriv *) lfirst(item);
1435  char *rolename = priv->priv_name;
1436  Oid roleid;
1437 
1438  /* Must reject priv(columns) and ALL PRIVILEGES(columns) */
1439  if (rolename == NULL || priv->cols != NIL)
1440  ereport(ERROR,
1441  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1442  errmsg("column names cannot be included in GRANT/REVOKE ROLE")));
1443 
1444  roleid = get_role_oid(rolename, false);
1445  if (stmt->is_grant)
1446  AddRoleMems(rolename, roleid,
1447  stmt->grantee_roles, grantee_ids,
1448  grantor, &popt);
1449  else
1450  DelRoleMems(rolename, roleid,
1451  stmt->grantee_roles, grantee_ids,
1452  grantor, &popt, stmt->behavior);
1453  }
1454 
1455  /*
1456  * Close pg_authid, but keep lock till commit.
1457  */
1458  table_close(pg_authid_rel, NoLock);
1459 }
1460 
1461 /*
1462  * DropOwnedObjects
1463  *
1464  * Drop the objects owned by a given list of roles.
1465  */
1466 void
1468 {
1469  List *role_ids = roleSpecsToIds(stmt->roles);
1470  ListCell *cell;
1471 
1472  /* Check privileges */
1473  foreach(cell, role_ids)
1474  {
1475  Oid roleid = lfirst_oid(cell);
1476 
1477  if (!has_privs_of_role(GetUserId(), roleid))
1478  ereport(ERROR,
1479  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1480  errmsg("permission denied to drop objects")));
1481  }
1482 
1483  /* Ok, do it */
1484  shdepDropOwned(role_ids, stmt->behavior);
1485 }
1486 
1487 /*
1488  * ReassignOwnedObjects
1489  *
1490  * Give the objects owned by a given list of roles away to another user.
1491  */
1492 void
1494 {
1495  List *role_ids = roleSpecsToIds(stmt->roles);
1496  ListCell *cell;
1497  Oid newrole;
1498 
1499  /* Check privileges */
1500  foreach(cell, role_ids)
1501  {
1502  Oid roleid = lfirst_oid(cell);
1503 
1504  if (!has_privs_of_role(GetUserId(), roleid))
1505  ereport(ERROR,
1506  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1507  errmsg("permission denied to reassign objects")));
1508  }
1509 
1510  /* Must have privileges on the receiving side too */
1511  newrole = get_rolespec_oid(stmt->newrole, false);
1512 
1513  if (!has_privs_of_role(GetUserId(), newrole))
1514  ereport(ERROR,
1515  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1516  errmsg("permission denied to reassign objects")));
1517 
1518  /* Ok, do it */
1519  shdepReassignOwned(role_ids, newrole);
1520 }
1521 
1522 /*
1523  * roleSpecsToIds
1524  *
1525  * Given a list of RoleSpecs, generate a list of role OIDs in the same order.
1526  *
1527  * ROLESPEC_PUBLIC is not allowed.
1528  */
1529 List *
1530 roleSpecsToIds(List *memberNames)
1531 {
1532  List *result = NIL;
1533  ListCell *l;
1534 
1535  foreach(l, memberNames)
1536  {
1537  RoleSpec *rolespec = lfirst_node(RoleSpec, l);
1538  Oid roleid;
1539 
1540  roleid = get_rolespec_oid(rolespec, false);
1541  result = lappend_oid(result, roleid);
1542  }
1543  return result;
1544 }
1545 
1546 /*
1547  * AddRoleMems -- Add given members to the specified role
1548  *
1549  * rolename: name of role to add to (used only for error messages)
1550  * roleid: OID of role to add to
1551  * memberSpecs: list of RoleSpec of roles to add (used only for error messages)
1552  * memberIds: OIDs of roles to add
1553  * grantorId: who is granting the membership (InvalidOid if not set explicitly)
1554  * popt: information about grant options
1555  */
1556 static void
1557 AddRoleMems(const char *rolename, Oid roleid,
1558  List *memberSpecs, List *memberIds,
1559  Oid grantorId, GrantRoleOptions *popt)
1560 {
1561  Relation pg_authmem_rel;
1562  TupleDesc pg_authmem_dsc;
1563  ListCell *specitem;
1564  ListCell *iditem;
1565  Oid currentUserId = GetUserId();
1566 
1567  Assert(list_length(memberSpecs) == list_length(memberIds));
1568 
1569  /* Skip permission check if nothing to do */
1570  if (!memberIds)
1571  return;
1572 
1573  /*
1574  * Check permissions: must have createrole or admin option on the role to
1575  * be changed. To mess with a superuser role, you gotta be superuser.
1576  */
1577  if (superuser_arg(roleid))
1578  {
1579  if (!superuser())
1580  ereport(ERROR,
1581  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1582  errmsg("must be superuser to alter superusers")));
1583  }
1584  else
1585  {
1586  if (!have_createrole_privilege() &&
1587  !is_admin_of_role(currentUserId, roleid))
1588  ereport(ERROR,
1589  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1590  errmsg("must have admin option on role \"%s\"",
1591  rolename)));
1592  }
1593 
1594  /*
1595  * The charter of pg_database_owner is to have exactly one, implicit,
1596  * situation-dependent member. There's no technical need for this
1597  * restriction. (One could lift it and take the further step of making
1598  * object_ownercheck(DatabaseRelationId, ...) equivalent to has_privs_of_role(roleid,
1599  * ROLE_PG_DATABASE_OWNER), in which case explicit, situation-independent
1600  * members could act as the owner of any database.)
1601  */
1602  if (roleid == ROLE_PG_DATABASE_OWNER)
1603  ereport(ERROR,
1604  errmsg("role \"%s\" cannot have explicit members", rolename));
1605 
1606  /* Validate grantor (and resolve implicit grantor if not specified). */
1607  grantorId = check_role_grantor(currentUserId, roleid, grantorId, true);
1608 
1609  pg_authmem_rel = table_open(AuthMemRelationId, RowExclusiveLock);
1610  pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
1611 
1612  /*
1613  * Only allow changes to this role by one backend at a time, so that we
1614  * can check integrity constraints like the lack of circular ADMIN OPTION
1615  * grants without fear of race conditions.
1616  */
1617  LockSharedObject(AuthIdRelationId, roleid, 0,
1619 
1620  /* Preliminary sanity checks. */
1621  forboth(specitem, memberSpecs, iditem, memberIds)
1622  {
1623  RoleSpec *memberRole = lfirst_node(RoleSpec, specitem);
1624  Oid memberid = lfirst_oid(iditem);
1625 
1626  /*
1627  * pg_database_owner is never a role member. Lifting this restriction
1628  * would require a policy decision about membership loops. One could
1629  * prevent loops, which would include making "ALTER DATABASE x OWNER
1630  * TO proposed_datdba" fail if is_member_of_role(pg_database_owner,
1631  * proposed_datdba). Hence, gaining a membership could reduce what a
1632  * role could do. Alternately, one could allow these memberships to
1633  * complete loops. A role could then have actual WITH ADMIN OPTION on
1634  * itself, prompting a decision about is_admin_of_role() treatment of
1635  * the case.
1636  *
1637  * Lifting this restriction also has policy implications for ownership
1638  * of shared objects (databases and tablespaces). We allow such
1639  * ownership, but we might find cause to ban it in the future.
1640  * Designing such a ban would more troublesome if the design had to
1641  * address pg_database_owner being a member of role FOO that owns a
1642  * shared object. (The effect of such ownership is that any owner of
1643  * another database can act as the owner of affected shared objects.)
1644  */
1645  if (memberid == ROLE_PG_DATABASE_OWNER)
1646  ereport(ERROR,
1647  errmsg("role \"%s\" cannot be a member of any role",
1648  get_rolespec_name(memberRole)));
1649 
1650  /*
1651  * Refuse creation of membership loops, including the trivial case
1652  * where a role is made a member of itself. We do this by checking to
1653  * see if the target role is already a member of the proposed member
1654  * role. We have to ignore possible superuserness, however, else we
1655  * could never grant membership in a superuser-privileged role.
1656  */
1657  if (is_member_of_role_nosuper(roleid, memberid))
1658  ereport(ERROR,
1659  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1660  errmsg("role \"%s\" is a member of role \"%s\"",
1661  rolename, get_rolespec_name(memberRole))));
1662  }
1663 
1664  /*
1665  * Disallow attempts to grant ADMIN OPTION back to a user who granted it
1666  * to you, similar to what check_circularity does for ACLs. We want the
1667  * chains of grants to remain acyclic, so that it's always possible to use
1668  * REVOKE .. CASCADE to clean up all grants that depend on the one being
1669  * revoked.
1670  *
1671  * NB: This check might look redundant with the check for membership loops
1672  * above, but it isn't. That's checking for role-member loop (e.g. A is a
1673  * member of B and B is a member of A) while this is checking for a
1674  * member-grantor loop (e.g. A gave ADMIN OPTION on X to B and now B, who
1675  * has no other source of ADMIN OPTION on X, tries to give ADMIN OPTION on
1676  * X back to A).
1677  */
1678  if (popt->admin && grantorId != BOOTSTRAP_SUPERUSERID)
1679  {
1680  CatCList *memlist;
1681  RevokeRoleGrantAction *actions;
1682  int i;
1683 
1684  /* Get the list of members for this role. */
1686  ObjectIdGetDatum(roleid));
1687 
1688  /*
1689  * Figure out what would happen if we removed all existing grants to
1690  * every role to which we've been asked to make a new grant.
1691  */
1692  actions = initialize_revoke_actions(memlist);
1693  foreach(iditem, memberIds)
1694  {
1695  Oid memberid = lfirst_oid(iditem);
1696 
1697  if (memberid == BOOTSTRAP_SUPERUSERID)
1698  ereport(ERROR,
1699  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1700  errmsg("admin option cannot be granted back to your own grantor")));
1701  plan_member_revoke(memlist, actions, memberid);
1702  }
1703 
1704  /*
1705  * If the result would be that the grantor role would no longer have
1706  * the ability to perform the grant, then the proposed grant would
1707  * create a circularity.
1708  */
1709  for (i = 0; i < memlist->n_members; ++i)
1710  {
1711  HeapTuple authmem_tuple;
1712  Form_pg_auth_members authmem_form;
1713 
1714  authmem_tuple = &memlist->members[i]->tuple;
1715  authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
1716 
1717  if (actions[i] == RRG_NOOP &&
1718  authmem_form->member == grantorId &&
1719  authmem_form->admin_option)
1720  break;
1721  }
1722  if (i >= memlist->n_members)
1723  ereport(ERROR,
1724  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1725  errmsg("admin option cannot be granted back to your own grantor")));
1726 
1727  ReleaseSysCacheList(memlist);
1728  }
1729 
1730  /* Now perform the catalog updates. */
1731  forboth(specitem, memberSpecs, iditem, memberIds)
1732  {
1733  RoleSpec *memberRole = lfirst_node(RoleSpec, specitem);
1734  Oid memberid = lfirst_oid(iditem);
1735  HeapTuple authmem_tuple;
1736  HeapTuple tuple;
1737  Datum new_record[Natts_pg_auth_members] = {0};
1738  bool new_record_nulls[Natts_pg_auth_members] = {0};
1739  bool new_record_repl[Natts_pg_auth_members] = {0};
1740 
1741  /* Common initialization for possible insert or update */
1742  new_record[Anum_pg_auth_members_roleid - 1] =
1743  ObjectIdGetDatum(roleid);
1744  new_record[Anum_pg_auth_members_member - 1] =
1745  ObjectIdGetDatum(memberid);
1746  new_record[Anum_pg_auth_members_grantor - 1] =
1747  ObjectIdGetDatum(grantorId);
1748 
1749  /* Find any existing tuple */
1750  authmem_tuple = SearchSysCache3(AUTHMEMROLEMEM,
1751  ObjectIdGetDatum(roleid),
1752  ObjectIdGetDatum(memberid),
1753  ObjectIdGetDatum(grantorId));
1754 
1755  /*
1756  * If we found a tuple, update it with new option values, unless
1757  * there are no changes, in which case issue a WARNING.
1758  *
1759  * If we didn't find a tuple, just insert one.
1760  */
1761  if (HeapTupleIsValid(authmem_tuple))
1762  {
1763  Form_pg_auth_members authmem_form;
1764  bool at_least_one_change = false;
1765 
1766  authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
1767 
1768  if ((popt->specified & GRANT_ROLE_SPECIFIED_ADMIN) != 0
1769  && authmem_form->admin_option != popt->admin)
1770  {
1771  new_record[Anum_pg_auth_members_admin_option - 1] =
1772  BoolGetDatum(popt->admin);
1773  new_record_repl[Anum_pg_auth_members_admin_option - 1] =
1774  true;
1775  at_least_one_change = true;
1776  }
1777 
1778  if ((popt->specified & GRANT_ROLE_SPECIFIED_INHERIT) != 0
1779  && authmem_form->inherit_option != popt->inherit)
1780  {
1781  new_record[Anum_pg_auth_members_inherit_option - 1] =
1782  BoolGetDatum(popt->inherit);
1783  new_record_repl[Anum_pg_auth_members_inherit_option - 1] =
1784  true;
1785  at_least_one_change = true;
1786  }
1787 
1788  if ((popt->specified & GRANT_ROLE_SPECIFIED_SET) != 0
1789  && authmem_form->set_option != popt->set)
1790  {
1791  new_record[Anum_pg_auth_members_set_option - 1] =
1792  BoolGetDatum(popt->set);
1793  new_record_repl[Anum_pg_auth_members_set_option - 1] =
1794  true;
1795  at_least_one_change = true;
1796  }
1797 
1798  if (!at_least_one_change)
1799  {
1800  ereport(NOTICE,
1801  (errmsg("role \"%s\" has already been granted membership in role \"%s\" by role \"%s\"",
1802  get_rolespec_name(memberRole), rolename,
1803  GetUserNameFromId(grantorId, false))));
1804  ReleaseSysCache(authmem_tuple);
1805  continue;
1806  }
1807 
1808  tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
1809  new_record,
1810  new_record_nulls, new_record_repl);
1811  CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple);
1812 
1813  ReleaseSysCache(authmem_tuple);
1814  }
1815  else
1816  {
1817  Oid objectId;
1818  Oid *newmembers = palloc(sizeof(Oid));
1819 
1820  /*
1821  * The values for these options can be taken directly from 'popt'.
1822  * Either they were specified, or the defaults as set by
1823  * InitGrantRoleOptions are correct.
1824  */
1825  new_record[Anum_pg_auth_members_admin_option - 1] =
1826  BoolGetDatum(popt->admin);
1827  new_record[Anum_pg_auth_members_set_option - 1] =
1828  BoolGetDatum(popt->set);
1829 
1830  /*
1831  * If the user specified a value for the inherit option, use
1832  * whatever was specified. Otherwise, set the default value based
1833  * on the role-level property.
1834  */
1835  if ((popt->specified & GRANT_ROLE_SPECIFIED_INHERIT) != 0)
1836  new_record[Anum_pg_auth_members_inherit_option - 1] =
1837  popt->inherit;
1838  else
1839  {
1840  HeapTuple mrtup;
1841  Form_pg_authid mrform;
1842 
1843  mrtup = SearchSysCache1(AUTHOID, memberid);
1844  if (!HeapTupleIsValid(mrtup))
1845  elog(ERROR, "cache lookup failed for role %u", memberid);
1846  mrform = (Form_pg_authid) GETSTRUCT(mrtup);
1847  new_record[Anum_pg_auth_members_inherit_option - 1] =
1848  mrform->rolinherit;
1849  ReleaseSysCache(mrtup);
1850  }
1851 
1852  /* get an OID for the new row and insert it */
1853  objectId = GetNewObjectId();
1854  new_record[Anum_pg_auth_members_oid - 1] = objectId;
1855  tuple = heap_form_tuple(pg_authmem_dsc,
1856  new_record, new_record_nulls);
1857  CatalogTupleInsert(pg_authmem_rel, tuple);
1858 
1859  /* updateAclDependencies wants to pfree array inputs */
1860  newmembers[0] = grantorId;
1861  updateAclDependencies(AuthMemRelationId, objectId,
1862  0, InvalidOid,
1863  0, NULL,
1864  1, newmembers);
1865  }
1866 
1867  /* CCI after each change, in case there are duplicates in list */
1869  }
1870 
1871  /*
1872  * Close pg_authmem, but keep lock till commit.
1873  */
1874  table_close(pg_authmem_rel, NoLock);
1875 }
1876 
1877 /*
1878  * DelRoleMems -- Remove given members from the specified role
1879  *
1880  * rolename: name of role to del from (used only for error messages)
1881  * roleid: OID of role to del from
1882  * memberSpecs: list of RoleSpec of roles to del (used only for error messages)
1883  * memberIds: OIDs of roles to del
1884  * grantorId: who is revoking the membership
1885  * popt: information about grant options
1886  * behavior: RESTRICT or CASCADE behavior for recursive removal
1887  */
1888 static void
1889 DelRoleMems(const char *rolename, Oid roleid,
1890  List *memberSpecs, List *memberIds,
1891  Oid grantorId, GrantRoleOptions *popt, DropBehavior behavior)
1892 {
1893  Relation pg_authmem_rel;
1894  TupleDesc pg_authmem_dsc;
1895  ListCell *specitem;
1896  ListCell *iditem;
1897  Oid currentUserId = GetUserId();
1898  CatCList *memlist;
1899  RevokeRoleGrantAction *actions;
1900  int i;
1901 
1902  Assert(list_length(memberSpecs) == list_length(memberIds));
1903 
1904  /* Skip permission check if nothing to do */
1905  if (!memberIds)
1906  return;
1907 
1908  /*
1909  * Check permissions: must have createrole or admin option on the role to
1910  * be changed. To mess with a superuser role, you gotta be superuser.
1911  */
1912  if (superuser_arg(roleid))
1913  {
1914  if (!superuser())
1915  ereport(ERROR,
1916  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1917  errmsg("must be superuser to alter superusers")));
1918  }
1919  else
1920  {
1921  if (!have_createrole_privilege() &&
1922  !is_admin_of_role(currentUserId, roleid))
1923  ereport(ERROR,
1924  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1925  errmsg("must have admin option on role \"%s\"",
1926  rolename)));
1927  }
1928 
1929  /* Validate grantor (and resolve implicit grantor if not specified). */
1930  grantorId = check_role_grantor(currentUserId, roleid, grantorId, false);
1931 
1932  pg_authmem_rel = table_open(AuthMemRelationId, RowExclusiveLock);
1933  pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
1934 
1935  /*
1936  * Only allow changes to this role by one backend at a time, so that we
1937  * can check for things like dependent privileges without fear of race
1938  * conditions.
1939  */
1940  LockSharedObject(AuthIdRelationId, roleid, 0,
1942 
1944  actions = initialize_revoke_actions(memlist);
1945 
1946  /*
1947  * We may need to recurse to dependent privileges if DROP_CASCADE was
1948  * specified, or refuse to perform the operation if dependent privileges
1949  * exist and DROP_RESTRICT was specified. plan_single_revoke() will figure
1950  * out what to do with each catalog tuple.
1951  */
1952  forboth(specitem, memberSpecs, iditem, memberIds)
1953  {
1954  RoleSpec *memberRole = lfirst(specitem);
1955  Oid memberid = lfirst_oid(iditem);
1956 
1957  if (!plan_single_revoke(memlist, actions, memberid, grantorId,
1958  popt, behavior))
1959  {
1960  ereport(WARNING,
1961  (errmsg("role \"%s\" has not been granted membership in role \"%s\" by role \"%s\"",
1962  get_rolespec_name(memberRole), rolename,
1963  GetUserNameFromId(grantorId, false))));
1964  continue;
1965  }
1966  }
1967 
1968  /*
1969  * We now know what to do with each catalog tuple: it should either be
1970  * left alone, deleted, or just have the admin_option flag cleared.
1971  * Perform the appropriate action in each case.
1972  */
1973  for (i = 0; i < memlist->n_members; ++i)
1974  {
1975  HeapTuple authmem_tuple;
1976  Form_pg_auth_members authmem_form;
1977 
1978  if (actions[i] == RRG_NOOP)
1979  continue;
1980 
1981  authmem_tuple = &memlist->members[i]->tuple;
1982  authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
1983 
1984  if (actions[i] == RRG_DELETE_GRANT)
1985  {
1986  /*
1987  * Remove the entry altogether, after first removing its
1988  * dependencies
1989  */
1990  deleteSharedDependencyRecordsFor(AuthMemRelationId,
1991  authmem_form->oid, 0);
1992  CatalogTupleDelete(pg_authmem_rel, &authmem_tuple->t_self);
1993  }
1994  else
1995  {
1996  /* Just turn off the specified option */
1997  HeapTuple tuple;
1998  Datum new_record[Natts_pg_auth_members] = {0};
1999  bool new_record_nulls[Natts_pg_auth_members] = {0};
2000  bool new_record_repl[Natts_pg_auth_members] = {0};
2001 
2002  /* Build a tuple to update with */
2003  if (actions[i] == RRG_REMOVE_ADMIN_OPTION)
2004  {
2005  new_record[Anum_pg_auth_members_admin_option - 1] =
2006  BoolGetDatum(false);
2007  new_record_repl[Anum_pg_auth_members_admin_option - 1] =
2008  true;
2009  }
2010  else if (actions[i] == RRG_REMOVE_INHERIT_OPTION)
2011  {
2012  new_record[Anum_pg_auth_members_inherit_option - 1] =
2013  BoolGetDatum(false);
2014  new_record_repl[Anum_pg_auth_members_inherit_option - 1] =
2015  true;
2016  }
2017  else if (actions[i] == RRG_REMOVE_SET_OPTION)
2018  {
2019  new_record[Anum_pg_auth_members_set_option - 1] =
2020  BoolGetDatum(false);
2021  new_record_repl[Anum_pg_auth_members_set_option - 1] =
2022  true;
2023  }
2024  else
2025  elog(ERROR, "unknown role revoke action");
2026 
2027  tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
2028  new_record,
2029  new_record_nulls, new_record_repl);
2030  CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple);
2031  }
2032  }
2033 
2034  ReleaseSysCacheList(memlist);
2035 
2036  /*
2037  * Close pg_authmem, but keep lock till commit.
2038  */
2039  table_close(pg_authmem_rel, NoLock);
2040 }
2041 
2042 /*
2043  * Sanity-check, or infer, the grantor for a GRANT or REVOKE statement
2044  * targeting a role.
2045  *
2046  * The grantor must always be either a role with ADMIN OPTION on the role in
2047  * which membership is being granted, or the bootstrap superuser. This is
2048  * similar to the restriction enforced by select_best_grantor, except that
2049  * roles don't have owners, so we regard the bootstrap superuser as the
2050  * implicit owner.
2051  *
2052  * If the grantor was not explicitly specified by the user, grantorId should
2053  * be passed as InvalidOid, and this function will infer the user to be
2054  * recorded as the grantor. In many cases, this will be the current user, but
2055  * things get more complicated when the current user doesn't possess ADMIN
2056  * OPTION on the role but rather relies on having CREATEROLE privileges, or
2057  * on inheriting the privileges of a role which does have ADMIN OPTION. See
2058  * below for details.
2059  *
2060  * If the grantor was specified by the user, then it must be a user that
2061  * can legally be recorded as the grantor, as per the rule stated above.
2062  * This is an integrity constraint, not a permissions check, and thus even
2063  * superusers are subject to this restriction. However, there is also a
2064  * permissions check: to specify a role as the grantor, the current user
2065  * must possess the privileges of that role. Superusers will always pass
2066  * this check, but for non-superusers it may lead to an error.
2067  *
2068  * The return value is the OID to be regarded as the grantor when executing
2069  * the operation.
2070  */
2071 static Oid
2072 check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId, bool is_grant)
2073 {
2074  /* If the grantor ID was not specified, pick one to use. */
2075  if (!OidIsValid(grantorId))
2076  {
2077  /*
2078  * Grants where the grantor is recorded as the bootstrap superuser do
2079  * not depend on any other existing grants, so always default to this
2080  * interpretation when possible.
2081  */
2082  if (has_createrole_privilege(currentUserId))
2083  return BOOTSTRAP_SUPERUSERID;
2084 
2085  /*
2086  * Otherwise, the grantor must either have ADMIN OPTION on the role or
2087  * inherit the privileges of a role which does. In the former case,
2088  * record the grantor as the current user; in the latter, pick one of
2089  * the roles that is "most directly" inherited by the current role
2090  * (i.e. fewest "hops").
2091  *
2092  * (We shouldn't fail to find a best grantor, because we've already
2093  * established that the current user has permission to perform the
2094  * operation.)
2095  */
2096  grantorId = select_best_admin(currentUserId, roleid);
2097  if (!OidIsValid(grantorId))
2098  elog(ERROR, "no possible grantors");
2099  return grantorId;
2100  }
2101 
2102  /*
2103  * If an explicit grantor is specified, it must be a role whose privileges
2104  * the current user possesses.
2105  *
2106  * It should also be a role that has ADMIN OPTION on the target role, but
2107  * we check this condition only in case of GRANT. For REVOKE, no matching
2108  * grant should exist anyway, but if it somehow does, let the user get rid
2109  * of it.
2110  */
2111  if (is_grant)
2112  {
2113  if (!has_privs_of_role(currentUserId, grantorId))
2114  ereport(ERROR,
2115  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2116  errmsg("permission denied to grant privileges as role \"%s\"",
2117  GetUserNameFromId(grantorId, false))));
2118 
2119  if (grantorId != BOOTSTRAP_SUPERUSERID &&
2120  select_best_admin(grantorId, roleid) != grantorId)
2121  ereport(ERROR,
2122  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2123  errmsg("grantor must have ADMIN OPTION on \"%s\"",
2124  GetUserNameFromId(roleid, false))));
2125  }
2126  else
2127  {
2128  if (!has_privs_of_role(currentUserId, grantorId))
2129  ereport(ERROR,
2130  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2131  errmsg("permission denied to revoke privileges granted by role \"%s\"",
2132  GetUserNameFromId(grantorId, false))));
2133  }
2134 
2135  /*
2136  * If a grantor was specified explicitly, always attribute the grant to
2137  * that role (unless we error out above).
2138  */
2139  return grantorId;
2140 }
2141 
2142 /*
2143  * Initialize an array of RevokeRoleGrantAction objects.
2144  *
2145  * 'memlist' should be a list of all grants for the target role.
2146  *
2147  * This constructs an array indicating that no actions are to be performed;
2148  * that is, every element is initially RRG_NOOP.
2149  */
2150 static RevokeRoleGrantAction *
2152 {
2153  RevokeRoleGrantAction *result;
2154  int i;
2155 
2156  if (memlist->n_members == 0)
2157  return NULL;
2158 
2159  result = palloc(sizeof(RevokeRoleGrantAction) * memlist->n_members);
2160  for (i = 0; i < memlist->n_members; i++)
2161  result[i] = RRG_NOOP;
2162  return result;
2163 }
2164 
2165 /*
2166  * Figure out what we would need to do in order to revoke a grant, or just the
2167  * admin option on a grant, given that there might be dependent privileges.
2168  *
2169  * 'memlist' should be a list of all grants for the target role.
2170  *
2171  * Whatever actions prove to be necessary will be signalled by updating
2172  * 'actions'.
2173  *
2174  * If behavior is DROP_RESTRICT, an error will occur if there are dependent
2175  * role membership grants; if DROP_CASCADE, those grants will be scheduled
2176  * for deletion.
2177  *
2178  * The return value is true if the matching grant was found in the list,
2179  * and false if not.
2180  */
2181 static bool
2183  Oid member, Oid grantor, GrantRoleOptions *popt,
2184  DropBehavior behavior)
2185 {
2186  int i;
2187 
2188  /*
2189  * If popt.specified == 0, we're revoking the grant entirely; otherwise,
2190  * we expect just one bit to be set, and we're revoking the corresponding
2191  * option. As of this writing, there's no syntax that would allow for
2192  * an attempt to revoke multiple options at once, and the logic below
2193  * wouldn't work properly if such syntax were added, so assert that our
2194  * caller isn't trying to do that.
2195  */
2196  Assert(pg_popcount32(popt->specified) <= 1);
2197 
2198  for (i = 0; i < memlist->n_members; ++i)
2199  {
2200  HeapTuple authmem_tuple;
2201  Form_pg_auth_members authmem_form;
2202 
2203  authmem_tuple = &memlist->members[i]->tuple;
2204  authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
2205 
2206  if (authmem_form->member == member &&
2207  authmem_form->grantor == grantor)
2208  {
2209  if ((popt->specified & GRANT_ROLE_SPECIFIED_INHERIT) != 0)
2210  {
2211  /*
2212  * Revoking the INHERIT option doesn't change anything for
2213  * dependent privileges, so we don't need to recurse.
2214  */
2215  actions[i] = RRG_REMOVE_INHERIT_OPTION;
2216  }
2217  else if ((popt->specified & GRANT_ROLE_SPECIFIED_SET) != 0)
2218  {
2219  /* Here too, no need to recurse. */
2220  actions[i] = RRG_REMOVE_SET_OPTION;
2221  }
2222  else
2223  {
2224  bool revoke_admin_option_only;
2225 
2226  /*
2227  * Revoking the grant entirely, or ADMIN option on a grant,
2228  * implicates dependent privileges, so we may need to recurse.
2229  */
2230  revoke_admin_option_only =
2231  (popt->specified & GRANT_ROLE_SPECIFIED_ADMIN) != 0;
2232  plan_recursive_revoke(memlist, actions, i,
2233  revoke_admin_option_only, behavior);
2234  }
2235  return true;
2236  }
2237  }
2238 
2239  return false;
2240 }
2241 
2242 /*
2243  * Figure out what we would need to do in order to revoke all grants to
2244  * a given member, given that there might be dependent privileges.
2245  *
2246  * 'memlist' should be a list of all grants for the target role.
2247  *
2248  * Whatever actions prove to be necessary will be signalled by updating
2249  * 'actions'.
2250  */
2251 static void
2253  Oid member)
2254 {
2255  int i;
2256 
2257  for (i = 0; i < memlist->n_members; ++i)
2258  {
2259  HeapTuple authmem_tuple;
2260  Form_pg_auth_members authmem_form;
2261 
2262  authmem_tuple = &memlist->members[i]->tuple;
2263  authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
2264 
2265  if (authmem_form->member == member)
2266  plan_recursive_revoke(memlist, actions, i, false, DROP_CASCADE);
2267  }
2268 }
2269 
2270 /*
2271  * Workhorse for figuring out recursive revocation of role grants.
2272  *
2273  * This is similar to what recursive_revoke() does for ACLs.
2274  */
2275 static void
2277  int index,
2278  bool revoke_admin_option_only, DropBehavior behavior)
2279 {
2280  bool would_still_have_admin_option = false;
2281  HeapTuple authmem_tuple;
2282  Form_pg_auth_members authmem_form;
2283  int i;
2284 
2285  /* If it's already been done, we can just return. */
2286  if (actions[index] == RRG_DELETE_GRANT)
2287  return;
2288  if (actions[index] == RRG_REMOVE_ADMIN_OPTION &&
2289  revoke_admin_option_only)
2290  return;
2291 
2292  /* Locate tuple data. */
2293  authmem_tuple = &memlist->members[index]->tuple;
2294  authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
2295 
2296  /*
2297  * If the existing tuple does not have admin_option set, then we do not
2298  * need to recurse. If we're just supposed to clear that bit we don't need
2299  * to do anything at all; if we're supposed to remove the grant, we need
2300  * to do something, but only to the tuple, and not any others.
2301  */
2302  if (!revoke_admin_option_only)
2303  {
2304  actions[index] = RRG_DELETE_GRANT;
2305  if (!authmem_form->admin_option)
2306  return;
2307  }
2308  else
2309  {
2310  if (!authmem_form->admin_option)
2311  return;
2312  actions[index] = RRG_REMOVE_ADMIN_OPTION;
2313  }
2314 
2315  /* Determine whether the member would still have ADMIN OPTION. */
2316  for (i = 0; i < memlist->n_members; ++i)
2317  {
2318  HeapTuple am_cascade_tuple;
2319  Form_pg_auth_members am_cascade_form;
2320 
2321  am_cascade_tuple = &memlist->members[i]->tuple;
2322  am_cascade_form = (Form_pg_auth_members) GETSTRUCT(am_cascade_tuple);
2323 
2324  if (am_cascade_form->member == authmem_form->member &&
2325  am_cascade_form->admin_option && actions[i] == RRG_NOOP)
2326  {
2327  would_still_have_admin_option = true;
2328  break;
2329  }
2330  }
2331 
2332  /* If the member would still have ADMIN OPTION, we need not recurse. */
2333  if (would_still_have_admin_option)
2334  return;
2335 
2336  /*
2337  * Recurse to grants that are not yet slated for deletion which have this
2338  * member as the grantor.
2339  */
2340  for (i = 0; i < memlist->n_members; ++i)
2341  {
2342  HeapTuple am_cascade_tuple;
2343  Form_pg_auth_members am_cascade_form;
2344 
2345  am_cascade_tuple = &memlist->members[i]->tuple;
2346  am_cascade_form = (Form_pg_auth_members) GETSTRUCT(am_cascade_tuple);
2347 
2348  if (am_cascade_form->grantor == authmem_form->member &&
2349  actions[i] != RRG_DELETE_GRANT)
2350  {
2351  if (behavior == DROP_RESTRICT)
2352  ereport(ERROR,
2353  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
2354  errmsg("dependent privileges exist"),
2355  errhint("Use CASCADE to revoke them too.")));
2356 
2357  plan_recursive_revoke(memlist, actions, i, false, behavior);
2358  }
2359  }
2360 }
2361 
2362 /*
2363  * Initialize a GrantRoleOptions object with default values.
2364  */
2365 static void
2367 {
2368  popt->specified = 0;
2369  popt->admin = false;
2370  popt->inherit = false;
2371  popt->set = true;
2372 }
bool is_admin_of_role(Oid member, Oid role)
Definition: acl.c:5079
char * get_rolespec_name(const RoleSpec *role)
Definition: acl.c:5354
Oid select_best_admin(Oid member, Oid role)
Definition: acl.c:5104
bool is_member_of_role_nosuper(Oid member, Oid role)
Definition: acl.c:5057
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4949
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5235
void check_rolespec_name(const RoleSpec *role, const char *detail_msg)
Definition: acl.c:5376
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5269
HeapTuple get_rolespec_tuple(const RoleSpec *role)
Definition: acl.c:5308
@ ACLCHECK_NOT_OWNER
Definition: acl.h:186
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3485
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:4799
bool has_createrole_privilege(Oid roleid)
Definition: aclchk.c:4880
Datum timestamptz_in(PG_FUNCTION_ARGS)
Definition: timestamp.c:403
bool parse_bool(const char *value, bool *result)
Definition: bool.c:30
#define CStringGetTextDatum(s)
Definition: builtins.h:85
#define TextDatumGetCString(d)
Definition: builtins.h:86
#define NameStr(name)
Definition: c.h:682
#define STATUS_OK
Definition: c.h:1108
#define OidIsValid(objectId)
Definition: c.h:711
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:393
bool IsReservedName(const char *name)
Definition: catalog.c:219
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:221
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:89
char * encrypt_password(PasswordType target_type, const char *role, const char *password)
Definition: crypt.c:114
@ PASSWORD_TYPE_SCRAM_SHA_256
Definition: crypt.h:31
@ PASSWORD_TYPE_MD5
Definition: crypt.h:30
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:2934
Oid createdb(ParseState *pstate, const CreatedbStmt *stmt)
Definition: dbcommands.c:671
char * defGetString(DefElem *def)
Definition: define.c:49
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:385
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1066
int errdetail(const char *fmt,...)
Definition: elog.c:1039
int errhint(const char *fmt,...)
Definition: elog.c:1153
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
int errdetail_log(const char *fmt,...)
Definition: elog.c:1087
#define _(x)
Definition: elog.c:90
#define WARNING
Definition: elog.h:32
#define ERROR
Definition: elog.h:35
#define NOTICE
Definition: elog.h:31
#define ereport(elevel,...)
Definition: elog.h:145
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:646
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:599
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:506
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
bool IsBinaryUpgrade
Definition: globals.c:114
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:788
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
int i
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:338
List * lappend_oid(List *list, Oid datum)
Definition: list.c:374
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1046
#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:1483
void * palloc(Size size)
Definition: mcxt.c:1199
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition: miscinit.c:967
Oid GetOuterUserId(void)
Definition: miscinit.c:508
Oid GetUserId(void)
Definition: miscinit.c:497
Oid GetSessionUserId(void)
Definition: miscinit.c:531
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
#define makeNode(_type_)
Definition: nodes.h:165
#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 parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:110
@ ROLESPEC_CSTRING
Definition: parsenodes.h:359
DropBehavior
Definition: parsenodes.h:1934
@ DROP_CASCADE
Definition: parsenodes.h:1936
@ DROP_RESTRICT
Definition: parsenodes.h:1935
@ OBJECT_DATABASE
Definition: parsenodes.h:1871
@ ROLESTMT_ROLE
Definition: parsenodes.h:2693
@ ROLESTMT_USER
Definition: parsenodes.h:2694
@ ROLESTMT_GROUP
Definition: parsenodes.h:2695
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:278
void DropSetting(Oid databaseid, Oid roleid)
void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
#define lfirst(lc)
Definition: pg_list.h:170
#define lfirst_node(type, lc)
Definition: pg_list.h:174
static int list_length(const List *l)
Definition: pg_list.h:150
#define NIL
Definition: pg_list.h:66
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:465
#define list_make1_oid(x1)
Definition: pg_list.h:240
#define list_make1(x1)
Definition: pg_list.h:210
#define lfirst_oid(lc)
Definition: pg_list.h:172
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:1002
void updateAclDependencies(Oid classId, Oid objectId, int32 objsubId, Oid ownerId, int noldmembers, Oid *oldmembers, int nnewmembers, Oid *newmembers)
Definition: pg_shdepend.c:482
bool checkSharedDependencies(Oid classId, Oid objectId, char **detail_msg, char **detail_log_msg)
Definition: pg_shdepend.c:631
void shdepDropOwned(List *roleids, DropBehavior behavior)
Definition: pg_shdepend.c:1295
void shdepLockAndCheckObject(Oid classId, Oid objectId)
Definition: pg_shdepend.c:1166
void shdepReassignOwned(List *roleids, Oid newrole)
Definition: pg_shdepend.c:1467
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:670
uintptr_t Datum
Definition: postgres.h:412
static Datum BoolGetDatum(bool X)
Definition: postgres.h:450
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:600
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:698
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:560
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetDescr(relation)
Definition: rel.h:527
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:32
static char * password
Definition: streamutil.c:53
char * priv_name
Definition: parsenodes.h:2151
List * cols
Definition: parsenodes.h:2152
RoleSpec * role
Definition: parsenodes.h:2717
VariableSetStmt * setstmt
Definition: parsenodes.h:2719
List * options
Definition: parsenodes.h:2710
RoleSpec * role
Definition: parsenodes.h:2709
RoleStmtType stmt_type
Definition: parsenodes.h:2701
char * defname
Definition: parsenodes.h:777
int location
Definition: parsenodes.h:781
Node * arg
Definition: parsenodes.h:778
DropBehavior behavior
Definition: parsenodes.h:3678
List * roles
Definition: parsenodes.h:2725
unsigned specified
Definition: user.c:74
bool admin
Definition: user.c:75
bool set
Definition: user.c:77
bool inherit
Definition: user.c:76
DropBehavior behavior
Definition: parsenodes.h:2172
RoleSpec * grantor
Definition: parsenodes.h:2171
List * grantee_roles
Definition: parsenodes.h:2168
List * granted_roles
Definition: parsenodes.h:2167
ItemPointerData t_self
Definition: htup.h:65
Definition: pg_list.h:52
RoleSpec * newrole
Definition: parsenodes.h:3688
RoleSpecType roletype
Definition: parsenodes.h:369
int location
Definition: parsenodes.h:371
char * rolename
Definition: parsenodes.h:370
CatCTup * members[FLEXIBLE_ARRAY_MEMBER]
Definition: catcache.h:178
int n_members
Definition: catcache.h:176
HeapTupleData tuple
Definition: catcache.h:121
Definition: type.h:95
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
bool superuser(void)
Definition: superuser.c:46
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1221
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173
HeapTuple SearchSysCache3(int cacheId, Datum key1, Datum key2, Datum key3)
Definition: syscache.c:1195
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1434
@ AUTHOID
Definition: syscache.h:45
@ AUTHNAME
Definition: syscache.h:44
@ AUTHMEMROLEMEM
Definition: syscache.h:43
#define ReleaseSysCacheList(x)
Definition: syscache.h:222
#define SearchSysCacheList1(cacheId, key1)
Definition: syscache.h:215
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:188
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:117
ObjectAddress RenameRole(const char *oldname, const char *newname)
Definition: user.c:1227
#define GRANT_ROLE_SPECIFIED_ADMIN
Definition: user.c:80
static bool plan_single_revoke(CatCList *memlist, RevokeRoleGrantAction *actions, Oid member, Oid grantor, GrantRoleOptions *popt, DropBehavior behavior)
Definition: user.c:2182
static void InitGrantRoleOptions(GrantRoleOptions *popt)
Definition: user.c:2366
static void plan_member_revoke(CatCList *memlist, RevokeRoleGrantAction *actions, Oid member)
Definition: user.c:2252
void ReassignOwnedObjects(ReassignOwnedStmt *stmt)
Definition: user.c:1493
Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
Definition: user.c:550
#define GRANT_ROLE_SPECIFIED_SET
Definition: user.c:82
Oid AlterRoleSet(AlterRoleSetStmt *stmt)
Definition: user.c:906
static Oid check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId, bool is_grant)
Definition: user.c:2072
int Password_encryption
Definition: user.c:85
Oid binary_upgrade_next_pg_authid_oid
Definition: user.c:70
#define GRANT_ROLE_SPECIFIED_INHERIT
Definition: user.c:81
void DropRole(DropRoleStmt *stmt)
Definition: user.c:987
Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
Definition: user.c:127
void GrantRole(ParseState *pstate, GrantRoleStmt *stmt)
Definition: user.c:1367
static void plan_recursive_revoke(CatCList *memlist, RevokeRoleGrantAction *actions, int index, bool revoke_admin_option_only, DropBehavior behavior)
Definition: user.c:2276
List * roleSpecsToIds(List *memberNames)
Definition: user.c:1530
check_password_hook_type check_password_hook
Definition: user.c:88
static void AddRoleMems(const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, Oid grantorId, GrantRoleOptions *popt)
Definition: user.c:1557
RevokeRoleGrantAction
Definition: user.c:61
@ RRG_REMOVE_SET_OPTION
Definition: user.c:65
@ RRG_NOOP
Definition: user.c:62
@ RRG_DELETE_GRANT
Definition: user.c:66
@ RRG_REMOVE_INHERIT_OPTION
Definition: user.c:64
@ RRG_REMOVE_ADMIN_OPTION
Definition: user.c:63
static RevokeRoleGrantAction * initialize_revoke_actions(CatCList *memlist)
Definition: user.c:2151
static void DelRoleMems(const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, Oid grantorId, GrantRoleOptions *popt, DropBehavior behavior)
Definition: user.c:1889
void DropOwnedObjects(DropOwnedStmt *stmt)
Definition: user.c:1467
void(* check_password_hook_type)(const char *username, const char *shadow_pass, PasswordType password_type, Datum validuntil_time, bool validuntil_null)
Definition: user.h:23
#define boolVal(v)
Definition: value.h:81
#define intVal(v)
Definition: value.h:79
#define strVal(v)
Definition: value.h:82
Oid GetNewObjectId(void)
Definition: varsup.c:528
void CommandCounterIncrement(void)
Definition: xact.c:1077