PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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-2017, 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/heapam.h"
17 #include "access/htup_details.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/seclabel.h"
31 #include "commands/user.h"
32 #include "libpq/crypt.h"
33 #include "miscadmin.h"
34 #include "storage/lmgr.h"
35 #include "utils/acl.h"
36 #include "utils/builtins.h"
37 #include "utils/fmgroids.h"
38 #include "utils/syscache.h"
39 #include "utils/timestamp.h"
40 #include "utils/tqual.h"
41 
42 /* Potentially set by pg_upgrade_support functions */
44 
45 
46 /* GUC parameter */
48 
49 /* Hook to check passwords in CreateRole() and AlterRole() */
51 
52 static void AddRoleMems(const char *rolename, Oid roleid,
53  List *memberSpecs, List *memberIds,
54  Oid grantorId, bool admin_opt);
55 static void DelRoleMems(const char *rolename, Oid roleid,
56  List *memberSpecs, List *memberIds,
57  bool admin_opt);
58 
59 
60 /* Check if current user has createrole privileges */
61 static bool
63 {
65 }
66 
67 
68 /*
69  * CREATE ROLE
70  */
71 Oid
73 {
74  Relation pg_authid_rel;
75  TupleDesc pg_authid_dsc;
76  HeapTuple tuple;
77  Datum new_record[Natts_pg_authid];
78  bool new_record_nulls[Natts_pg_authid];
79  Oid roleid;
80  ListCell *item;
82  char *password = NULL; /* user password */
83  bool issuper = false; /* Make the user a superuser? */
84  bool inherit = true; /* Auto inherit privileges? */
85  bool createrole = false; /* Can this user create roles? */
86  bool createdb = false; /* Can the user create databases? */
87  bool canlogin = false; /* Can this user login? */
88  bool isreplication = false; /* Is this a replication role? */
89  bool bypassrls = false; /* Is this a row security enabled
90  * role? */
91  int connlimit = -1; /* maximum connections allowed */
92  List *addroleto = NIL; /* roles to make this a member of */
93  List *rolemembers = NIL; /* roles to be members of this role */
94  List *adminmembers = NIL; /* roles to be admins of this role */
95  char *validUntil = NULL; /* time the login is valid until */
96  Datum validUntil_datum; /* same, as timestamptz Datum */
97  bool validUntil_null;
98  DefElem *dpassword = NULL;
99  DefElem *dissuper = NULL;
100  DefElem *dinherit = NULL;
101  DefElem *dcreaterole = NULL;
102  DefElem *dcreatedb = NULL;
103  DefElem *dcanlogin = NULL;
104  DefElem *disreplication = NULL;
105  DefElem *dconnlimit = NULL;
106  DefElem *daddroleto = NULL;
107  DefElem *drolemembers = NULL;
108  DefElem *dadminmembers = NULL;
109  DefElem *dvalidUntil = NULL;
110  DefElem *dbypassRLS = NULL;
111 
112  /* The defaults can vary depending on the original statement type */
113  switch (stmt->stmt_type)
114  {
115  case ROLESTMT_ROLE:
116  break;
117  case ROLESTMT_USER:
118  canlogin = true;
119  /* may eventually want inherit to default to false here */
120  break;
121  case ROLESTMT_GROUP:
122  break;
123  }
124 
125  /* Extract options from the statement node tree */
126  foreach(option, stmt->options)
127  {
128  DefElem *defel = (DefElem *) lfirst(option);
129 
130  if (strcmp(defel->defname, "password") == 0)
131  {
132  if (dpassword)
133  ereport(ERROR,
134  (errcode(ERRCODE_SYNTAX_ERROR),
135  errmsg("conflicting or redundant options"),
136  parser_errposition(pstate, defel->location)));
137  dpassword = defel;
138  }
139  else if (strcmp(defel->defname, "sysid") == 0)
140  {
141  ereport(NOTICE,
142  (errmsg("SYSID can no longer be specified")));
143  }
144  else if (strcmp(defel->defname, "superuser") == 0)
145  {
146  if (dissuper)
147  ereport(ERROR,
148  (errcode(ERRCODE_SYNTAX_ERROR),
149  errmsg("conflicting or redundant options"),
150  parser_errposition(pstate, defel->location)));
151  dissuper = defel;
152  }
153  else if (strcmp(defel->defname, "inherit") == 0)
154  {
155  if (dinherit)
156  ereport(ERROR,
157  (errcode(ERRCODE_SYNTAX_ERROR),
158  errmsg("conflicting or redundant options"),
159  parser_errposition(pstate, defel->location)));
160  dinherit = defel;
161  }
162  else if (strcmp(defel->defname, "createrole") == 0)
163  {
164  if (dcreaterole)
165  ereport(ERROR,
166  (errcode(ERRCODE_SYNTAX_ERROR),
167  errmsg("conflicting or redundant options"),
168  parser_errposition(pstate, defel->location)));
169  dcreaterole = defel;
170  }
171  else if (strcmp(defel->defname, "createdb") == 0)
172  {
173  if (dcreatedb)
174  ereport(ERROR,
175  (errcode(ERRCODE_SYNTAX_ERROR),
176  errmsg("conflicting or redundant options"),
177  parser_errposition(pstate, defel->location)));
178  dcreatedb = defel;
179  }
180  else if (strcmp(defel->defname, "canlogin") == 0)
181  {
182  if (dcanlogin)
183  ereport(ERROR,
184  (errcode(ERRCODE_SYNTAX_ERROR),
185  errmsg("conflicting or redundant options"),
186  parser_errposition(pstate, defel->location)));
187  dcanlogin = defel;
188  }
189  else if (strcmp(defel->defname, "isreplication") == 0)
190  {
191  if (disreplication)
192  ereport(ERROR,
193  (errcode(ERRCODE_SYNTAX_ERROR),
194  errmsg("conflicting or redundant options"),
195  parser_errposition(pstate, defel->location)));
196  disreplication = defel;
197  }
198  else if (strcmp(defel->defname, "connectionlimit") == 0)
199  {
200  if (dconnlimit)
201  ereport(ERROR,
202  (errcode(ERRCODE_SYNTAX_ERROR),
203  errmsg("conflicting or redundant options"),
204  parser_errposition(pstate, defel->location)));
205  dconnlimit = defel;
206  }
207  else if (strcmp(defel->defname, "addroleto") == 0)
208  {
209  if (daddroleto)
210  ereport(ERROR,
211  (errcode(ERRCODE_SYNTAX_ERROR),
212  errmsg("conflicting or redundant options"),
213  parser_errposition(pstate, defel->location)));
214  daddroleto = defel;
215  }
216  else if (strcmp(defel->defname, "rolemembers") == 0)
217  {
218  if (drolemembers)
219  ereport(ERROR,
220  (errcode(ERRCODE_SYNTAX_ERROR),
221  errmsg("conflicting or redundant options"),
222  parser_errposition(pstate, defel->location)));
223  drolemembers = defel;
224  }
225  else if (strcmp(defel->defname, "adminmembers") == 0)
226  {
227  if (dadminmembers)
228  ereport(ERROR,
229  (errcode(ERRCODE_SYNTAX_ERROR),
230  errmsg("conflicting or redundant options"),
231  parser_errposition(pstate, defel->location)));
232  dadminmembers = defel;
233  }
234  else if (strcmp(defel->defname, "validUntil") == 0)
235  {
236  if (dvalidUntil)
237  ereport(ERROR,
238  (errcode(ERRCODE_SYNTAX_ERROR),
239  errmsg("conflicting or redundant options"),
240  parser_errposition(pstate, defel->location)));
241  dvalidUntil = defel;
242  }
243  else if (strcmp(defel->defname, "bypassrls") == 0)
244  {
245  if (dbypassRLS)
246  ereport(ERROR,
247  (errcode(ERRCODE_SYNTAX_ERROR),
248  errmsg("conflicting or redundant options"),
249  parser_errposition(pstate, defel->location)));
250  dbypassRLS = defel;
251  }
252  else
253  elog(ERROR, "option \"%s\" not recognized",
254  defel->defname);
255  }
256 
257  if (dpassword && dpassword->arg)
258  password = strVal(dpassword->arg);
259  if (dissuper)
260  issuper = intVal(dissuper->arg) != 0;
261  if (dinherit)
262  inherit = intVal(dinherit->arg) != 0;
263  if (dcreaterole)
264  createrole = intVal(dcreaterole->arg) != 0;
265  if (dcreatedb)
266  createdb = intVal(dcreatedb->arg) != 0;
267  if (dcanlogin)
268  canlogin = intVal(dcanlogin->arg) != 0;
269  if (disreplication)
270  isreplication = intVal(disreplication->arg) != 0;
271  if (dconnlimit)
272  {
273  connlimit = intVal(dconnlimit->arg);
274  if (connlimit < -1)
275  ereport(ERROR,
276  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
277  errmsg("invalid connection limit: %d", connlimit)));
278  }
279  if (daddroleto)
280  addroleto = (List *) daddroleto->arg;
281  if (drolemembers)
282  rolemembers = (List *) drolemembers->arg;
283  if (dadminmembers)
284  adminmembers = (List *) dadminmembers->arg;
285  if (dvalidUntil)
286  validUntil = strVal(dvalidUntil->arg);
287  if (dbypassRLS)
288  bypassrls = intVal(dbypassRLS->arg) != 0;
289 
290  /* Check some permissions first */
291  if (issuper)
292  {
293  if (!superuser())
294  ereport(ERROR,
295  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
296  errmsg("must be superuser to create superusers")));
297  }
298  else if (isreplication)
299  {
300  if (!superuser())
301  ereport(ERROR,
302  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
303  errmsg("must be superuser to create replication users")));
304  }
305  else if (bypassrls)
306  {
307  if (!superuser())
308  ereport(ERROR,
309  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
310  errmsg("must be superuser to change bypassrls attribute")));
311  }
312  else
313  {
315  ereport(ERROR,
316  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
317  errmsg("permission denied to create role")));
318  }
319 
320  /*
321  * Check that the user is not trying to create a role in the reserved
322  * "pg_" namespace.
323  */
324  if (IsReservedName(stmt->role))
325  ereport(ERROR,
326  (errcode(ERRCODE_RESERVED_NAME),
327  errmsg("role name \"%s\" is reserved",
328  stmt->role),
329  errdetail("Role names starting with \"pg_\" are reserved.")));
330 
331  /*
332  * Check the pg_authid relation to be certain the role doesn't already
333  * exist.
334  */
335  pg_authid_rel = heap_open(AuthIdRelationId, RowExclusiveLock);
336  pg_authid_dsc = RelationGetDescr(pg_authid_rel);
337 
338  if (OidIsValid(get_role_oid(stmt->role, true)))
339  ereport(ERROR,
341  errmsg("role \"%s\" already exists",
342  stmt->role)));
343 
344  /* Convert validuntil to internal form */
345  if (validUntil)
346  {
347  validUntil_datum = DirectFunctionCall3(timestamptz_in,
348  CStringGetDatum(validUntil),
350  Int32GetDatum(-1));
351  validUntil_null = false;
352  }
353  else
354  {
355  validUntil_datum = (Datum) 0;
356  validUntil_null = true;
357  }
358 
359  /*
360  * Call the password checking hook if there is one defined
361  */
362  if (check_password_hook && password)
363  (*check_password_hook) (stmt->role,
364  password,
365  get_password_type(password),
366  validUntil_datum,
367  validUntil_null);
368 
369  /*
370  * Build a tuple to insert
371  */
372  MemSet(new_record, 0, sizeof(new_record));
373  MemSet(new_record_nulls, false, sizeof(new_record_nulls));
374 
375  new_record[Anum_pg_authid_rolname - 1] =
377 
378  new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper);
379  new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit);
380  new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole);
381  new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb);
382  new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin);
383  new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication);
384  new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
385 
386  if (password)
387  {
388  /* Encrypt the password to the requested format. */
389  char *shadow_pass;
390 
391  shadow_pass = encrypt_password(Password_encryption, stmt->role,
392  password);
393  new_record[Anum_pg_authid_rolpassword - 1] =
394  CStringGetTextDatum(shadow_pass);
395  }
396  else
397  new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
398 
399  new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
400  new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
401 
402  new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(bypassrls);
403 
404  tuple = heap_form_tuple(pg_authid_dsc, new_record, new_record_nulls);
405 
406  /*
407  * pg_largeobject_metadata contains pg_authid.oid's, so we use the
408  * binary-upgrade override.
409  */
410  if (IsBinaryUpgrade)
411  {
413  ereport(ERROR,
414  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
415  errmsg("pg_authid OID value not set when in binary upgrade mode")));
416 
419  }
420 
421  /*
422  * Insert new record in the pg_authid table
423  */
424  roleid = CatalogTupleInsert(pg_authid_rel, tuple);
425 
426  /*
427  * Advance command counter so we can see new record; else tests in
428  * AddRoleMems may fail.
429  */
430  if (addroleto || adminmembers || rolemembers)
432 
433  /*
434  * Add the new role to the specified existing roles.
435  */
436  foreach(item, addroleto)
437  {
438  RoleSpec *oldrole = lfirst(item);
439  HeapTuple oldroletup = get_rolespec_tuple(oldrole);
440  Oid oldroleid = HeapTupleGetOid(oldroletup);
441  char *oldrolename = NameStr(((Form_pg_authid) GETSTRUCT(oldroletup))->rolname);
442 
443  AddRoleMems(oldrolename, oldroleid,
444  list_make1(makeString(stmt->role)),
445  list_make1_oid(roleid),
446  GetUserId(), false);
447 
448  ReleaseSysCache(oldroletup);
449  }
450 
451  /*
452  * Add the specified members to this new role. adminmembers get the admin
453  * option, rolemembers don't.
454  */
455  AddRoleMems(stmt->role, roleid,
456  adminmembers, roleSpecsToIds(adminmembers),
457  GetUserId(), true);
458  AddRoleMems(stmt->role, roleid,
459  rolemembers, roleSpecsToIds(rolemembers),
460  GetUserId(), false);
461 
462  /* Post creation hook for new role */
464 
465  /*
466  * Close pg_authid, but keep lock till commit.
467  */
468  heap_close(pg_authid_rel, NoLock);
469 
470  return roleid;
471 }
472 
473 
474 /*
475  * ALTER ROLE
476  *
477  * Note: the rolemembers option accepted here is intended to support the
478  * backwards-compatible ALTER GROUP syntax. Although it will work to say
479  * "ALTER ROLE role ROLE rolenames", we don't document it.
480  */
481 Oid
483 {
484  Datum new_record[Natts_pg_authid];
485  bool new_record_nulls[Natts_pg_authid];
486  bool new_record_repl[Natts_pg_authid];
487  Relation pg_authid_rel;
488  TupleDesc pg_authid_dsc;
489  HeapTuple tuple,
490  new_tuple;
491  Form_pg_authid authform;
492  ListCell *option;
493  char *rolename = NULL;
494  char *password = NULL; /* user password */
495  int issuper = -1; /* Make the user a superuser? */
496  int inherit = -1; /* Auto inherit privileges? */
497  int createrole = -1; /* Can this user create roles? */
498  int createdb = -1; /* Can the user create databases? */
499  int canlogin = -1; /* Can this user login? */
500  int isreplication = -1; /* Is this a replication role? */
501  int connlimit = -1; /* maximum connections allowed */
502  List *rolemembers = NIL; /* roles to be added/removed */
503  char *validUntil = NULL; /* time the login is valid until */
504  Datum validUntil_datum; /* same, as timestamptz Datum */
505  bool validUntil_null;
506  int bypassrls = -1;
507  DefElem *dpassword = NULL;
508  DefElem *dissuper = NULL;
509  DefElem *dinherit = NULL;
510  DefElem *dcreaterole = NULL;
511  DefElem *dcreatedb = NULL;
512  DefElem *dcanlogin = NULL;
513  DefElem *disreplication = NULL;
514  DefElem *dconnlimit = NULL;
515  DefElem *drolemembers = NULL;
516  DefElem *dvalidUntil = NULL;
517  DefElem *dbypassRLS = NULL;
518  Oid roleid;
519 
521  "Cannot alter reserved roles.");
522 
523  /* Extract options from the statement node tree */
524  foreach(option, stmt->options)
525  {
526  DefElem *defel = (DefElem *) lfirst(option);
527 
528  if (strcmp(defel->defname, "password") == 0)
529  {
530  if (dpassword)
531  ereport(ERROR,
532  (errcode(ERRCODE_SYNTAX_ERROR),
533  errmsg("conflicting or redundant options")));
534  dpassword = defel;
535  }
536  else if (strcmp(defel->defname, "superuser") == 0)
537  {
538  if (dissuper)
539  ereport(ERROR,
540  (errcode(ERRCODE_SYNTAX_ERROR),
541  errmsg("conflicting or redundant options")));
542  dissuper = defel;
543  }
544  else if (strcmp(defel->defname, "inherit") == 0)
545  {
546  if (dinherit)
547  ereport(ERROR,
548  (errcode(ERRCODE_SYNTAX_ERROR),
549  errmsg("conflicting or redundant options")));
550  dinherit = defel;
551  }
552  else if (strcmp(defel->defname, "createrole") == 0)
553  {
554  if (dcreaterole)
555  ereport(ERROR,
556  (errcode(ERRCODE_SYNTAX_ERROR),
557  errmsg("conflicting or redundant options")));
558  dcreaterole = defel;
559  }
560  else if (strcmp(defel->defname, "createdb") == 0)
561  {
562  if (dcreatedb)
563  ereport(ERROR,
564  (errcode(ERRCODE_SYNTAX_ERROR),
565  errmsg("conflicting or redundant options")));
566  dcreatedb = defel;
567  }
568  else if (strcmp(defel->defname, "canlogin") == 0)
569  {
570  if (dcanlogin)
571  ereport(ERROR,
572  (errcode(ERRCODE_SYNTAX_ERROR),
573  errmsg("conflicting or redundant options")));
574  dcanlogin = defel;
575  }
576  else if (strcmp(defel->defname, "isreplication") == 0)
577  {
578  if (disreplication)
579  ereport(ERROR,
580  (errcode(ERRCODE_SYNTAX_ERROR),
581  errmsg("conflicting or redundant options")));
582  disreplication = defel;
583  }
584  else if (strcmp(defel->defname, "connectionlimit") == 0)
585  {
586  if (dconnlimit)
587  ereport(ERROR,
588  (errcode(ERRCODE_SYNTAX_ERROR),
589  errmsg("conflicting or redundant options")));
590  dconnlimit = defel;
591  }
592  else if (strcmp(defel->defname, "rolemembers") == 0 &&
593  stmt->action != 0)
594  {
595  if (drolemembers)
596  ereport(ERROR,
597  (errcode(ERRCODE_SYNTAX_ERROR),
598  errmsg("conflicting or redundant options")));
599  drolemembers = defel;
600  }
601  else if (strcmp(defel->defname, "validUntil") == 0)
602  {
603  if (dvalidUntil)
604  ereport(ERROR,
605  (errcode(ERRCODE_SYNTAX_ERROR),
606  errmsg("conflicting or redundant options")));
607  dvalidUntil = defel;
608  }
609  else if (strcmp(defel->defname, "bypassrls") == 0)
610  {
611  if (dbypassRLS)
612  ereport(ERROR,
613  (errcode(ERRCODE_SYNTAX_ERROR),
614  errmsg("conflicting or redundant options")));
615  dbypassRLS = defel;
616  }
617  else
618  elog(ERROR, "option \"%s\" not recognized",
619  defel->defname);
620  }
621 
622  if (dpassword && dpassword->arg)
623  password = strVal(dpassword->arg);
624  if (dissuper)
625  issuper = intVal(dissuper->arg);
626  if (dinherit)
627  inherit = intVal(dinherit->arg);
628  if (dcreaterole)
629  createrole = intVal(dcreaterole->arg);
630  if (dcreatedb)
631  createdb = intVal(dcreatedb->arg);
632  if (dcanlogin)
633  canlogin = intVal(dcanlogin->arg);
634  if (disreplication)
635  isreplication = intVal(disreplication->arg);
636  if (dconnlimit)
637  {
638  connlimit = intVal(dconnlimit->arg);
639  if (connlimit < -1)
640  ereport(ERROR,
641  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
642  errmsg("invalid connection limit: %d", connlimit)));
643  }
644  if (drolemembers)
645  rolemembers = (List *) drolemembers->arg;
646  if (dvalidUntil)
647  validUntil = strVal(dvalidUntil->arg);
648  if (dbypassRLS)
649  bypassrls = intVal(dbypassRLS->arg);
650 
651  /*
652  * Scan the pg_authid relation to be certain the user exists.
653  */
654  pg_authid_rel = heap_open(AuthIdRelationId, RowExclusiveLock);
655  pg_authid_dsc = RelationGetDescr(pg_authid_rel);
656 
657  tuple = get_rolespec_tuple(stmt->role);
658  authform = (Form_pg_authid) GETSTRUCT(tuple);
659  rolename = pstrdup(NameStr(authform->rolname));
660  roleid = HeapTupleGetOid(tuple);
661 
662  /*
663  * To mess with a superuser you gotta be superuser; else you need
664  * createrole, or just want to change your own password
665  */
666  if (authform->rolsuper || issuper >= 0)
667  {
668  if (!superuser())
669  ereport(ERROR,
670  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
671  errmsg("must be superuser to alter superusers")));
672  }
673  else if (authform->rolreplication || isreplication >= 0)
674  {
675  if (!superuser())
676  ereport(ERROR,
677  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
678  errmsg("must be superuser to alter replication users")));
679  }
680  else if (authform->rolbypassrls || bypassrls >= 0)
681  {
682  if (!superuser())
683  ereport(ERROR,
684  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
685  errmsg("must be superuser to change bypassrls attribute")));
686  }
687  else if (!have_createrole_privilege())
688  {
689  if (!(inherit < 0 &&
690  createrole < 0 &&
691  createdb < 0 &&
692  canlogin < 0 &&
693  isreplication < 0 &&
694  !dconnlimit &&
695  !rolemembers &&
696  !validUntil &&
697  dpassword &&
698  roleid == GetUserId()))
699  ereport(ERROR,
700  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
701  errmsg("permission denied")));
702  }
703 
704  /* Convert validuntil to internal form */
705  if (validUntil)
706  {
707  validUntil_datum = DirectFunctionCall3(timestamptz_in,
708  CStringGetDatum(validUntil),
710  Int32GetDatum(-1));
711  validUntil_null = false;
712  }
713  else
714  {
715  /* fetch existing setting in case hook needs it */
716  validUntil_datum = SysCacheGetAttr(AUTHNAME, tuple,
718  &validUntil_null);
719  }
720 
721  /*
722  * Call the password checking hook if there is one defined
723  */
724  if (check_password_hook && password)
725  (*check_password_hook) (rolename,
726  password,
727  get_password_type(password),
728  validUntil_datum,
729  validUntil_null);
730 
731  /*
732  * Build an updated tuple, perusing the information just obtained
733  */
734  MemSet(new_record, 0, sizeof(new_record));
735  MemSet(new_record_nulls, false, sizeof(new_record_nulls));
736  MemSet(new_record_repl, false, sizeof(new_record_repl));
737 
738  /*
739  * issuper/createrole/etc
740  */
741  if (issuper >= 0)
742  {
743  new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper > 0);
744  new_record_repl[Anum_pg_authid_rolsuper - 1] = true;
745  }
746 
747  if (inherit >= 0)
748  {
749  new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit > 0);
750  new_record_repl[Anum_pg_authid_rolinherit - 1] = true;
751  }
752 
753  if (createrole >= 0)
754  {
755  new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole > 0);
756  new_record_repl[Anum_pg_authid_rolcreaterole - 1] = true;
757  }
758 
759  if (createdb >= 0)
760  {
761  new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb > 0);
762  new_record_repl[Anum_pg_authid_rolcreatedb - 1] = true;
763  }
764 
765  if (canlogin >= 0)
766  {
767  new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin > 0);
768  new_record_repl[Anum_pg_authid_rolcanlogin - 1] = true;
769  }
770 
771  if (isreplication >= 0)
772  {
773  new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication > 0);
774  new_record_repl[Anum_pg_authid_rolreplication - 1] = true;
775  }
776 
777  if (dconnlimit)
778  {
779  new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
780  new_record_repl[Anum_pg_authid_rolconnlimit - 1] = true;
781  }
782 
783  /* password */
784  if (password)
785  {
786  /* Encrypt the password to the requested format. */
787  char *shadow_pass;
788 
789  shadow_pass = encrypt_password(Password_encryption, rolename,
790  password);
791  new_record[Anum_pg_authid_rolpassword - 1] =
792  CStringGetTextDatum(shadow_pass);
793  new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
794  }
795 
796  /* unset password */
797  if (dpassword && dpassword->arg == NULL)
798  {
799  new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
800  new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
801  }
802 
803  /* valid until */
804  new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
805  new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
806  new_record_repl[Anum_pg_authid_rolvaliduntil - 1] = true;
807 
808  if (bypassrls >= 0)
809  {
810  new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(bypassrls > 0);
811  new_record_repl[Anum_pg_authid_rolbypassrls - 1] = true;
812  }
813 
814  new_tuple = heap_modify_tuple(tuple, pg_authid_dsc, new_record,
815  new_record_nulls, new_record_repl);
816  CatalogTupleUpdate(pg_authid_rel, &tuple->t_self, new_tuple);
817 
819 
820  ReleaseSysCache(tuple);
821  heap_freetuple(new_tuple);
822 
823  /*
824  * Advance command counter so we can see new record; else tests in
825  * AddRoleMems may fail.
826  */
827  if (rolemembers)
829 
830  if (stmt->action == +1) /* add members to role */
831  AddRoleMems(rolename, roleid,
832  rolemembers, roleSpecsToIds(rolemembers),
833  GetUserId(), false);
834  else if (stmt->action == -1) /* drop members from role */
835  DelRoleMems(rolename, roleid,
836  rolemembers, roleSpecsToIds(rolemembers),
837  false);
838 
839  /*
840  * Close pg_authid, but keep lock till commit.
841  */
842  heap_close(pg_authid_rel, NoLock);
843 
844  return roleid;
845 }
846 
847 
848 /*
849  * ALTER ROLE ... SET
850  */
851 Oid
853 {
854  HeapTuple roletuple;
855  Oid databaseid = InvalidOid;
856  Oid roleid = InvalidOid;
857 
858  if (stmt->role)
859  {
861  "Cannot alter reserved roles.");
862 
863  roletuple = get_rolespec_tuple(stmt->role);
864  roleid = HeapTupleGetOid(roletuple);
865 
866  /*
867  * Obtain a lock on the role and make sure it didn't go away in the
868  * meantime.
869  */
871 
872  /*
873  * To mess with a superuser you gotta be superuser; else you need
874  * createrole, or just want to change your own settings
875  */
876  if (((Form_pg_authid) GETSTRUCT(roletuple))->rolsuper)
877  {
878  if (!superuser())
879  ereport(ERROR,
880  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
881  errmsg("must be superuser to alter superusers")));
882  }
883  else
884  {
885  if (!have_createrole_privilege() &&
886  HeapTupleGetOid(roletuple) != GetUserId())
887  ereport(ERROR,
888  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
889  errmsg("permission denied")));
890  }
891 
892  ReleaseSysCache(roletuple);
893  }
894 
895  /* look up and lock the database, if specified */
896  if (stmt->database != NULL)
897  {
898  databaseid = get_database_oid(stmt->database, false);
900 
901  if (!stmt->role)
902  {
903  /*
904  * If no role is specified, then this is effectively the same as
905  * ALTER DATABASE ... SET, so use the same permission check.
906  */
907  if (!pg_database_ownercheck(databaseid, GetUserId()))
909  stmt->database);
910  }
911  }
912 
913  if (!stmt->role && !stmt->database)
914  {
915  /* Must be superuser to alter settings globally. */
916  if (!superuser())
917  ereport(ERROR,
918  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
919  errmsg("must be superuser to alter settings globally")));
920  }
921 
922  AlterSetting(databaseid, roleid, stmt->setstmt);
923 
924  return roleid;
925 }
926 
927 
928 /*
929  * DROP ROLE
930  */
931 void
933 {
934  Relation pg_authid_rel,
935  pg_auth_members_rel;
936  ListCell *item;
937 
939  ereport(ERROR,
940  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
941  errmsg("permission denied to drop role")));
942 
943  /*
944  * Scan the pg_authid relation to find the Oid of the role(s) to be
945  * deleted.
946  */
947  pg_authid_rel = heap_open(AuthIdRelationId, RowExclusiveLock);
948  pg_auth_members_rel = heap_open(AuthMemRelationId, RowExclusiveLock);
949 
950  foreach(item, stmt->roles)
951  {
952  RoleSpec *rolspec = lfirst(item);
953  char *role;
954  HeapTuple tuple,
955  tmp_tuple;
956  ScanKeyData scankey;
957  char *detail;
958  char *detail_log;
959  SysScanDesc sscan;
960  Oid roleid;
961 
962  if (rolspec->roletype != ROLESPEC_CSTRING)
963  ereport(ERROR,
964  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
965  errmsg("cannot use special role specifier in DROP ROLE")));
966  role = rolspec->rolename;
967 
968  tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
969  if (!HeapTupleIsValid(tuple))
970  {
971  if (!stmt->missing_ok)
972  {
973  ereport(ERROR,
974  (errcode(ERRCODE_UNDEFINED_OBJECT),
975  errmsg("role \"%s\" does not exist", role)));
976  }
977  else
978  {
979  ereport(NOTICE,
980  (errmsg("role \"%s\" does not exist, skipping",
981  role)));
982  }
983 
984  continue;
985  }
986 
987  roleid = HeapTupleGetOid(tuple);
988 
989  if (roleid == GetUserId())
990  ereport(ERROR,
991  (errcode(ERRCODE_OBJECT_IN_USE),
992  errmsg("current user cannot be dropped")));
993  if (roleid == GetOuterUserId())
994  ereport(ERROR,
995  (errcode(ERRCODE_OBJECT_IN_USE),
996  errmsg("current user cannot be dropped")));
997  if (roleid == GetSessionUserId())
998  ereport(ERROR,
999  (errcode(ERRCODE_OBJECT_IN_USE),
1000  errmsg("session user cannot be dropped")));
1001 
1002  /*
1003  * For safety's sake, we allow createrole holders to drop ordinary
1004  * roles but not superuser roles. This is mainly to avoid the
1005  * scenario where you accidentally drop the last superuser.
1006  */
1007  if (((Form_pg_authid) GETSTRUCT(tuple))->rolsuper &&
1008  !superuser())
1009  ereport(ERROR,
1010  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1011  errmsg("must be superuser to drop superusers")));
1012 
1013  /* DROP hook for the role being removed */
1015 
1016  /*
1017  * Lock the role, so nobody can add dependencies to her while we drop
1018  * her. We keep the lock until the end of transaction.
1019  */
1021 
1022  /* Check for pg_shdepend entries depending on this role */
1024  &detail, &detail_log))
1025  ereport(ERROR,
1026  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1027  errmsg("role \"%s\" cannot be dropped because some objects depend on it",
1028  role),
1029  errdetail_internal("%s", detail),
1030  errdetail_log("%s", detail_log)));
1031 
1032  /*
1033  * Remove the role from the pg_authid table
1034  */
1035  CatalogTupleDelete(pg_authid_rel, &tuple->t_self);
1036 
1037  ReleaseSysCache(tuple);
1038 
1039  /*
1040  * Remove role from the pg_auth_members table. We have to remove all
1041  * tuples that show it as either a role or a member.
1042  *
1043  * XXX what about grantor entries? Maybe we should do one heap scan.
1044  */
1045  ScanKeyInit(&scankey,
1047  BTEqualStrategyNumber, F_OIDEQ,
1048  ObjectIdGetDatum(roleid));
1049 
1050  sscan = systable_beginscan(pg_auth_members_rel, AuthMemRoleMemIndexId,
1051  true, NULL, 1, &scankey);
1052 
1053  while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
1054  {
1055  CatalogTupleDelete(pg_auth_members_rel, &tmp_tuple->t_self);
1056  }
1057 
1058  systable_endscan(sscan);
1059 
1060  ScanKeyInit(&scankey,
1062  BTEqualStrategyNumber, F_OIDEQ,
1063  ObjectIdGetDatum(roleid));
1064 
1065  sscan = systable_beginscan(pg_auth_members_rel, AuthMemMemRoleIndexId,
1066  true, NULL, 1, &scankey);
1067 
1068  while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
1069  {
1070  CatalogTupleDelete(pg_auth_members_rel, &tmp_tuple->t_self);
1071  }
1072 
1073  systable_endscan(sscan);
1074 
1075  /*
1076  * Remove any comments or security labels on this role.
1077  */
1080 
1081  /*
1082  * Remove settings for this role.
1083  */
1084  DropSetting(InvalidOid, roleid);
1085 
1086  /*
1087  * Advance command counter so that later iterations of this loop will
1088  * see the changes already made. This is essential if, for example,
1089  * we are trying to drop both a role and one of its direct members ---
1090  * we'll get an error if we try to delete the linking pg_auth_members
1091  * tuple twice. (We do not need a CCI between the two delete loops
1092  * above, because it's not allowed for a role to directly contain
1093  * itself.)
1094  */
1096  }
1097 
1098  /*
1099  * Now we can clean up; but keep locks until commit.
1100  */
1101  heap_close(pg_auth_members_rel, NoLock);
1102  heap_close(pg_authid_rel, NoLock);
1103 }
1104 
1105 /*
1106  * Rename role
1107  */
1109 RenameRole(const char *oldname, const char *newname)
1110 {
1111  HeapTuple oldtuple,
1112  newtuple;
1113  TupleDesc dsc;
1114  Relation rel;
1115  Datum datum;
1116  bool isnull;
1117  Datum repl_val[Natts_pg_authid];
1118  bool repl_null[Natts_pg_authid];
1119  bool repl_repl[Natts_pg_authid];
1120  int i;
1121  Oid roleid;
1122  ObjectAddress address;
1123  Form_pg_authid authform;
1124 
1126  dsc = RelationGetDescr(rel);
1127 
1128  oldtuple = SearchSysCache1(AUTHNAME, CStringGetDatum(oldname));
1129  if (!HeapTupleIsValid(oldtuple))
1130  ereport(ERROR,
1131  (errcode(ERRCODE_UNDEFINED_OBJECT),
1132  errmsg("role \"%s\" does not exist", oldname)));
1133 
1134  /*
1135  * XXX Client applications probably store the session user somewhere, so
1136  * renaming it could cause confusion. On the other hand, there may not be
1137  * an actual problem besides a little confusion, so think about this and
1138  * decide. Same for SET ROLE ... we don't restrict renaming the current
1139  * effective userid, though.
1140  */
1141 
1142  roleid = HeapTupleGetOid(oldtuple);
1143  authform = (Form_pg_authid) GETSTRUCT(oldtuple);
1144 
1145  if (roleid == GetSessionUserId())
1146  ereport(ERROR,
1147  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1148  errmsg("session user cannot be renamed")));
1149  if (roleid == GetOuterUserId())
1150  ereport(ERROR,
1151  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1152  errmsg("current user cannot be renamed")));
1153 
1154  /*
1155  * Check that the user is not trying to rename a system role and not
1156  * trying to rename a role into the reserved "pg_" namespace.
1157  */
1158  if (IsReservedName(NameStr(authform->rolname)))
1159  ereport(ERROR,
1160  (errcode(ERRCODE_RESERVED_NAME),
1161  errmsg("role name \"%s\" is reserved",
1162  NameStr(authform->rolname)),
1163  errdetail("Role names starting with \"pg_\" are reserved.")));
1164 
1165  if (IsReservedName(newname))
1166  ereport(ERROR,
1167  (errcode(ERRCODE_RESERVED_NAME),
1168  errmsg("role name \"%s\" is reserved",
1169  newname),
1170  errdetail("Role names starting with \"pg_\" are reserved.")));
1171 
1172  /* make sure the new name doesn't exist */
1174  ereport(ERROR,
1176  errmsg("role \"%s\" already exists", newname)));
1177 
1178  /*
1179  * createrole is enough privilege unless you want to mess with a superuser
1180  */
1181  if (((Form_pg_authid) GETSTRUCT(oldtuple))->rolsuper)
1182  {
1183  if (!superuser())
1184  ereport(ERROR,
1185  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1186  errmsg("must be superuser to rename superusers")));
1187  }
1188  else
1189  {
1191  ereport(ERROR,
1192  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1193  errmsg("permission denied to rename role")));
1194  }
1195 
1196  /* OK, construct the modified tuple */
1197  for (i = 0; i < Natts_pg_authid; i++)
1198  repl_repl[i] = false;
1199 
1200  repl_repl[Anum_pg_authid_rolname - 1] = true;
1202  CStringGetDatum(newname));
1203  repl_null[Anum_pg_authid_rolname - 1] = false;
1204 
1205  datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull);
1206 
1207  if (!isnull && get_password_type(TextDatumGetCString(datum)) == PASSWORD_TYPE_MD5)
1208  {
1209  /* MD5 uses the username as salt, so just clear it on a rename */
1210  repl_repl[Anum_pg_authid_rolpassword - 1] = true;
1211  repl_null[Anum_pg_authid_rolpassword - 1] = true;
1212 
1213  ereport(NOTICE,
1214  (errmsg("MD5 password cleared because of role rename")));
1215  }
1216 
1217  newtuple = heap_modify_tuple(oldtuple, dsc, repl_val, repl_null, repl_repl);
1218  CatalogTupleUpdate(rel, &oldtuple->t_self, newtuple);
1219 
1221 
1222  ObjectAddressSet(address, AuthIdRelationId, roleid);
1223 
1224  ReleaseSysCache(oldtuple);
1225 
1226  /*
1227  * Close pg_authid, but keep lock till commit.
1228  */
1229  heap_close(rel, NoLock);
1230 
1231  return address;
1232 }
1233 
1234 /*
1235  * GrantRoleStmt
1236  *
1237  * Grant/Revoke roles to/from roles
1238  */
1239 void
1241 {
1242  Relation pg_authid_rel;
1243  Oid grantor;
1244  List *grantee_ids;
1245  ListCell *item;
1246 
1247  if (stmt->grantor)
1248  grantor = get_rolespec_oid(stmt->grantor, false);
1249  else
1250  grantor = GetUserId();
1251 
1252  grantee_ids = roleSpecsToIds(stmt->grantee_roles);
1253 
1254  /* AccessShareLock is enough since we aren't modifying pg_authid */
1255  pg_authid_rel = heap_open(AuthIdRelationId, AccessShareLock);
1256 
1257  /*
1258  * Step through all of the granted roles and add/remove entries for the
1259  * grantees, or, if admin_opt is set, then just add/remove the admin
1260  * option.
1261  *
1262  * Note: Permissions checking is done by AddRoleMems/DelRoleMems
1263  */
1264  foreach(item, stmt->granted_roles)
1265  {
1266  AccessPriv *priv = (AccessPriv *) lfirst(item);
1267  char *rolename = priv->priv_name;
1268  Oid roleid;
1269 
1270  /* Must reject priv(columns) and ALL PRIVILEGES(columns) */
1271  if (rolename == NULL || priv->cols != NIL)
1272  ereport(ERROR,
1273  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1274  errmsg("column names cannot be included in GRANT/REVOKE ROLE")));
1275 
1276  roleid = get_role_oid(rolename, false);
1277  if (stmt->is_grant)
1278  AddRoleMems(rolename, roleid,
1279  stmt->grantee_roles, grantee_ids,
1280  grantor, stmt->admin_opt);
1281  else
1282  DelRoleMems(rolename, roleid,
1283  stmt->grantee_roles, grantee_ids,
1284  stmt->admin_opt);
1285  }
1286 
1287  /*
1288  * Close pg_authid, but keep lock till commit.
1289  */
1290  heap_close(pg_authid_rel, NoLock);
1291 }
1292 
1293 /*
1294  * DropOwnedObjects
1295  *
1296  * Drop the objects owned by a given list of roles.
1297  */
1298 void
1300 {
1301  List *role_ids = roleSpecsToIds(stmt->roles);
1302  ListCell *cell;
1303 
1304  /* Check privileges */
1305  foreach(cell, role_ids)
1306  {
1307  Oid roleid = lfirst_oid(cell);
1308 
1309  if (!has_privs_of_role(GetUserId(), roleid))
1310  ereport(ERROR,
1311  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1312  errmsg("permission denied to drop objects")));
1313  }
1314 
1315  /* Ok, do it */
1316  shdepDropOwned(role_ids, stmt->behavior);
1317 }
1318 
1319 /*
1320  * ReassignOwnedObjects
1321  *
1322  * Give the objects owned by a given list of roles away to another user.
1323  */
1324 void
1326 {
1327  List *role_ids = roleSpecsToIds(stmt->roles);
1328  ListCell *cell;
1329  Oid newrole;
1330 
1331  /* Check privileges */
1332  foreach(cell, role_ids)
1333  {
1334  Oid roleid = lfirst_oid(cell);
1335 
1336  if (!has_privs_of_role(GetUserId(), roleid))
1337  ereport(ERROR,
1338  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1339  errmsg("permission denied to reassign objects")));
1340  }
1341 
1342  /* Must have privileges on the receiving side too */
1343  newrole = get_rolespec_oid(stmt->newrole, false);
1344 
1345  if (!has_privs_of_role(GetUserId(), newrole))
1346  ereport(ERROR,
1347  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1348  errmsg("permission denied to reassign objects")));
1349 
1350  /* Ok, do it */
1351  shdepReassignOwned(role_ids, newrole);
1352 }
1353 
1354 /*
1355  * roleSpecsToIds
1356  *
1357  * Given a list of RoleSpecs, generate a list of role OIDs in the same order.
1358  *
1359  * ROLESPEC_PUBLIC is not allowed.
1360  */
1361 List *
1362 roleSpecsToIds(List *memberNames)
1363 {
1364  List *result = NIL;
1365  ListCell *l;
1366 
1367  foreach(l, memberNames)
1368  {
1369  RoleSpec *rolespec = lfirst_node(RoleSpec, l);
1370  Oid roleid;
1371 
1372  roleid = get_rolespec_oid(rolespec, false);
1373  result = lappend_oid(result, roleid);
1374  }
1375  return result;
1376 }
1377 
1378 /*
1379  * AddRoleMems -- Add given members to the specified role
1380  *
1381  * rolename: name of role to add to (used only for error messages)
1382  * roleid: OID of role to add to
1383  * memberSpecs: list of RoleSpec of roles to add (used only for error messages)
1384  * memberIds: OIDs of roles to add
1385  * grantorId: who is granting the membership
1386  * admin_opt: granting admin option?
1387  *
1388  * Note: caller is responsible for calling auth_file_update_needed().
1389  */
1390 static void
1391 AddRoleMems(const char *rolename, Oid roleid,
1392  List *memberSpecs, List *memberIds,
1393  Oid grantorId, bool admin_opt)
1394 {
1395  Relation pg_authmem_rel;
1396  TupleDesc pg_authmem_dsc;
1397  ListCell *specitem;
1398  ListCell *iditem;
1399 
1400  Assert(list_length(memberSpecs) == list_length(memberIds));
1401 
1402  /* Skip permission check if nothing to do */
1403  if (!memberIds)
1404  return;
1405 
1406  /*
1407  * Check permissions: must have createrole or admin option on the role to
1408  * be changed. To mess with a superuser role, you gotta be superuser.
1409  */
1410  if (superuser_arg(roleid))
1411  {
1412  if (!superuser())
1413  ereport(ERROR,
1414  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1415  errmsg("must be superuser to alter superusers")));
1416  }
1417  else
1418  {
1419  if (!have_createrole_privilege() &&
1420  !is_admin_of_role(grantorId, roleid))
1421  ereport(ERROR,
1422  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1423  errmsg("must have admin option on role \"%s\"",
1424  rolename)));
1425  }
1426 
1427  /*
1428  * The role membership grantor of record has little significance at
1429  * present. Nonetheless, inasmuch as users might look to it for a crude
1430  * audit trail, let only superusers impute the grant to a third party.
1431  *
1432  * Before lifting this restriction, give the member == role case of
1433  * is_admin_of_role() a fresh look. Ensure that the current role cannot
1434  * use an explicit grantor specification to take advantage of the session
1435  * user's self-admin right.
1436  */
1437  if (grantorId != GetUserId() && !superuser())
1438  ereport(ERROR,
1439  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1440  errmsg("must be superuser to set grantor")));
1441 
1442  pg_authmem_rel = heap_open(AuthMemRelationId, RowExclusiveLock);
1443  pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
1444 
1445  forboth(specitem, memberSpecs, iditem, memberIds)
1446  {
1447  RoleSpec *memberRole = lfirst(specitem);
1448  Oid memberid = lfirst_oid(iditem);
1449  HeapTuple authmem_tuple;
1450  HeapTuple tuple;
1451  Datum new_record[Natts_pg_auth_members];
1452  bool new_record_nulls[Natts_pg_auth_members];
1453  bool new_record_repl[Natts_pg_auth_members];
1454 
1455  /*
1456  * Refuse creation of membership loops, including the trivial case
1457  * where a role is made a member of itself. We do this by checking to
1458  * see if the target role is already a member of the proposed member
1459  * role. We have to ignore possible superuserness, however, else we
1460  * could never grant membership in a superuser-privileged role.
1461  */
1462  if (is_member_of_role_nosuper(roleid, memberid))
1463  ereport(ERROR,
1464  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1465  (errmsg("role \"%s\" is a member of role \"%s\"",
1466  rolename, get_rolespec_name(memberRole)))));
1467 
1468  /*
1469  * Check if entry for this role/member already exists; if so, give
1470  * warning unless we are adding admin option.
1471  */
1472  authmem_tuple = SearchSysCache2(AUTHMEMROLEMEM,
1473  ObjectIdGetDatum(roleid),
1474  ObjectIdGetDatum(memberid));
1475  if (HeapTupleIsValid(authmem_tuple) &&
1476  (!admin_opt ||
1477  ((Form_pg_auth_members) GETSTRUCT(authmem_tuple))->admin_option))
1478  {
1479  ereport(NOTICE,
1480  (errmsg("role \"%s\" is already a member of role \"%s\"",
1481  get_rolespec_name(memberRole), rolename)));
1482  ReleaseSysCache(authmem_tuple);
1483  continue;
1484  }
1485 
1486  /* Build a tuple to insert or update */
1487  MemSet(new_record, 0, sizeof(new_record));
1488  MemSet(new_record_nulls, false, sizeof(new_record_nulls));
1489  MemSet(new_record_repl, false, sizeof(new_record_repl));
1490 
1491  new_record[Anum_pg_auth_members_roleid - 1] = ObjectIdGetDatum(roleid);
1492  new_record[Anum_pg_auth_members_member - 1] = ObjectIdGetDatum(memberid);
1493  new_record[Anum_pg_auth_members_grantor - 1] = ObjectIdGetDatum(grantorId);
1494  new_record[Anum_pg_auth_members_admin_option - 1] = BoolGetDatum(admin_opt);
1495 
1496  if (HeapTupleIsValid(authmem_tuple))
1497  {
1498  new_record_repl[Anum_pg_auth_members_grantor - 1] = true;
1499  new_record_repl[Anum_pg_auth_members_admin_option - 1] = true;
1500  tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
1501  new_record,
1502  new_record_nulls, new_record_repl);
1503  CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple);
1504  ReleaseSysCache(authmem_tuple);
1505  }
1506  else
1507  {
1508  tuple = heap_form_tuple(pg_authmem_dsc,
1509  new_record, new_record_nulls);
1510  CatalogTupleInsert(pg_authmem_rel, tuple);
1511  }
1512 
1513  /* CCI after each change, in case there are duplicates in list */
1515  }
1516 
1517  /*
1518  * Close pg_authmem, but keep lock till commit.
1519  */
1520  heap_close(pg_authmem_rel, NoLock);
1521 }
1522 
1523 /*
1524  * DelRoleMems -- Remove given members from the specified role
1525  *
1526  * rolename: name of role to del from (used only for error messages)
1527  * roleid: OID of role to del from
1528  * memberSpecs: list of RoleSpec of roles to del (used only for error messages)
1529  * memberIds: OIDs of roles to del
1530  * admin_opt: remove admin option only?
1531  *
1532  * Note: caller is responsible for calling auth_file_update_needed().
1533  */
1534 static void
1535 DelRoleMems(const char *rolename, Oid roleid,
1536  List *memberSpecs, List *memberIds,
1537  bool admin_opt)
1538 {
1539  Relation pg_authmem_rel;
1540  TupleDesc pg_authmem_dsc;
1541  ListCell *specitem;
1542  ListCell *iditem;
1543 
1544  Assert(list_length(memberSpecs) == list_length(memberIds));
1545 
1546  /* Skip permission check if nothing to do */
1547  if (!memberIds)
1548  return;
1549 
1550  /*
1551  * Check permissions: must have createrole or admin option on the role to
1552  * be changed. To mess with a superuser role, you gotta be superuser.
1553  */
1554  if (superuser_arg(roleid))
1555  {
1556  if (!superuser())
1557  ereport(ERROR,
1558  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1559  errmsg("must be superuser to alter superusers")));
1560  }
1561  else
1562  {
1563  if (!have_createrole_privilege() &&
1564  !is_admin_of_role(GetUserId(), roleid))
1565  ereport(ERROR,
1566  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1567  errmsg("must have admin option on role \"%s\"",
1568  rolename)));
1569  }
1570 
1571  pg_authmem_rel = heap_open(AuthMemRelationId, RowExclusiveLock);
1572  pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
1573 
1574  forboth(specitem, memberSpecs, iditem, memberIds)
1575  {
1576  RoleSpec *memberRole = lfirst(specitem);
1577  Oid memberid = lfirst_oid(iditem);
1578  HeapTuple authmem_tuple;
1579 
1580  /*
1581  * Find entry for this role/member
1582  */
1583  authmem_tuple = SearchSysCache2(AUTHMEMROLEMEM,
1584  ObjectIdGetDatum(roleid),
1585  ObjectIdGetDatum(memberid));
1586  if (!HeapTupleIsValid(authmem_tuple))
1587  {
1588  ereport(WARNING,
1589  (errmsg("role \"%s\" is not a member of role \"%s\"",
1590  get_rolespec_name(memberRole), rolename)));
1591  continue;
1592  }
1593 
1594  if (!admin_opt)
1595  {
1596  /* Remove the entry altogether */
1597  CatalogTupleDelete(pg_authmem_rel, &authmem_tuple->t_self);
1598  }
1599  else
1600  {
1601  /* Just turn off the admin option */
1602  HeapTuple tuple;
1603  Datum new_record[Natts_pg_auth_members];
1604  bool new_record_nulls[Natts_pg_auth_members];
1605  bool new_record_repl[Natts_pg_auth_members];
1606 
1607  /* Build a tuple to update with */
1608  MemSet(new_record, 0, sizeof(new_record));
1609  MemSet(new_record_nulls, false, sizeof(new_record_nulls));
1610  MemSet(new_record_repl, false, sizeof(new_record_repl));
1611 
1612  new_record[Anum_pg_auth_members_admin_option - 1] = BoolGetDatum(false);
1613  new_record_repl[Anum_pg_auth_members_admin_option - 1] = true;
1614 
1615  tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
1616  new_record,
1617  new_record_nulls, new_record_repl);
1618  CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple);
1619  }
1620 
1621  ReleaseSysCache(authmem_tuple);
1622 
1623  /* CCI after each change, in case there are duplicates in list */
1625  }
1626 
1627  /*
1628  * Close pg_authmem, but keep lock till commit.
1629  */
1630  heap_close(pg_authmem_rel, NoLock);
1631 }
bool has_createrole_privilege(Oid roleid)
Definition: aclchk.c:5171
Value * makeString(char *str)
Definition: value.c:53
#define NIL
Definition: pg_list.h:69
static char password[100]
Definition: streamutil.c:41
RoleSpec * role
Definition: parsenodes.h:2406
void shdepDropOwned(List *roleids, DropBehavior behavior)
Definition: pg_shdepend.c:1163
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:46
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:499
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
Oid binary_upgrade_next_pg_authid_oid
Definition: user.c:43
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:145
#define RelationGetDescr(relation)
Definition: rel.h:429
Oid GetUserId(void)
Definition: miscinit.c:283
int Password_encryption
Definition: user.c:47
#define PointerGetDatum(X)
Definition: postgres.h:562
#define AuthMemRelationId
RoleStmtType stmt_type
Definition: parsenodes.h:2398
char * pstrdup(const char *in)
Definition: mcxt.c:1077
#define DatabaseRelationId
Definition: pg_database.h:29
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:99
void DropOwnedObjects(DropOwnedStmt *stmt)
Definition: user.c:1299
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4813
void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
#define InvokeObjectDropHook(classId, objectId, subId)
Definition: objectaccess.h:154
bool is_admin_of_role(Oid member, Oid role)
Definition: acl.c:4895
#define AccessShareLock
Definition: lockdefs.h:36
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:575
bool superuser(void)
Definition: superuser.c:47
#define MemSet(start, val, len)
Definition: c.h:857
#define Anum_pg_authid_rolpassword
Definition: pg_authid.h:88
List * granted_roles
Definition: parsenodes.h:1877
return result
Definition: formatting.c:1632
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:255
RoleSpec * role
Definition: parsenodes.h:2414
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
#define Anum_pg_authid_rolreplication
Definition: pg_authid.h:85
List * roles
Definition: parsenodes.h:2422
#define heap_close(r, l)
Definition: heapam.h:97
List * cols
Definition: parsenodes.h:1862
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:584
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1372
unsigned int Oid
Definition: postgres_ext.h:31
bool IsReservedName(const char *name)
Definition: catalog.c:193
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:538
Oid GetSessionUserId(void)
Definition: miscinit.c:317
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:328
bool IsBinaryUpgrade
Definition: globals.c:101
Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
Definition: user.c:72
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:156
int errdetail_internal(const char *fmt,...)
Definition: elog.c:900
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5096
#define AuthIdRelationId
Definition: pg_authid.h:42
#define HeapTupleSetOid(tuple, oid)
Definition: htup_details.h:698
#define Natts_pg_auth_members
#define list_make1(x1)
Definition: pg_list.h:139
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:72
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:416
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:174
Oid GetOuterUserId(void)
Definition: miscinit.c:294
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
Oid CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:162
void GrantRole(GrantRoleStmt *stmt)
Definition: user.c:1240
#define Anum_pg_authid_rolvaliduntil
Definition: pg_authid.h:89
static void AddRoleMems(const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, Oid grantorId, bool admin_opt)
Definition: user.c:1391
void shdepLockAndCheckObject(Oid classId, Oid objectId)
Definition: pg_shdepend.c:987
ItemPointerData t_self
Definition: htup.h:65
#define lfirst_node(type, lc)
Definition: pg_list.h:109
#define NoLock
Definition: lockdefs.h:34
void shdepReassignOwned(List *roleids, Oid newrole)
Definition: pg_shdepend.c:1285
#define Anum_pg_authid_rolsuper
Definition: pg_authid.h:80
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
Definition: aclchk.c:3399
int location
Definition: parsenodes.h:723
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define Anum_pg_auth_members_grantor
#define CStringGetDatum(X)
Definition: postgres.h:584
#define Anum_pg_authid_rolcanlogin
Definition: pg_authid.h:84
int errdetail_log(const char *fmt,...)
Definition: elog.c:921
#define Anum_pg_authid_rolconnlimit
Definition: pg_authid.h:87
DropBehavior behavior
Definition: parsenodes.h:3287
#define ereport(elevel, rest)
Definition: elog.h:122
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:163
RoleSpec * grantor
Definition: parsenodes.h:1881
bool pg_database_ownercheck(Oid db_oid, Oid roleid)
Definition: aclchk.c:4964
bool superuser_arg(Oid roleid)
Definition: superuser.c:57
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:588
Node * arg
Definition: parsenodes.h:721
char * get_rolespec_name(const RoleSpec *role)
Definition: acl.c:5211
#define AuthMemRoleMemIndexId
Definition: indexing.h:102
#define WARNING
Definition: elog.h:40
Oid AlterRole(AlterRoleStmt *stmt)
Definition: user.c:482
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
#define Anum_pg_authid_rolbypassrls
Definition: pg_authid.h:86
#define TextDatumGetCString(d)
Definition: builtins.h:92
#define Anum_pg_auth_members_roleid
uintptr_t Datum
Definition: postgres.h:372
void CommandCounterIncrement(void)
Definition: xact.c:922
void check_rolespec_name(const RoleSpec *role, const char *detail_msg)
Definition: acl.c:5233
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1117
RoleSpecType roletype
Definition: parsenodes.h:328
Oid AlterRoleSet(AlterRoleSetStmt *stmt)
Definition: user.c:852
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1279
#define list_make1_oid(x1)
Definition: pg_list.h:151
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5129
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1284
FormData_pg_auth_members * Form_pg_auth_members
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:871
#define Anum_pg_authid_rolcreatedb
Definition: pg_authid.h:83
VariableSetStmt * setstmt
Definition: parsenodes.h:2416
char * encrypt_password(PasswordType target_type, const char *role, const char *password)
Definition: crypt.c:116
#define BoolGetDatum(X)
Definition: postgres.h:408
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:2009
#define InvalidOid
Definition: postgres_ext.h:36
ObjectAddress RenameRole(const char *oldname, const char *newname)
Definition: user.c:1109
#define NOTICE
Definition: elog.h:37
List * roleSpecsToIds(List *memberNames)
Definition: user.c:1362
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
void DeleteSharedComments(Oid oid, Oid classoid)
Definition: comment.c:373
List * options
Definition: parsenodes.h:2407
#define AuthMemMemRoleIndexId
Definition: indexing.h:104
HeapTuple get_rolespec_tuple(const RoleSpec *role)
Definition: acl.c:5167
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:210
static int list_length(const List *l)
Definition: pg_list.h:89
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
RoleSpec * newrole
Definition: parsenodes.h:3297
char * rolename
Definition: parsenodes.h:329
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
void DeleteSharedSecurityLabel(Oid objectId, Oid classId)
Definition: seclabel.c:414
#define Anum_pg_authid_rolname
Definition: pg_authid.h:79
#define AccessExclusiveLock
Definition: lockdefs.h:46
#define Int32GetDatum(X)
Definition: postgres.h:485
bool is_member_of_role_nosuper(Oid member, Oid role)
Definition: acl.c:4875
Datum timestamptz_in(PG_FUNCTION_ARGS)
Definition: timestamp.c:383
#define intVal(v)
Definition: value.h:52
Oid createdb(ParseState *pstate, const CreatedbStmt *stmt)
Definition: dbcommands.c:99
int errmsg(const char *fmt,...)
Definition: elog.c:797
void ReassignOwnedObjects(ReassignOwnedStmt *stmt)
Definition: user.c:1325
static bool have_createrole_privilege(void)
Definition: user.c:62
int i
#define NameStr(name)
Definition: c.h:499
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
#define Anum_pg_auth_members_admin_option
#define CStringGetTextDatum(s)
Definition: builtins.h:91
void DropRole(DropRoleStmt *stmt)
Definition: user.c:932
char * defname
Definition: parsenodes.h:720
#define Anum_pg_authid_rolcreaterole
Definition: pg_authid.h:82
List * grantee_roles
Definition: parsenodes.h:1878
#define elog
Definition: elog.h:219
bool checkSharedDependencies(Oid classId, Oid objectId, char **detail_msg, char **detail_log_msg)
Definition: pg_shdepend.c:522
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:791
check_password_hook_type check_password_hook
Definition: user.c:50
void DropSetting(Oid databaseid, Oid roleid)
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:31
Definition: pg_list.h:45
#define Anum_pg_authid_rolinherit
Definition: pg_authid.h:81
#define BTEqualStrategyNumber
Definition: stratnum.h:31
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
char * priv_name
Definition: parsenodes.h:1861
#define lfirst_oid(lc)
Definition: pg_list.h:108
#define Natts_pg_authid
Definition: pg_authid.h:78
static void DelRoleMems(const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, bool admin_opt)
Definition: user.c:1535
#define Anum_pg_auth_members_member
#define SearchSysCache2(cacheId, key1, key2)
Definition: syscache.h:158