PostgreSQL Source Code  git master
user.c File Reference
#include "postgres.h"
#include "access/genam.h"
#include "access/htup_details.h"
#include "access/table.h"
#include "access/xact.h"
#include "catalog/binary_upgrade.h"
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_auth_members.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_database.h"
#include "catalog/pg_db_role_setting.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/seclabel.h"
#include "commands/user.h"
#include "libpq/crypt.h"
#include "miscadmin.h"
#include "storage/lmgr.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/syscache.h"
#include "utils/timestamp.h"
Include dependency graph for user.c:

Go to the source code of this file.

Functions

static void AddRoleMems (const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, Oid grantorId, bool admin_opt)
 
static void DelRoleMems (const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, bool admin_opt)
 
static bool have_createrole_privilege (void)
 
Oid CreateRole (ParseState *pstate, CreateRoleStmt *stmt)
 
Oid AlterRole (ParseState *pstate, AlterRoleStmt *stmt)
 
Oid AlterRoleSet (AlterRoleSetStmt *stmt)
 
void DropRole (DropRoleStmt *stmt)
 
ObjectAddress RenameRole (const char *oldname, const char *newname)
 
void GrantRole (GrantRoleStmt *stmt)
 
void DropOwnedObjects (DropOwnedStmt *stmt)
 
void ReassignOwnedObjects (ReassignOwnedStmt *stmt)
 
ListroleSpecsToIds (List *memberNames)
 

Variables

Oid binary_upgrade_next_pg_authid_oid = InvalidOid
 
int Password_encryption = PASSWORD_TYPE_SCRAM_SHA_256
 
check_password_hook_type check_password_hook = NULL
 

Function Documentation

◆ AddRoleMems()

static void AddRoleMems ( const char *  rolename,
Oid  roleid,
List memberSpecs,
List memberIds,
Oid  grantorId,
bool  admin_opt 
)
static

Definition at line 1403 of file user.c.

References admin_option, Assert, AUTHMEMROLEMEM, BoolGetDatum, CatalogTupleInsert(), CatalogTupleUpdate(), CommandCounterIncrement(), ereport, errcode(), errmsg(), ERROR, forboth, get_rolespec_name(), GETSTRUCT, GetUserId(), have_createrole_privilege(), heap_form_tuple(), heap_modify_tuple(), HeapTupleIsValid, is_admin_of_role(), is_member_of_role_nosuper(), lfirst_node, lfirst_oid, list_length(), MemSet, NoLock, NOTICE, ObjectIdGetDatum, RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache2(), superuser(), superuser_arg(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by AlterRole(), CreateRole(), and GrantRole().

1406 {
1407  Relation pg_authmem_rel;
1408  TupleDesc pg_authmem_dsc;
1409  ListCell *specitem;
1410  ListCell *iditem;
1411 
1412  Assert(list_length(memberSpecs) == list_length(memberIds));
1413 
1414  /* Skip permission check if nothing to do */
1415  if (!memberIds)
1416  return;
1417 
1418  /*
1419  * Check permissions: must have createrole or admin option on the role to
1420  * be changed. To mess with a superuser role, you gotta be superuser.
1421  */
1422  if (superuser_arg(roleid))
1423  {
1424  if (!superuser())
1425  ereport(ERROR,
1426  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1427  errmsg("must be superuser to alter superusers")));
1428  }
1429  else
1430  {
1431  if (!have_createrole_privilege() &&
1432  !is_admin_of_role(grantorId, roleid))
1433  ereport(ERROR,
1434  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1435  errmsg("must have admin option on role \"%s\"",
1436  rolename)));
1437  }
1438 
1439  /*
1440  * The charter of pg_database_owner is to have exactly one, implicit,
1441  * situation-dependent member. There's no technical need for this
1442  * restriction. (One could lift it and take the further step of making
1443  * pg_database_ownercheck() equivalent to has_privs_of_role(roleid,
1444  * ROLE_PG_DATABASE_OWNER), in which case explicit, situation-independent
1445  * members could act as the owner of any database.)
1446  */
1447  if (roleid == ROLE_PG_DATABASE_OWNER)
1448  ereport(ERROR,
1449  errmsg("role \"%s\" cannot have explicit members", rolename));
1450 
1451  /*
1452  * The role membership grantor of record has little significance at
1453  * present. Nonetheless, inasmuch as users might look to it for a crude
1454  * audit trail, let only superusers impute the grant to a third party.
1455  *
1456  * Before lifting this restriction, give the member == role case of
1457  * is_admin_of_role() a fresh look. Ensure that the current role cannot
1458  * use an explicit grantor specification to take advantage of the session
1459  * user's self-admin right.
1460  */
1461  if (grantorId != GetUserId() && !superuser())
1462  ereport(ERROR,
1463  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1464  errmsg("must be superuser to set grantor")));
1465 
1466  pg_authmem_rel = table_open(AuthMemRelationId, RowExclusiveLock);
1467  pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
1468 
1469  forboth(specitem, memberSpecs, iditem, memberIds)
1470  {
1471  RoleSpec *memberRole = lfirst_node(RoleSpec, specitem);
1472  Oid memberid = lfirst_oid(iditem);
1473  HeapTuple authmem_tuple;
1474  HeapTuple tuple;
1475  Datum new_record[Natts_pg_auth_members];
1476  bool new_record_nulls[Natts_pg_auth_members];
1477  bool new_record_repl[Natts_pg_auth_members];
1478 
1479  /*
1480  * pg_database_owner is never a role member. Lifting this restriction
1481  * would require a policy decision about membership loops. One could
1482  * prevent loops, which would include making "ALTER DATABASE x OWNER
1483  * TO proposed_datdba" fail if is_member_of_role(pg_database_owner,
1484  * proposed_datdba). Hence, gaining a membership could reduce what a
1485  * role could do. Alternately, one could allow these memberships to
1486  * complete loops. A role could then have actual WITH ADMIN OPTION on
1487  * itself, prompting a decision about is_admin_of_role() treatment of
1488  * the case.
1489  *
1490  * Lifting this restriction also has policy implications for ownership
1491  * of shared objects (databases and tablespaces). We allow such
1492  * ownership, but we might find cause to ban it in the future.
1493  * Designing such a ban would more troublesome if the design had to
1494  * address pg_database_owner being a member of role FOO that owns a
1495  * shared object. (The effect of such ownership is that any owner of
1496  * another database can act as the owner of affected shared objects.)
1497  */
1498  if (memberid == ROLE_PG_DATABASE_OWNER)
1499  ereport(ERROR,
1500  errmsg("role \"%s\" cannot be a member of any role",
1501  get_rolespec_name(memberRole)));
1502 
1503  /*
1504  * Refuse creation of membership loops, including the trivial case
1505  * where a role is made a member of itself. We do this by checking to
1506  * see if the target role is already a member of the proposed member
1507  * role. We have to ignore possible superuserness, however, else we
1508  * could never grant membership in a superuser-privileged role.
1509  */
1510  if (is_member_of_role_nosuper(roleid, memberid))
1511  ereport(ERROR,
1512  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1513  errmsg("role \"%s\" is a member of role \"%s\"",
1514  rolename, get_rolespec_name(memberRole))));
1515 
1516  /*
1517  * Check if entry for this role/member already exists; if so, give
1518  * warning unless we are adding admin option.
1519  */
1520  authmem_tuple = SearchSysCache2(AUTHMEMROLEMEM,
1521  ObjectIdGetDatum(roleid),
1522  ObjectIdGetDatum(memberid));
1523  if (HeapTupleIsValid(authmem_tuple) &&
1524  (!admin_opt ||
1525  ((Form_pg_auth_members) GETSTRUCT(authmem_tuple))->admin_option))
1526  {
1527  ereport(NOTICE,
1528  (errmsg("role \"%s\" is already a member of role \"%s\"",
1529  get_rolespec_name(memberRole), rolename)));
1530  ReleaseSysCache(authmem_tuple);
1531  continue;
1532  }
1533 
1534  /* Build a tuple to insert or update */
1535  MemSet(new_record, 0, sizeof(new_record));
1536  MemSet(new_record_nulls, false, sizeof(new_record_nulls));
1537  MemSet(new_record_repl, false, sizeof(new_record_repl));
1538 
1539  new_record[Anum_pg_auth_members_roleid - 1] = ObjectIdGetDatum(roleid);
1540  new_record[Anum_pg_auth_members_member - 1] = ObjectIdGetDatum(memberid);
1541  new_record[Anum_pg_auth_members_grantor - 1] = ObjectIdGetDatum(grantorId);
1542  new_record[Anum_pg_auth_members_admin_option - 1] = BoolGetDatum(admin_opt);
1543 
1544  if (HeapTupleIsValid(authmem_tuple))
1545  {
1546  new_record_repl[Anum_pg_auth_members_grantor - 1] = true;
1547  new_record_repl[Anum_pg_auth_members_admin_option - 1] = true;
1548  tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
1549  new_record,
1550  new_record_nulls, new_record_repl);
1551  CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple);
1552  ReleaseSysCache(authmem_tuple);
1553  }
1554  else
1555  {
1556  tuple = heap_form_tuple(pg_authmem_dsc,
1557  new_record, new_record_nulls);
1558  CatalogTupleInsert(pg_authmem_rel, tuple);
1559  }
1560 
1561  /* CCI after each change, in case there are duplicates in list */
1563  }
1564 
1565  /*
1566  * Close pg_authmem, but keep lock till commit.
1567  */
1568  table_close(pg_authmem_rel, NoLock);
1569 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:495
bool is_admin_of_role(Oid member, Oid role)
Definition: acl.c:4931
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
#define MemSet(start, val, len)
Definition: c.h:1008
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define lfirst_node(type, lc)
Definition: pg_list.h:172
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
char * get_rolespec_name(const RoleSpec *role)
Definition: acl.c:5213
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1022
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
FormData_pg_auth_members * Form_pg_auth_members
bool admin_option
#define BoolGetDatum(X)
Definition: postgres.h:446
#define ereport(elevel,...)
Definition: elog.h:157
#define NOTICE
Definition: elog.h:37
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
static int list_length(const List *l)
Definition: pg_list.h:149
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1138
bool is_member_of_role_nosuper(Oid member, Oid role)
Definition: acl.c:4909
int errmsg(const char *fmt,...)
Definition: elog.c:909
static bool have_createrole_privilege(void)
Definition: user.c:62
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
#define lfirst_oid(lc)
Definition: pg_list.h:171

◆ AlterRole()

Oid AlterRole ( ParseState pstate,
AlterRoleStmt stmt 
)

Definition at line 493 of file user.c.

References AlterRoleStmt::action, AddRoleMems(), DefElem::arg, AUTHNAME, BoolGetDatum, CatalogTupleUpdate(), check_password_hook, check_rolespec_name(), CommandCounterIncrement(), createdb(), CStringGetDatum, CStringGetTextDatum, DefElem::defname, DelRoleMems(), DirectFunctionCall3, elog, encrypt_password(), ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), get_password_type(), get_rolespec_tuple(), GETSTRUCT, GetUserId(), have_createrole_privilege(), heap_freetuple(), heap_modify_tuple(), Int32GetDatum, intVal, InvalidOid, InvokeObjectPostAlterHook, lfirst, MemSet, NameStr, NIL, NoLock, NOTICE, ObjectIdGetDatum, AlterRoleStmt::options, password, Password_encryption, plain_crypt_verify(), pstrdup(), RelationGetDescr, ReleaseSysCache(), AlterRoleStmt::role, roleSpecsToIds(), RowExclusiveLock, STATUS_OK, strVal, superuser(), SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), and timestamptz_in().

Referenced by standard_ProcessUtility().

494 {
495  Datum new_record[Natts_pg_authid];
496  bool new_record_nulls[Natts_pg_authid];
497  bool new_record_repl[Natts_pg_authid];
498  Relation pg_authid_rel;
499  TupleDesc pg_authid_dsc;
500  HeapTuple tuple,
501  new_tuple;
502  Form_pg_authid authform;
503  ListCell *option;
504  char *rolename = NULL;
505  char *password = NULL; /* user password */
506  int issuper = -1; /* Make the user a superuser? */
507  int inherit = -1; /* Auto inherit privileges? */
508  int createrole = -1; /* Can this user create roles? */
509  int createdb = -1; /* Can the user create databases? */
510  int canlogin = -1; /* Can this user login? */
511  int isreplication = -1; /* Is this a replication role? */
512  int connlimit = -1; /* maximum connections allowed */
513  List *rolemembers = NIL; /* roles to be added/removed */
514  char *validUntil = NULL; /* time the login is valid until */
515  Datum validUntil_datum; /* same, as timestamptz Datum */
516  bool validUntil_null;
517  int bypassrls = -1;
518  DefElem *dpassword = NULL;
519  DefElem *dissuper = NULL;
520  DefElem *dinherit = NULL;
521  DefElem *dcreaterole = NULL;
522  DefElem *dcreatedb = NULL;
523  DefElem *dcanlogin = NULL;
524  DefElem *disreplication = NULL;
525  DefElem *dconnlimit = NULL;
526  DefElem *drolemembers = NULL;
527  DefElem *dvalidUntil = NULL;
528  DefElem *dbypassRLS = NULL;
529  Oid roleid;
530 
532  "Cannot alter reserved roles.");
533 
534  /* Extract options from the statement node tree */
535  foreach(option, stmt->options)
536  {
537  DefElem *defel = (DefElem *) lfirst(option);
538 
539  if (strcmp(defel->defname, "password") == 0)
540  {
541  if (dpassword)
542  errorConflictingDefElem(defel, pstate);
543  dpassword = defel;
544  }
545  else if (strcmp(defel->defname, "superuser") == 0)
546  {
547  if (dissuper)
548  errorConflictingDefElem(defel, pstate);
549  dissuper = defel;
550  }
551  else if (strcmp(defel->defname, "inherit") == 0)
552  {
553  if (dinherit)
554  errorConflictingDefElem(defel, pstate);
555  dinherit = defel;
556  }
557  else if (strcmp(defel->defname, "createrole") == 0)
558  {
559  if (dcreaterole)
560  errorConflictingDefElem(defel, pstate);
561  dcreaterole = defel;
562  }
563  else if (strcmp(defel->defname, "createdb") == 0)
564  {
565  if (dcreatedb)
566  errorConflictingDefElem(defel, pstate);
567  dcreatedb = defel;
568  }
569  else if (strcmp(defel->defname, "canlogin") == 0)
570  {
571  if (dcanlogin)
572  errorConflictingDefElem(defel, pstate);
573  dcanlogin = defel;
574  }
575  else if (strcmp(defel->defname, "isreplication") == 0)
576  {
577  if (disreplication)
578  errorConflictingDefElem(defel, pstate);
579  disreplication = defel;
580  }
581  else if (strcmp(defel->defname, "connectionlimit") == 0)
582  {
583  if (dconnlimit)
584  errorConflictingDefElem(defel, pstate);
585  dconnlimit = defel;
586  }
587  else if (strcmp(defel->defname, "rolemembers") == 0 &&
588  stmt->action != 0)
589  {
590  if (drolemembers)
591  errorConflictingDefElem(defel, pstate);
592  drolemembers = defel;
593  }
594  else if (strcmp(defel->defname, "validUntil") == 0)
595  {
596  if (dvalidUntil)
597  errorConflictingDefElem(defel, pstate);
598  dvalidUntil = defel;
599  }
600  else if (strcmp(defel->defname, "bypassrls") == 0)
601  {
602  if (dbypassRLS)
603  errorConflictingDefElem(defel, pstate);
604  dbypassRLS = defel;
605  }
606  else
607  elog(ERROR, "option \"%s\" not recognized",
608  defel->defname);
609  }
610 
611  if (dpassword && dpassword->arg)
612  password = strVal(dpassword->arg);
613  if (dissuper)
614  issuper = intVal(dissuper->arg);
615  if (dinherit)
616  inherit = intVal(dinherit->arg);
617  if (dcreaterole)
618  createrole = intVal(dcreaterole->arg);
619  if (dcreatedb)
620  createdb = intVal(dcreatedb->arg);
621  if (dcanlogin)
622  canlogin = intVal(dcanlogin->arg);
623  if (disreplication)
624  isreplication = intVal(disreplication->arg);
625  if (dconnlimit)
626  {
627  connlimit = intVal(dconnlimit->arg);
628  if (connlimit < -1)
629  ereport(ERROR,
630  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
631  errmsg("invalid connection limit: %d", connlimit)));
632  }
633  if (drolemembers)
634  rolemembers = (List *) drolemembers->arg;
635  if (dvalidUntil)
636  validUntil = strVal(dvalidUntil->arg);
637  if (dbypassRLS)
638  bypassrls = intVal(dbypassRLS->arg);
639 
640  /*
641  * Scan the pg_authid relation to be certain the user exists.
642  */
643  pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
644  pg_authid_dsc = RelationGetDescr(pg_authid_rel);
645 
646  tuple = get_rolespec_tuple(stmt->role);
647  authform = (Form_pg_authid) GETSTRUCT(tuple);
648  rolename = pstrdup(NameStr(authform->rolname));
649  roleid = authform->oid;
650 
651  /*
652  * To mess with a superuser or replication role in any way you gotta be
653  * superuser. We also insist on superuser to change the BYPASSRLS
654  * property. Otherwise, if you don't have createrole, you're only allowed
655  * to change your own password.
656  */
657  if (authform->rolsuper || issuper >= 0)
658  {
659  if (!superuser())
660  ereport(ERROR,
661  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
662  errmsg("must be superuser to alter superuser roles or change superuser attribute")));
663  }
664  else if (authform->rolreplication || isreplication >= 0)
665  {
666  if (!superuser())
667  ereport(ERROR,
668  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
669  errmsg("must be superuser to alter replication roles or change replication attribute")));
670  }
671  else if (bypassrls >= 0)
672  {
673  if (!superuser())
674  ereport(ERROR,
675  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
676  errmsg("must be superuser to change bypassrls attribute")));
677  }
678  else if (!have_createrole_privilege())
679  {
680  /* We already checked issuper, isreplication, and bypassrls */
681  if (!(inherit < 0 &&
682  createrole < 0 &&
683  createdb < 0 &&
684  canlogin < 0 &&
685  !dconnlimit &&
686  !rolemembers &&
687  !validUntil &&
688  dpassword &&
689  roleid == GetUserId()))
690  ereport(ERROR,
691  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
692  errmsg("permission denied")));
693  }
694 
695  /* Convert validuntil to internal form */
696  if (validUntil)
697  {
698  validUntil_datum = DirectFunctionCall3(timestamptz_in,
699  CStringGetDatum(validUntil),
701  Int32GetDatum(-1));
702  validUntil_null = false;
703  }
704  else
705  {
706  /* fetch existing setting in case hook needs it */
707  validUntil_datum = SysCacheGetAttr(AUTHNAME, tuple,
708  Anum_pg_authid_rolvaliduntil,
709  &validUntil_null);
710  }
711 
712  /*
713  * Call the password checking hook if there is one defined
714  */
715  if (check_password_hook && password)
716  (*check_password_hook) (rolename,
717  password,
718  get_password_type(password),
719  validUntil_datum,
720  validUntil_null);
721 
722  /*
723  * Build an updated tuple, perusing the information just obtained
724  */
725  MemSet(new_record, 0, sizeof(new_record));
726  MemSet(new_record_nulls, false, sizeof(new_record_nulls));
727  MemSet(new_record_repl, false, sizeof(new_record_repl));
728 
729  /*
730  * issuper/createrole/etc
731  */
732  if (issuper >= 0)
733  {
734  new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper > 0);
735  new_record_repl[Anum_pg_authid_rolsuper - 1] = true;
736  }
737 
738  if (inherit >= 0)
739  {
740  new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit > 0);
741  new_record_repl[Anum_pg_authid_rolinherit - 1] = true;
742  }
743 
744  if (createrole >= 0)
745  {
746  new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole > 0);
747  new_record_repl[Anum_pg_authid_rolcreaterole - 1] = true;
748  }
749 
750  if (createdb >= 0)
751  {
752  new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb > 0);
753  new_record_repl[Anum_pg_authid_rolcreatedb - 1] = true;
754  }
755 
756  if (canlogin >= 0)
757  {
758  new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin > 0);
759  new_record_repl[Anum_pg_authid_rolcanlogin - 1] = true;
760  }
761 
762  if (isreplication >= 0)
763  {
764  new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication > 0);
765  new_record_repl[Anum_pg_authid_rolreplication - 1] = true;
766  }
767 
768  if (dconnlimit)
769  {
770  new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
771  new_record_repl[Anum_pg_authid_rolconnlimit - 1] = true;
772  }
773 
774  /* password */
775  if (password)
776  {
777  char *shadow_pass;
778  char *logdetail;
779 
780  /* Like in CREATE USER, don't allow an empty password. */
781  if (password[0] == '\0' ||
782  plain_crypt_verify(rolename, password, "", &logdetail) == STATUS_OK)
783  {
784  ereport(NOTICE,
785  (errmsg("empty string is not a valid password, clearing password")));
786  new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
787  }
788  else
789  {
790  /* Encrypt the password to the requested format. */
791  shadow_pass = encrypt_password(Password_encryption, rolename,
792  password);
793  new_record[Anum_pg_authid_rolpassword - 1] =
794  CStringGetTextDatum(shadow_pass);
795  }
796  new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
797  }
798 
799  /* unset password */
800  if (dpassword && dpassword->arg == NULL)
801  {
802  new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
803  new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
804  }
805 
806  /* valid until */
807  new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
808  new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
809  new_record_repl[Anum_pg_authid_rolvaliduntil - 1] = true;
810 
811  if (bypassrls >= 0)
812  {
813  new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(bypassrls > 0);
814  new_record_repl[Anum_pg_authid_rolbypassrls - 1] = true;
815  }
816 
817  new_tuple = heap_modify_tuple(tuple, pg_authid_dsc, new_record,
818  new_record_nulls, new_record_repl);
819  CatalogTupleUpdate(pg_authid_rel, &tuple->t_self, new_tuple);
820 
821  InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
822 
823  ReleaseSysCache(tuple);
824  heap_freetuple(new_tuple);
825 
826  /*
827  * Advance command counter so we can see new record; else tests in
828  * AddRoleMems may fail.
829  */
830  if (rolemembers)
832 
833  if (stmt->action == +1) /* add members to role */
834  AddRoleMems(rolename, roleid,
835  rolemembers, roleSpecsToIds(rolemembers),
836  GetUserId(), false);
837  else if (stmt->action == -1) /* drop members from role */
838  DelRoleMems(rolename, roleid,
839  rolemembers, roleSpecsToIds(rolemembers),
840  false);
841 
842  /*
843  * Close pg_authid, but keep lock till commit.
844  */
845  table_close(pg_authid_rel, NoLock);
846 
847  return roleid;
848 }
#define NIL
Definition: pg_list.h:65
RoleSpec * role
Definition: parsenodes.h:2629
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:495
int Password_encryption
Definition: user.c:47
char * pstrdup(const char *in)
Definition: mcxt.c:1299
char * encrypt_password(PasswordType target_type, const char *role, const char *password)
Definition: crypt.c:114
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, char **logdetail)
Definition: crypt.c:222
#define strVal(v)
Definition: value.h:65
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
#define MemSet(start, val, len)
Definition: c.h:1008
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
unsigned int Oid
Definition: postgres_ext.h:31
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
static void AddRoleMems(const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, Oid grantorId, bool admin_opt)
Definition: user.c:1403
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
#define CStringGetDatum(X)
Definition: postgres.h:622
static char * password
Definition: streamutil.c:53
#define STATUS_OK
Definition: c.h:1170
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:630
Node * arg
Definition: parsenodes.h:759
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1022
void check_rolespec_name(const RoleSpec *role, const char *detail_msg)
Definition: acl.c:5235
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1388
#define BoolGetDatum(X)
Definition: postgres.h:446
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:350
#define NOTICE
Definition: elog.h:37
List * roleSpecsToIds(List *memberNames)
Definition: user.c:1376
#define lfirst(lc)
Definition: pg_list.h:169
List * options
Definition: parsenodes.h:2630
HeapTuple get_rolespec_tuple(const RoleSpec *role)
Definition: acl.c:5167
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define Int32GetDatum(X)
Definition: postgres.h:523
Datum timestamptz_in(PG_FUNCTION_ARGS)
Definition: timestamp.c:403
#define intVal(v)
Definition: value.h:63
Oid createdb(ParseState *pstate, const CreatedbStmt *stmt)
Definition: dbcommands.c:100
int errmsg(const char *fmt,...)
Definition: elog.c:909
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:89
#define elog(elevel,...)
Definition: elog.h:232
static bool have_createrole_privilege(void)
Definition: user.c:62
#define NameStr(name)
Definition: c.h:681
#define CStringGetTextDatum(s)
Definition: builtins.h:86
char * defname
Definition: parsenodes.h:758
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
check_password_hook_type check_password_hook
Definition: user.c:50
Definition: pg_list.h:50
static void DelRoleMems(const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, bool admin_opt)
Definition: user.c:1581

◆ AlterRoleSet()

Oid AlterRoleSet ( AlterRoleSetStmt stmt)

Definition at line 855 of file user.c.

References aclcheck_error(), ACLCHECK_NOT_OWNER, AlterSetting(), check_rolespec_name(), AlterRoleSetStmt::database, ereport, errcode(), errmsg(), ERROR, get_database_oid(), get_rolespec_tuple(), GETSTRUCT, GetUserId(), have_createrole_privilege(), InvalidOid, OBJECT_DATABASE, pg_database_ownercheck(), ReleaseSysCache(), AlterRoleSetStmt::role, AlterRoleSetStmt::setstmt, shdepLockAndCheckObject(), and superuser().

Referenced by standard_ProcessUtility().

856 {
857  HeapTuple roletuple;
858  Form_pg_authid roleform;
859  Oid databaseid = InvalidOid;
860  Oid roleid = InvalidOid;
861 
862  if (stmt->role)
863  {
865  "Cannot alter reserved roles.");
866 
867  roletuple = get_rolespec_tuple(stmt->role);
868  roleform = (Form_pg_authid) GETSTRUCT(roletuple);
869  roleid = roleform->oid;
870 
871  /*
872  * Obtain a lock on the role and make sure it didn't go away in the
873  * meantime.
874  */
875  shdepLockAndCheckObject(AuthIdRelationId, roleid);
876 
877  /*
878  * To mess with a superuser you gotta be superuser; else you need
879  * createrole, or just want to change your own settings
880  */
881  if (roleform->rolsuper)
882  {
883  if (!superuser())
884  ereport(ERROR,
885  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
886  errmsg("must be superuser to alter superusers")));
887  }
888  else
889  {
890  if (!have_createrole_privilege() && roleid != GetUserId())
891  ereport(ERROR,
892  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
893  errmsg("permission denied")));
894  }
895 
896  ReleaseSysCache(roletuple);
897  }
898 
899  /* look up and lock the database, if specified */
900  if (stmt->database != NULL)
901  {
902  databaseid = get_database_oid(stmt->database, false);
903  shdepLockAndCheckObject(DatabaseRelationId, databaseid);
904 
905  if (!stmt->role)
906  {
907  /*
908  * If no role is specified, then this is effectively the same as
909  * ALTER DATABASE ... SET, so use the same permission check.
910  */
911  if (!pg_database_ownercheck(databaseid, GetUserId()))
913  stmt->database);
914  }
915  }
916 
917  if (!stmt->role && !stmt->database)
918  {
919  /* Must be superuser to alter settings globally. */
920  if (!superuser())
921  ereport(ERROR,
922  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
923  errmsg("must be superuser to alter settings globally")));
924  }
925 
926  AlterSetting(databaseid, roleid, stmt->setstmt);
927 
928  return roleid;
929 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
Oid GetUserId(void)
Definition: miscinit.c:495
void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
RoleSpec * role
Definition: parsenodes.h:2637
unsigned int Oid
Definition: postgres_ext.h:31
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
#define ERROR
Definition: elog.h:46
void shdepLockAndCheckObject(Oid classId, Oid objectId)
Definition: pg_shdepend.c:1161
bool pg_database_ownercheck(Oid db_oid, Oid roleid)
Definition: aclchk.c:5236
void check_rolespec_name(const RoleSpec *role, const char *detail_msg)
Definition: acl.c:5235
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
VariableSetStmt * setstmt
Definition: parsenodes.h:2639
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:2066
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
HeapTuple get_rolespec_tuple(const RoleSpec *role)
Definition: acl.c:5167
int errmsg(const char *fmt,...)
Definition: elog.c:909
static bool have_createrole_privilege(void)
Definition: user.c:62

◆ CreateRole()

Oid CreateRole ( ParseState pstate,
CreateRoleStmt stmt 
)

Definition at line 72 of file user.c.

References AddRoleMems(), DefElem::arg, binary_upgrade_next_pg_authid_oid, BoolGetDatum, CatalogTupleInsert(), check_password_hook, CommandCounterIncrement(), createdb(), CStringGetDatum, CStringGetTextDatum, DefElem::defname, DirectFunctionCall1, DirectFunctionCall3, elog, encrypt_password(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errdetail(), errmsg(), ERROR, errorConflictingDefElem(), get_password_type(), get_role_oid(), get_rolespec_tuple(), GetNewOidWithIndex(), GETSTRUCT, GetUserId(), have_createrole_privilege(), heap_form_tuple(), Int32GetDatum, intVal, InvalidOid, InvokeObjectPostCreateHook, IsBinaryUpgrade, IsReservedName(), lfirst, list_make1, list_make1_oid, RoleSpec::location, makeNode, MemSet, namein(), NameStr, NIL, NoLock, NOTICE, ObjectIdGetDatum, OidIsValid, CreateRoleStmt::options, password, Password_encryption, plain_crypt_verify(), RelationGetDescr, ReleaseSysCache(), CreateRoleStmt::role, RoleSpec::rolename, ROLESPEC_CSTRING, roleSpecsToIds(), ROLESTMT_GROUP, ROLESTMT_ROLE, ROLESTMT_USER, RoleSpec::roletype, RowExclusiveLock, STATUS_OK, CreateRoleStmt::stmt_type, strVal, superuser(), table_close(), table_open(), timestamptz_in(), and WARNING.

Referenced by standard_ProcessUtility().

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 role? */
90  int connlimit = -1; /* maximum connections allowed */
91  List *addroleto = NIL; /* roles to make this a member of */
92  List *rolemembers = NIL; /* roles to be members of this role */
93  List *adminmembers = NIL; /* roles to be admins of this role */
94  char *validUntil = NULL; /* time the login is valid until */
95  Datum validUntil_datum; /* same, as timestamptz Datum */
96  bool validUntil_null;
97  DefElem *dpassword = NULL;
98  DefElem *dissuper = NULL;
99  DefElem *dinherit = NULL;
100  DefElem *dcreaterole = NULL;
101  DefElem *dcreatedb = NULL;
102  DefElem *dcanlogin = NULL;
103  DefElem *disreplication = NULL;
104  DefElem *dconnlimit = NULL;
105  DefElem *daddroleto = NULL;
106  DefElem *drolemembers = NULL;
107  DefElem *dadminmembers = NULL;
108  DefElem *dvalidUntil = NULL;
109  DefElem *dbypassRLS = NULL;
110 
111  /* The defaults can vary depending on the original statement type */
112  switch (stmt->stmt_type)
113  {
114  case ROLESTMT_ROLE:
115  break;
116  case ROLESTMT_USER:
117  canlogin = true;
118  /* may eventually want inherit to default to false here */
119  break;
120  case ROLESTMT_GROUP:
121  break;
122  }
123 
124  /* Extract options from the statement node tree */
125  foreach(option, stmt->options)
126  {
127  DefElem *defel = (DefElem *) lfirst(option);
128 
129  if (strcmp(defel->defname, "password") == 0)
130  {
131  if (dpassword)
132  errorConflictingDefElem(defel, pstate);
133  dpassword = defel;
134  }
135  else if (strcmp(defel->defname, "sysid") == 0)
136  {
137  ereport(NOTICE,
138  (errmsg("SYSID can no longer be specified")));
139  }
140  else if (strcmp(defel->defname, "superuser") == 0)
141  {
142  if (dissuper)
143  errorConflictingDefElem(defel, pstate);
144  dissuper = defel;
145  }
146  else if (strcmp(defel->defname, "inherit") == 0)
147  {
148  if (dinherit)
149  errorConflictingDefElem(defel, pstate);
150  dinherit = defel;
151  }
152  else if (strcmp(defel->defname, "createrole") == 0)
153  {
154  if (dcreaterole)
155  errorConflictingDefElem(defel, pstate);
156  dcreaterole = defel;
157  }
158  else if (strcmp(defel->defname, "createdb") == 0)
159  {
160  if (dcreatedb)
161  errorConflictingDefElem(defel, pstate);
162  dcreatedb = defel;
163  }
164  else if (strcmp(defel->defname, "canlogin") == 0)
165  {
166  if (dcanlogin)
167  errorConflictingDefElem(defel, pstate);
168  dcanlogin = defel;
169  }
170  else if (strcmp(defel->defname, "isreplication") == 0)
171  {
172  if (disreplication)
173  errorConflictingDefElem(defel, pstate);
174  disreplication = defel;
175  }
176  else if (strcmp(defel->defname, "connectionlimit") == 0)
177  {
178  if (dconnlimit)
179  errorConflictingDefElem(defel, pstate);
180  dconnlimit = defel;
181  }
182  else if (strcmp(defel->defname, "addroleto") == 0)
183  {
184  if (daddroleto)
185  errorConflictingDefElem(defel, pstate);
186  daddroleto = defel;
187  }
188  else if (strcmp(defel->defname, "rolemembers") == 0)
189  {
190  if (drolemembers)
191  errorConflictingDefElem(defel, pstate);
192  drolemembers = defel;
193  }
194  else if (strcmp(defel->defname, "adminmembers") == 0)
195  {
196  if (dadminmembers)
197  errorConflictingDefElem(defel, pstate);
198  dadminmembers = defel;
199  }
200  else if (strcmp(defel->defname, "validUntil") == 0)
201  {
202  if (dvalidUntil)
203  errorConflictingDefElem(defel, pstate);
204  dvalidUntil = defel;
205  }
206  else if (strcmp(defel->defname, "bypassrls") == 0)
207  {
208  if (dbypassRLS)
209  errorConflictingDefElem(defel, pstate);
210  dbypassRLS = defel;
211  }
212  else
213  elog(ERROR, "option \"%s\" not recognized",
214  defel->defname);
215  }
216 
217  if (dpassword && dpassword->arg)
218  password = strVal(dpassword->arg);
219  if (dissuper)
220  issuper = intVal(dissuper->arg) != 0;
221  if (dinherit)
222  inherit = intVal(dinherit->arg) != 0;
223  if (dcreaterole)
224  createrole = intVal(dcreaterole->arg) != 0;
225  if (dcreatedb)
226  createdb = intVal(dcreatedb->arg) != 0;
227  if (dcanlogin)
228  canlogin = intVal(dcanlogin->arg) != 0;
229  if (disreplication)
230  isreplication = intVal(disreplication->arg) != 0;
231  if (dconnlimit)
232  {
233  connlimit = intVal(dconnlimit->arg);
234  if (connlimit < -1)
235  ereport(ERROR,
236  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
237  errmsg("invalid connection limit: %d", connlimit)));
238  }
239  if (daddroleto)
240  addroleto = (List *) daddroleto->arg;
241  if (drolemembers)
242  rolemembers = (List *) drolemembers->arg;
243  if (dadminmembers)
244  adminmembers = (List *) dadminmembers->arg;
245  if (dvalidUntil)
246  validUntil = strVal(dvalidUntil->arg);
247  if (dbypassRLS)
248  bypassrls = intVal(dbypassRLS->arg) != 0;
249 
250  /* Check some permissions first */
251  if (issuper)
252  {
253  if (!superuser())
254  ereport(ERROR,
255  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
256  errmsg("must be superuser to create superusers")));
257  }
258  else if (isreplication)
259  {
260  if (!superuser())
261  ereport(ERROR,
262  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
263  errmsg("must be superuser to create replication users")));
264  }
265  else if (bypassrls)
266  {
267  if (!superuser())
268  ereport(ERROR,
269  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
270  errmsg("must be superuser to create bypassrls users")));
271  }
272  else
273  {
275  ereport(ERROR,
276  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
277  errmsg("permission denied to create role")));
278  }
279 
280  /*
281  * Check that the user is not trying to create a role in the reserved
282  * "pg_" namespace.
283  */
284  if (IsReservedName(stmt->role))
285  ereport(ERROR,
286  (errcode(ERRCODE_RESERVED_NAME),
287  errmsg("role name \"%s\" is reserved",
288  stmt->role),
289  errdetail("Role names starting with \"pg_\" are reserved.")));
290 
291  /*
292  * If built with appropriate switch, whine when regression-testing
293  * conventions for role names are violated.
294  */
295 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
296  if (strncmp(stmt->role, "regress_", 8) != 0)
297  elog(WARNING, "roles created by regression test cases should have names starting with \"regress_\"");
298 #endif
299 
300  /*
301  * Check the pg_authid relation to be certain the role doesn't already
302  * exist.
303  */
304  pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
305  pg_authid_dsc = RelationGetDescr(pg_authid_rel);
306 
307  if (OidIsValid(get_role_oid(stmt->role, true)))
308  ereport(ERROR,
310  errmsg("role \"%s\" already exists",
311  stmt->role)));
312 
313  /* Convert validuntil to internal form */
314  if (validUntil)
315  {
316  validUntil_datum = DirectFunctionCall3(timestamptz_in,
317  CStringGetDatum(validUntil),
319  Int32GetDatum(-1));
320  validUntil_null = false;
321  }
322  else
323  {
324  validUntil_datum = (Datum) 0;
325  validUntil_null = true;
326  }
327 
328  /*
329  * Call the password checking hook if there is one defined
330  */
331  if (check_password_hook && password)
332  (*check_password_hook) (stmt->role,
333  password,
334  get_password_type(password),
335  validUntil_datum,
336  validUntil_null);
337 
338  /*
339  * Build a tuple to insert
340  */
341  MemSet(new_record, 0, sizeof(new_record));
342  MemSet(new_record_nulls, false, sizeof(new_record_nulls));
343 
344  new_record[Anum_pg_authid_rolname - 1] =
346 
347  new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper);
348  new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit);
349  new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole);
350  new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb);
351  new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin);
352  new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication);
353  new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
354 
355  if (password)
356  {
357  char *shadow_pass;
358  char *logdetail;
359 
360  /*
361  * Don't allow an empty password. Libpq treats an empty password the
362  * same as no password at all, and won't even try to authenticate. But
363  * other clients might, so allowing it would be confusing. By clearing
364  * the password when an empty string is specified, the account is
365  * consistently locked for all clients.
366  *
367  * Note that this only covers passwords stored in the database itself.
368  * There are also checks in the authentication code, to forbid an
369  * empty password from being used with authentication methods that
370  * fetch the password from an external system, like LDAP or PAM.
371  */
372  if (password[0] == '\0' ||
373  plain_crypt_verify(stmt->role, password, "", &logdetail) == STATUS_OK)
374  {
375  ereport(NOTICE,
376  (errmsg("empty string is not a valid password, clearing password")));
377  new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
378  }
379  else
380  {
381  /* Encrypt the password to the requested format. */
382  shadow_pass = encrypt_password(Password_encryption, stmt->role,
383  password);
384  new_record[Anum_pg_authid_rolpassword - 1] =
385  CStringGetTextDatum(shadow_pass);
386  }
387  }
388  else
389  new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
390 
391  new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
392  new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
393 
394  new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(bypassrls);
395 
396  /*
397  * pg_largeobject_metadata contains pg_authid.oid's, so we use the
398  * binary-upgrade override.
399  */
400  if (IsBinaryUpgrade)
401  {
403  ereport(ERROR,
404  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
405  errmsg("pg_authid OID value not set when in binary upgrade mode")));
406 
409  }
410  else
411  {
412  roleid = GetNewOidWithIndex(pg_authid_rel, AuthIdOidIndexId,
413  Anum_pg_authid_oid);
414  }
415 
416  new_record[Anum_pg_authid_oid - 1] = ObjectIdGetDatum(roleid);
417 
418  tuple = heap_form_tuple(pg_authid_dsc, new_record, new_record_nulls);
419 
420  /*
421  * Insert new record in the pg_authid table
422  */
423  CatalogTupleInsert(pg_authid_rel, tuple);
424 
425  /*
426  * Advance command counter so we can see new record; else tests in
427  * AddRoleMems may fail.
428  */
429  if (addroleto || adminmembers || rolemembers)
431 
432  /*
433  * Add the new role to the specified existing roles.
434  */
435  if (addroleto)
436  {
437  RoleSpec *thisrole = makeNode(RoleSpec);
438  List *thisrole_list = list_make1(thisrole);
439  List *thisrole_oidlist = list_make1_oid(roleid);
440 
441  thisrole->roletype = ROLESPEC_CSTRING;
442  thisrole->rolename = stmt->role;
443  thisrole->location = -1;
444 
445  foreach(item, addroleto)
446  {
447  RoleSpec *oldrole = lfirst(item);
448  HeapTuple oldroletup = get_rolespec_tuple(oldrole);
449  Form_pg_authid oldroleform = (Form_pg_authid) GETSTRUCT(oldroletup);
450  Oid oldroleid = oldroleform->oid;
451  char *oldrolename = NameStr(oldroleform->rolname);
452 
453  AddRoleMems(oldrolename, oldroleid,
454  thisrole_list,
455  thisrole_oidlist,
456  GetUserId(), false);
457 
458  ReleaseSysCache(oldroletup);
459  }
460  }
461 
462  /*
463  * Add the specified members to this new role. adminmembers get the admin
464  * option, rolemembers don't.
465  */
466  AddRoleMems(stmt->role, roleid,
467  adminmembers, roleSpecsToIds(adminmembers),
468  GetUserId(), true);
469  AddRoleMems(stmt->role, roleid,
470  rolemembers, roleSpecsToIds(rolemembers),
471  GetUserId(), false);
472 
473  /* Post creation hook for new role */
474  InvokeObjectPostCreateHook(AuthIdRelationId, roleid, 0);
475 
476  /*
477  * Close pg_authid, but keep lock till commit.
478  */
479  table_close(pg_authid_rel, NoLock);
480 
481  return roleid;
482 }
#define NIL
Definition: pg_list.h:65
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:381
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
Oid binary_upgrade_next_pg_authid_oid
Definition: user.c:43
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:495
int Password_encryption
Definition: user.c:47
RoleStmtType stmt_type
Definition: parsenodes.h:2621
char * encrypt_password(PasswordType target_type, const char *role, const char *password)
Definition: crypt.c:114
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, char **logdetail)
Definition: crypt.c:222
#define strVal(v)
Definition: value.h:65
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
#define MemSet(start, val, len)
Definition: c.h:1008
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:626
unsigned int Oid
Definition: postgres_ext.h:31
bool IsReservedName(const char *name)
Definition: catalog.c:218
#define OidIsValid(objectId)
Definition: c.h:710
bool IsBinaryUpgrade
Definition: globals.c:113
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5094
#define list_make1(x1)
Definition: pg_list.h:206
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
static void AddRoleMems(const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, Oid grantorId, bool admin_opt)
Definition: user.c:1403
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define CStringGetDatum(X)
Definition: postgres.h:622
static char * password
Definition: streamutil.c:53
#define STATUS_OK
Definition: c.h:1170
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:630
Node * arg
Definition: parsenodes.h:759
int location
Definition: parsenodes.h:353
#define WARNING
Definition: elog.h:40
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1022
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
RoleSpecType roletype
Definition: parsenodes.h:351
#define list_make1_oid(x1)
Definition: pg_list.h:236
#define BoolGetDatum(X)
Definition: postgres.h:446
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:350
#define NOTICE
Definition: elog.h:37
List * roleSpecsToIds(List *memberNames)
Definition: user.c:1376
#define makeNode(_type_)
Definition: nodes.h:585
#define lfirst(lc)
Definition: pg_list.h:169
HeapTuple get_rolespec_tuple(const RoleSpec *role)
Definition: acl.c:5167
char * rolename
Definition: parsenodes.h:352
#define Int32GetDatum(X)
Definition: postgres.h:523
Datum timestamptz_in(PG_FUNCTION_ARGS)
Definition: timestamp.c:403
#define intVal(v)
Definition: value.h:63
Oid createdb(ParseState *pstate, const CreatedbStmt *stmt)
Definition: dbcommands.c:100
int errmsg(const char *fmt,...)
Definition: elog.c:909
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:89
#define elog(elevel,...)
Definition: elog.h:232
static bool have_createrole_privilege(void)
Definition: user.c:62
#define NameStr(name)
Definition: c.h:681
#define CStringGetTextDatum(s)
Definition: builtins.h:86
char * defname
Definition: parsenodes.h:758
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
check_password_hook_type check_password_hook
Definition: user.c:50
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
Definition: pg_list.h:50
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221

◆ DelRoleMems()

static void DelRoleMems ( const char *  rolename,
Oid  roleid,
List memberSpecs,
List memberIds,
bool  admin_opt 
)
static

Definition at line 1581 of file user.c.

References Assert, AUTHMEMROLEMEM, BoolGetDatum, CatalogTupleDelete(), CatalogTupleUpdate(), CommandCounterIncrement(), ereport, errcode(), errmsg(), ERROR, forboth, get_rolespec_name(), GetUserId(), have_createrole_privilege(), heap_modify_tuple(), HeapTupleIsValid, is_admin_of_role(), lfirst, lfirst_oid, list_length(), MemSet, NoLock, ObjectIdGetDatum, RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache2(), superuser(), superuser_arg(), HeapTupleData::t_self, table_close(), table_open(), and WARNING.

Referenced by AlterRole(), and GrantRole().

1584 {
1585  Relation pg_authmem_rel;
1586  TupleDesc pg_authmem_dsc;
1587  ListCell *specitem;
1588  ListCell *iditem;
1589 
1590  Assert(list_length(memberSpecs) == list_length(memberIds));
1591 
1592  /* Skip permission check if nothing to do */
1593  if (!memberIds)
1594  return;
1595 
1596  /*
1597  * Check permissions: must have createrole or admin option on the role to
1598  * be changed. To mess with a superuser role, you gotta be superuser.
1599  */
1600  if (superuser_arg(roleid))
1601  {
1602  if (!superuser())
1603  ereport(ERROR,
1604  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1605  errmsg("must be superuser to alter superusers")));
1606  }
1607  else
1608  {
1609  if (!have_createrole_privilege() &&
1610  !is_admin_of_role(GetUserId(), roleid))
1611  ereport(ERROR,
1612  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1613  errmsg("must have admin option on role \"%s\"",
1614  rolename)));
1615  }
1616 
1617  pg_authmem_rel = table_open(AuthMemRelationId, RowExclusiveLock);
1618  pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
1619 
1620  forboth(specitem, memberSpecs, iditem, memberIds)
1621  {
1622  RoleSpec *memberRole = lfirst(specitem);
1623  Oid memberid = lfirst_oid(iditem);
1624  HeapTuple authmem_tuple;
1625 
1626  /*
1627  * Find entry for this role/member
1628  */
1629  authmem_tuple = SearchSysCache2(AUTHMEMROLEMEM,
1630  ObjectIdGetDatum(roleid),
1631  ObjectIdGetDatum(memberid));
1632  if (!HeapTupleIsValid(authmem_tuple))
1633  {
1634  ereport(WARNING,
1635  (errmsg("role \"%s\" is not a member of role \"%s\"",
1636  get_rolespec_name(memberRole), rolename)));
1637  continue;
1638  }
1639 
1640  if (!admin_opt)
1641  {
1642  /* Remove the entry altogether */
1643  CatalogTupleDelete(pg_authmem_rel, &authmem_tuple->t_self);
1644  }
1645  else
1646  {
1647  /* Just turn off the admin option */
1648  HeapTuple tuple;
1649  Datum new_record[Natts_pg_auth_members];
1650  bool new_record_nulls[Natts_pg_auth_members];
1651  bool new_record_repl[Natts_pg_auth_members];
1652 
1653  /* Build a tuple to update with */
1654  MemSet(new_record, 0, sizeof(new_record));
1655  MemSet(new_record_nulls, false, sizeof(new_record_nulls));
1656  MemSet(new_record_repl, false, sizeof(new_record_repl));
1657 
1658  new_record[Anum_pg_auth_members_admin_option - 1] = BoolGetDatum(false);
1659  new_record_repl[Anum_pg_auth_members_admin_option - 1] = true;
1660 
1661  tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
1662  new_record,
1663  new_record_nulls, new_record_repl);
1664  CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple);
1665  }
1666 
1667  ReleaseSysCache(authmem_tuple);
1668 
1669  /* CCI after each change, in case there are duplicates in list */
1671  }
1672 
1673  /*
1674  * Close pg_authmem, but keep lock till commit.
1675  */
1676  table_close(pg_authmem_rel, NoLock);
1677 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
#define RelationGetDescr(relation)
Definition: rel.h:503
Oid GetUserId(void)
Definition: miscinit.c:495
bool is_admin_of_role(Oid member, Oid role)
Definition: acl.c:4931
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
#define MemSet(start, val, len)
Definition: c.h:1008
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
char * get_rolespec_name(const RoleSpec *role)
Definition: acl.c:5213
#define WARNING
Definition: elog.h:40
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1022
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define BoolGetDatum(X)
Definition: postgres.h:446
#define ereport(elevel,...)
Definition: elog.h:157
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
static int list_length(const List *l)
Definition: pg_list.h:149
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
Definition: syscache.c:1138
int errmsg(const char *fmt,...)
Definition: elog.c:909
static bool have_createrole_privilege(void)
Definition: user.c:62
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define lfirst_oid(lc)
Definition: pg_list.h:171

◆ DropOwnedObjects()

void DropOwnedObjects ( DropOwnedStmt stmt)

Definition at line 1313 of file user.c.

References DropOwnedStmt::behavior, ereport, errcode(), errmsg(), ERROR, GetUserId(), has_privs_of_role(), lfirst_oid, DropOwnedStmt::roles, roleSpecsToIds(), and shdepDropOwned().

Referenced by ProcessUtilitySlow().

1314 {
1315  List *role_ids = roleSpecsToIds(stmt->roles);
1316  ListCell *cell;
1317 
1318  /* Check privileges */
1319  foreach(cell, role_ids)
1320  {
1321  Oid roleid = lfirst_oid(cell);
1322 
1323  if (!has_privs_of_role(GetUserId(), roleid))
1324  ereport(ERROR,
1325  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1326  errmsg("permission denied to drop objects")));
1327  }
1328 
1329  /* Ok, do it */
1330  shdepDropOwned(role_ids, stmt->behavior);
1331 }
void shdepDropOwned(List *roleids, DropBehavior behavior)
Definition: pg_shdepend.c:1284
Oid GetUserId(void)
Definition: miscinit.c:495
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4843
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:46
DropBehavior behavior
Definition: parsenodes.h:3587
#define ereport(elevel,...)
Definition: elog.h:157
List * roleSpecsToIds(List *memberNames)
Definition: user.c:1376
int errmsg(const char *fmt,...)
Definition: elog.c:909
Definition: pg_list.h:50
#define lfirst_oid(lc)
Definition: pg_list.h:171

◆ DropRole()

void DropRole ( DropRoleStmt stmt)

Definition at line 936 of file user.c.

References AccessExclusiveLock, AUTHNAME, BTEqualStrategyNumber, CatalogTupleDelete(), checkSharedDependencies(), CommandCounterIncrement(), DeleteSharedComments(), DeleteSharedSecurityLabel(), DropSetting(), ereport, errcode(), errdetail_internal(), errdetail_log(), errmsg(), ERROR, GetOuterUserId(), GetSessionUserId(), GETSTRUCT, GetUserId(), have_createrole_privilege(), HeapTupleIsValid, InvalidOid, InvokeObjectDropHook, lfirst, LockSharedObject(), DropRoleStmt::missing_ok, NoLock, NOTICE, ObjectIdGetDatum, PointerGetDatum, ReleaseSysCache(), RoleSpec::rolename, DropRoleStmt::roles, ROLESPEC_CSTRING, RoleSpec::roletype, RowExclusiveLock, ScanKeyInit(), SearchSysCache1(), superuser(), systable_beginscan(), systable_endscan(), systable_getnext(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by standard_ProcessUtility().

937 {
938  Relation pg_authid_rel,
939  pg_auth_members_rel;
940  ListCell *item;
941 
943  ereport(ERROR,
944  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
945  errmsg("permission denied to drop role")));
946 
947  /*
948  * Scan the pg_authid relation to find the Oid of the role(s) to be
949  * deleted.
950  */
951  pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
952  pg_auth_members_rel = table_open(AuthMemRelationId, RowExclusiveLock);
953 
954  foreach(item, stmt->roles)
955  {
956  RoleSpec *rolspec = lfirst(item);
957  char *role;
958  HeapTuple tuple,
959  tmp_tuple;
960  Form_pg_authid roleform;
961  ScanKeyData scankey;
962  char *detail;
963  char *detail_log;
964  SysScanDesc sscan;
965  Oid roleid;
966 
967  if (rolspec->roletype != ROLESPEC_CSTRING)
968  ereport(ERROR,
969  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
970  errmsg("cannot use special role specifier in DROP ROLE")));
971  role = rolspec->rolename;
972 
973  tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
974  if (!HeapTupleIsValid(tuple))
975  {
976  if (!stmt->missing_ok)
977  {
978  ereport(ERROR,
979  (errcode(ERRCODE_UNDEFINED_OBJECT),
980  errmsg("role \"%s\" does not exist", role)));
981  }
982  else
983  {
984  ereport(NOTICE,
985  (errmsg("role \"%s\" does not exist, skipping",
986  role)));
987  }
988 
989  continue;
990  }
991 
992  roleform = (Form_pg_authid) GETSTRUCT(tuple);
993  roleid = roleform->oid;
994 
995  if (roleid == GetUserId())
996  ereport(ERROR,
997  (errcode(ERRCODE_OBJECT_IN_USE),
998  errmsg("current user cannot be dropped")));
999  if (roleid == GetOuterUserId())
1000  ereport(ERROR,
1001  (errcode(ERRCODE_OBJECT_IN_USE),
1002  errmsg("current user cannot be dropped")));
1003  if (roleid == GetSessionUserId())
1004  ereport(ERROR,
1005  (errcode(ERRCODE_OBJECT_IN_USE),
1006  errmsg("session user cannot be dropped")));
1007 
1008  /*
1009  * For safety's sake, we allow createrole holders to drop ordinary
1010  * roles but not superuser roles. This is mainly to avoid the
1011  * scenario where you accidentally drop the last superuser.
1012  */
1013  if (roleform->rolsuper && !superuser())
1014  ereport(ERROR,
1015  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1016  errmsg("must be superuser to drop superusers")));
1017 
1018  /* DROP hook for the role being removed */
1019  InvokeObjectDropHook(AuthIdRelationId, roleid, 0);
1020 
1021  /*
1022  * Lock the role, so nobody can add dependencies to her while we drop
1023  * her. We keep the lock until the end of transaction.
1024  */
1025  LockSharedObject(AuthIdRelationId, roleid, 0, AccessExclusiveLock);
1026 
1027  /* Check for pg_shdepend entries depending on this role */
1028  if (checkSharedDependencies(AuthIdRelationId, roleid,
1029  &detail, &detail_log))
1030  ereport(ERROR,
1031  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1032  errmsg("role \"%s\" cannot be dropped because some objects depend on it",
1033  role),
1034  errdetail_internal("%s", detail),
1035  errdetail_log("%s", detail_log)));
1036 
1037  /*
1038  * Remove the role from the pg_authid table
1039  */
1040  CatalogTupleDelete(pg_authid_rel, &tuple->t_self);
1041 
1042  ReleaseSysCache(tuple);
1043 
1044  /*
1045  * Remove role from the pg_auth_members table. We have to remove all
1046  * tuples that show it as either a role or a member.
1047  *
1048  * XXX what about grantor entries? Maybe we should do one heap scan.
1049  */
1050  ScanKeyInit(&scankey,
1051  Anum_pg_auth_members_roleid,
1052  BTEqualStrategyNumber, F_OIDEQ,
1053  ObjectIdGetDatum(roleid));
1054 
1055  sscan = systable_beginscan(pg_auth_members_rel, AuthMemRoleMemIndexId,
1056  true, NULL, 1, &scankey);
1057 
1058  while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
1059  {
1060  CatalogTupleDelete(pg_auth_members_rel, &tmp_tuple->t_self);
1061  }
1062 
1063  systable_endscan(sscan);
1064 
1065  ScanKeyInit(&scankey,
1066  Anum_pg_auth_members_member,
1067  BTEqualStrategyNumber, F_OIDEQ,
1068  ObjectIdGetDatum(roleid));
1069 
1070  sscan = systable_beginscan(pg_auth_members_rel, AuthMemMemRoleIndexId,
1071  true, NULL, 1, &scankey);
1072 
1073  while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
1074  {
1075  CatalogTupleDelete(pg_auth_members_rel, &tmp_tuple->t_self);
1076  }
1077 
1078  systable_endscan(sscan);
1079 
1080  /*
1081  * Remove any comments or security labels on this role.
1082  */
1083  DeleteSharedComments(roleid, AuthIdRelationId);
1084  DeleteSharedSecurityLabel(roleid, AuthIdRelationId);
1085 
1086  /*
1087  * Remove settings for this role.
1088  */
1089  DropSetting(InvalidOid, roleid);
1090 
1091  /*
1092  * Advance command counter so that later iterations of this loop will
1093  * see the changes already made. This is essential if, for example,
1094  * we are trying to drop both a role and one of its direct members ---
1095  * we'll get an error if we try to delete the linking pg_auth_members
1096  * tuple twice. (We do not need a CCI between the two delete loops
1097  * above, because it's not allowed for a role to directly contain
1098  * itself.)
1099  */
1101  }
1102 
1103  /*
1104  * Now we can clean up; but keep locks until commit.
1105  */
1106  table_close(pg_auth_members_rel, NoLock);
1107  table_close(pg_authid_rel, NoLock);
1108 }
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:595
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
Oid GetUserId(void)
Definition: miscinit.c:495
#define PointerGetDatum(X)
Definition: postgres.h:600
#define InvokeObjectDropHook(classId, objectId, subId)
Definition: objectaccess.h:160
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
List * roles
Definition: parsenodes.h:2645
unsigned int Oid
Definition: postgres_ext.h:31
Oid GetSessionUserId(void)
Definition: miscinit.c:529
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:383
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1069
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:502
Oid GetOuterUserId(void)
Definition: miscinit.c:506
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail_log(const char *fmt,...)
Definition: elog.c:1090
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void CommandCounterIncrement(void)
Definition: xact.c:1022
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
RoleSpecType roletype
Definition: parsenodes.h:351
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1018
#define InvalidOid
Definition: postgres_ext.h:36
#define ereport(elevel,...)
Definition: elog.h:157
#define NOTICE
Definition: elog.h:37
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define lfirst(lc)
Definition: pg_list.h:169
void DeleteSharedComments(Oid oid, Oid classoid)
Definition: comment.c:374
char * rolename
Definition: parsenodes.h:352
void DeleteSharedSecurityLabel(Oid objectId, Oid classId)
Definition: seclabel.c:489
#define AccessExclusiveLock
Definition: lockdefs.h:45
int errmsg(const char *fmt,...)
Definition: elog.c:909
static bool have_createrole_privilege(void)
Definition: user.c:62
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
bool checkSharedDependencies(Oid classId, Oid objectId, char **detail_msg, char **detail_log_msg)
Definition: pg_shdepend.c:629
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
void DropSetting(Oid databaseid, Oid roleid)
#define BTEqualStrategyNumber
Definition: stratnum.h:31

◆ GrantRole()

void GrantRole ( GrantRoleStmt stmt)

Definition at line 1254 of file user.c.

References AccessShareLock, AddRoleMems(), GrantRoleStmt::admin_opt, AccessPriv::cols, DelRoleMems(), ereport, errcode(), errmsg(), ERROR, get_role_oid(), get_rolespec_oid(), GetUserId(), GrantRoleStmt::granted_roles, GrantRoleStmt::grantee_roles, GrantRoleStmt::grantor, GrantRoleStmt::is_grant, lfirst, NIL, NoLock, AccessPriv::priv_name, roleSpecsToIds(), table_close(), and table_open().

Referenced by standard_ProcessUtility().

1255 {
1256  Relation pg_authid_rel;
1257  Oid grantor;
1258  List *grantee_ids;
1259  ListCell *item;
1260 
1261  if (stmt->grantor)
1262  grantor = get_rolespec_oid(stmt->grantor, false);
1263  else
1264  grantor = GetUserId();
1265 
1266  grantee_ids = roleSpecsToIds(stmt->grantee_roles);
1267 
1268  /* AccessShareLock is enough since we aren't modifying pg_authid */
1269  pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
1270 
1271  /*
1272  * Step through all of the granted roles and add/remove entries for the
1273  * grantees, or, if admin_opt is set, then just add/remove the admin
1274  * option.
1275  *
1276  * Note: Permissions checking is done by AddRoleMems/DelRoleMems
1277  */
1278  foreach(item, stmt->granted_roles)
1279  {
1280  AccessPriv *priv = (AccessPriv *) lfirst(item);
1281  char *rolename = priv->priv_name;
1282  Oid roleid;
1283 
1284  /* Must reject priv(columns) and ALL PRIVILEGES(columns) */
1285  if (rolename == NULL || priv->cols != NIL)
1286  ereport(ERROR,
1287  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1288  errmsg("column names cannot be included in GRANT/REVOKE ROLE")));
1289 
1290  roleid = get_role_oid(rolename, false);
1291  if (stmt->is_grant)
1292  AddRoleMems(rolename, roleid,
1293  stmt->grantee_roles, grantee_ids,
1294  grantor, stmt->admin_opt);
1295  else
1296  DelRoleMems(rolename, roleid,
1297  stmt->grantee_roles, grantee_ids,
1298  stmt->admin_opt);
1299  }
1300 
1301  /*
1302  * Close pg_authid, but keep lock till commit.
1303  */
1304  table_close(pg_authid_rel, NoLock);
1305 }
#define NIL
Definition: pg_list.h:65
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Oid GetUserId(void)
Definition: miscinit.c:495
#define AccessShareLock
Definition: lockdefs.h:36
int errcode(int sqlerrcode)
Definition: elog.c:698
List * granted_roles
Definition: parsenodes.h:2091
List * cols
Definition: parsenodes.h:2076
unsigned int Oid
Definition: postgres_ext.h:31
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5094
#define ERROR
Definition: elog.h:46
static void AddRoleMems(const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, Oid grantorId, bool admin_opt)
Definition: user.c:1403
#define NoLock
Definition: lockdefs.h:34
RoleSpec * grantor
Definition: parsenodes.h:2095
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5128
#define ereport(elevel,...)
Definition: elog.h:157
List * roleSpecsToIds(List *memberNames)
Definition: user.c:1376
#define lfirst(lc)
Definition: pg_list.h:169
int errmsg(const char *fmt,...)
Definition: elog.c:909
List * grantee_roles
Definition: parsenodes.h:2092
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: pg_list.h:50
char * priv_name
Definition: parsenodes.h:2075
static void DelRoleMems(const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, bool admin_opt)
Definition: user.c:1581

◆ have_createrole_privilege()

static bool have_createrole_privilege ( void  )
static

Definition at line 62 of file user.c.

References GetUserId(), and has_createrole_privilege().

Referenced by AddRoleMems(), AlterRole(), AlterRoleSet(), CreateRole(), DelRoleMems(), DropRole(), and RenameRole().

63 {
65 }
bool has_createrole_privilege(Oid roleid)
Definition: aclchk.c:5443
Oid GetUserId(void)
Definition: miscinit.c:495

◆ ReassignOwnedObjects()

void ReassignOwnedObjects ( ReassignOwnedStmt stmt)

Definition at line 1339 of file user.c.

References ereport, errcode(), errmsg(), ERROR, get_rolespec_oid(), GetUserId(), has_privs_of_role(), lfirst_oid, ReassignOwnedStmt::newrole, ReassignOwnedStmt::roles, roleSpecsToIds(), and shdepReassignOwned().

Referenced by standard_ProcessUtility().

1340 {
1341  List *role_ids = roleSpecsToIds(stmt->roles);
1342  ListCell *cell;
1343  Oid newrole;
1344 
1345  /* Check privileges */
1346  foreach(cell, role_ids)
1347  {
1348  Oid roleid = lfirst_oid(cell);
1349 
1350  if (!has_privs_of_role(GetUserId(), roleid))
1351  ereport(ERROR,
1352  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1353  errmsg("permission denied to reassign objects")));
1354  }
1355 
1356  /* Must have privileges on the receiving side too */
1357  newrole = get_rolespec_oid(stmt->newrole, false);
1358 
1359  if (!has_privs_of_role(GetUserId(), newrole))
1360  ereport(ERROR,
1361  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1362  errmsg("permission denied to reassign objects")));
1363 
1364  /* Ok, do it */
1365  shdepReassignOwned(role_ids, newrole);
1366 }
Oid GetUserId(void)
Definition: miscinit.c:495
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4843
int errcode(int sqlerrcode)
Definition: elog.c:698
unsigned int Oid
Definition: postgres_ext.h:31
#define ERROR
Definition: elog.h:46
void shdepReassignOwned(List *roleids, Oid newrole)
Definition: pg_shdepend.c:1437
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5128
#define ereport(elevel,...)
Definition: elog.h:157
List * roleSpecsToIds(List *memberNames)
Definition: user.c:1376
RoleSpec * newrole
Definition: parsenodes.h:3597
int errmsg(const char *fmt,...)
Definition: elog.c:909
Definition: pg_list.h:50
#define lfirst_oid(lc)
Definition: pg_list.h:171

◆ RenameRole()

ObjectAddress RenameRole ( const char *  oldname,
const char *  newname 
)

Definition at line 1114 of file user.c.

References AUTHNAME, CatalogTupleUpdate(), CStringGetDatum, DirectFunctionCall1, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errdetail(), errmsg(), ERROR, get_password_type(), GetOuterUserId(), GetSessionUserId(), GETSTRUCT, have_createrole_privilege(), heap_getattr, heap_modify_tuple(), HeapTupleIsValid, i, InvokeObjectPostAlterHook, IsReservedName(), namein(), NameStr, NoLock, NOTICE, ObjectAddressSet, PASSWORD_TYPE_MD5, RelationGetDescr, ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), SearchSysCacheExists1, superuser(), HeapTupleData::t_self, table_close(), table_open(), TextDatumGetCString, and WARNING.

Referenced by ExecRenameStmt().

1115 {
1116  HeapTuple oldtuple,
1117  newtuple;
1118  TupleDesc dsc;
1119  Relation rel;
1120  Datum datum;
1121  bool isnull;
1122  Datum repl_val[Natts_pg_authid];
1123  bool repl_null[Natts_pg_authid];
1124  bool repl_repl[Natts_pg_authid];
1125  int i;
1126  Oid roleid;
1127  ObjectAddress address;
1128  Form_pg_authid authform;
1129 
1130  rel = table_open(AuthIdRelationId, RowExclusiveLock);
1131  dsc = RelationGetDescr(rel);
1132 
1133  oldtuple = SearchSysCache1(AUTHNAME, CStringGetDatum(oldname));
1134  if (!HeapTupleIsValid(oldtuple))
1135  ereport(ERROR,
1136  (errcode(ERRCODE_UNDEFINED_OBJECT),
1137  errmsg("role \"%s\" does not exist", oldname)));
1138 
1139  /*
1140  * XXX Client applications probably store the session user somewhere, so
1141  * renaming it could cause confusion. On the other hand, there may not be
1142  * an actual problem besides a little confusion, so think about this and
1143  * decide. Same for SET ROLE ... we don't restrict renaming the current
1144  * effective userid, though.
1145  */
1146 
1147  authform = (Form_pg_authid) GETSTRUCT(oldtuple);
1148  roleid = authform->oid;
1149 
1150  if (roleid == GetSessionUserId())
1151  ereport(ERROR,
1152  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1153  errmsg("session user cannot be renamed")));
1154  if (roleid == GetOuterUserId())
1155  ereport(ERROR,
1156  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1157  errmsg("current user cannot be renamed")));
1158 
1159  /*
1160  * Check that the user is not trying to rename a system role and not
1161  * trying to rename a role into the reserved "pg_" namespace.
1162  */
1163  if (IsReservedName(NameStr(authform->rolname)))
1164  ereport(ERROR,
1165  (errcode(ERRCODE_RESERVED_NAME),
1166  errmsg("role name \"%s\" is reserved",
1167  NameStr(authform->rolname)),
1168  errdetail("Role names starting with \"pg_\" are reserved.")));
1169 
1170  if (IsReservedName(newname))
1171  ereport(ERROR,
1172  (errcode(ERRCODE_RESERVED_NAME),
1173  errmsg("role name \"%s\" is reserved",
1174  newname),
1175  errdetail("Role names starting with \"pg_\" are reserved.")));
1176 
1177  /*
1178  * If built with appropriate switch, whine when regression-testing
1179  * conventions for role names are violated.
1180  */
1181 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
1182  if (strncmp(newname, "regress_", 8) != 0)
1183  elog(WARNING, "roles created by regression test cases should have names starting with \"regress_\"");
1184 #endif
1185 
1186  /* make sure the new name doesn't exist */
1188  ereport(ERROR,
1190  errmsg("role \"%s\" already exists", newname)));
1191 
1192  /*
1193  * createrole is enough privilege unless you want to mess with a superuser
1194  */
1195  if (((Form_pg_authid) GETSTRUCT(oldtuple))->rolsuper)
1196  {
1197  if (!superuser())
1198  ereport(ERROR,
1199  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1200  errmsg("must be superuser to rename superusers")));
1201  }
1202  else
1203  {
1205  ereport(ERROR,
1206  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1207  errmsg("permission denied to rename role")));
1208  }
1209 
1210  /* OK, construct the modified tuple */
1211  for (i = 0; i < Natts_pg_authid; i++)
1212  repl_repl[i] = false;
1213 
1214  repl_repl[Anum_pg_authid_rolname - 1] = true;
1215  repl_val[Anum_pg_authid_rolname - 1] = DirectFunctionCall1(namein,
1216  CStringGetDatum(newname));
1217  repl_null[Anum_pg_authid_rolname - 1] = false;
1218 
1219  datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull);
1220 
1221  if (!isnull && get_password_type(TextDatumGetCString(datum)) == PASSWORD_TYPE_MD5)
1222  {
1223  /* MD5 uses the username as salt, so just clear it on a rename */
1224  repl_repl[Anum_pg_authid_rolpassword - 1] = true;
1225  repl_null[Anum_pg_authid_rolpassword - 1] = true;
1226 
1227  ereport(NOTICE,
1228  (errmsg("MD5 password cleared because of role rename")));
1229  }
1230 
1231  newtuple = heap_modify_tuple(oldtuple, dsc, repl_val, repl_null, repl_repl);
1232  CatalogTupleUpdate(rel, &oldtuple->t_self, newtuple);
1233 
1234  InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
1235 
1236  ObjectAddressSet(address, AuthIdRelationId, roleid);
1237 
1238  ReleaseSysCache(oldtuple);
1239 
1240  /*
1241  * Close pg_authid, but keep lock till commit.
1242  */
1243  table_close(rel, NoLock);
1244 
1245  return address;
1246 }
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define RelationGetDescr(relation)
Definition: rel.h:503
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:626
unsigned int Oid
Definition: postgres_ext.h:31
bool IsReservedName(const char *name)
Definition: catalog.c:218
Oid GetSessionUserId(void)
Definition: miscinit.c:529
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:184
Oid GetOuterUserId(void)
Definition: miscinit.c:506
#define ERROR
Definition: elog.h:46
ItemPointerData t_self
Definition: htup.h:65
#define NoLock
Definition: lockdefs.h:34
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:1042
#define CStringGetDatum(X)
Definition: postgres.h:622
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:175
#define WARNING
Definition: elog.h:40
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
#define TextDatumGetCString(d)
Definition: builtins.h:87
uintptr_t Datum
Definition: postgres.h:411
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define ereport(elevel,...)
Definition: elog.h:157
#define NOTICE
Definition: elog.h:37
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
int errmsg(const char *fmt,...)
Definition: elog.c:909
PasswordType get_password_type(const char *shadow_pass)
Definition: crypt.c:89
#define elog(elevel,...)
Definition: elog.h:232
static bool have_createrole_privilege(void)
Definition: user.c:62
int i
#define NameStr(name)
Definition: c.h:681
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:1113
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32

◆ roleSpecsToIds()

List* roleSpecsToIds ( List memberNames)

Definition at line 1376 of file user.c.

References get_rolespec_oid(), lappend_oid(), lfirst_node, and NIL.

Referenced by AlterRole(), AlterTableMoveAll(), CreateRole(), DropOwnedObjects(), GrantRole(), and ReassignOwnedObjects().

1377 {
1378  List *result = NIL;
1379  ListCell *l;
1380 
1381  foreach(l, memberNames)
1382  {
1383  RoleSpec *rolespec = lfirst_node(RoleSpec, l);
1384  Oid roleid;
1385 
1386  roleid = get_rolespec_oid(rolespec, false);
1387  result = lappend_oid(result, roleid);
1388  }
1389  return result;
1390 }
#define NIL
Definition: pg_list.h:65
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
#define lfirst_node(type, lc)
Definition: pg_list.h:172
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5128
Definition: pg_list.h:50

Variable Documentation

◆ binary_upgrade_next_pg_authid_oid

Oid binary_upgrade_next_pg_authid_oid = InvalidOid

Definition at line 43 of file user.c.

Referenced by binary_upgrade_set_next_pg_authid_oid(), and CreateRole().

◆ check_password_hook

check_password_hook_type check_password_hook = NULL

Definition at line 50 of file user.c.

Referenced by _PG_fini(), _PG_init(), AlterRole(), and CreateRole().

◆ Password_encryption

int Password_encryption = PASSWORD_TYPE_SCRAM_SHA_256

Definition at line 47 of file user.c.

Referenced by AlterRole(), CheckPWChallengeAuth(), and CreateRole().