PostgreSQL Source Code  git master
user.h File Reference
Include dependency graph for user.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef void(* check_password_hook_type) (const char *username, const char *shadow_pass, PasswordType password_type, Datum validuntil_time, bool validuntil_null)
 

Functions

Oid CreateRole (ParseState *pstate, CreateRoleStmt *stmt)
 
Oid AlterRole (ParseState *pstate, AlterRoleStmt *stmt)
 
Oid AlterRoleSet (AlterRoleSetStmt *stmt)
 
void DropRole (DropRoleStmt *stmt)
 
void GrantRole (GrantRoleStmt *stmt)
 
ObjectAddress RenameRole (const char *oldname, const char *newname)
 
void DropOwnedObjects (DropOwnedStmt *stmt)
 
void ReassignOwnedObjects (ReassignOwnedStmt *stmt)
 
ListroleSpecsToIds (List *memberNames)
 

Variables

int Password_encryption
 
PGDLLIMPORT check_password_hook_type check_password_hook
 

Typedef Documentation

◆ check_password_hook_type

typedef void(* check_password_hook_type) (const char *username, const char *shadow_pass, PasswordType password_type, Datum validuntil_time, bool validuntil_null)

Definition at line 23 of file user.h.

Function Documentation

◆ AlterRole()

Oid AlterRole ( ParseState pstate,
AlterRoleStmt stmt 
)

Definition at line 493 of file user.c.

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

References AlterRoleStmt::action, AddRoleMems(), DefElem::arg, AUTHNAME, BoolGetDatum, boolVal, CatalogTupleUpdate(), check_password_hook, check_rolespec_name(), CommandCounterIncrement(), 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, 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().

◆ AlterRoleSet()

Oid AlterRoleSet ( AlterRoleSetStmt stmt)

Definition at line 828 of file user.c.

829 {
830  HeapTuple roletuple;
831  Form_pg_authid roleform;
832  Oid databaseid = InvalidOid;
833  Oid roleid = InvalidOid;
834 
835  if (stmt->role)
836  {
838  "Cannot alter reserved roles.");
839 
840  roletuple = get_rolespec_tuple(stmt->role);
841  roleform = (Form_pg_authid) GETSTRUCT(roletuple);
842  roleid = roleform->oid;
843 
844  /*
845  * Obtain a lock on the role and make sure it didn't go away in the
846  * meantime.
847  */
848  shdepLockAndCheckObject(AuthIdRelationId, roleid);
849 
850  /*
851  * To mess with a superuser you gotta be superuser; else you need
852  * createrole, or just want to change your own settings
853  */
854  if (roleform->rolsuper)
855  {
856  if (!superuser())
857  ereport(ERROR,
858  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
859  errmsg("must be superuser to alter superusers")));
860  }
861  else
862  {
863  if (!have_createrole_privilege() && roleid != GetUserId())
864  ereport(ERROR,
865  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
866  errmsg("permission denied")));
867  }
868 
869  ReleaseSysCache(roletuple);
870  }
871 
872  /* look up and lock the database, if specified */
873  if (stmt->database != NULL)
874  {
875  databaseid = get_database_oid(stmt->database, false);
876  shdepLockAndCheckObject(DatabaseRelationId, databaseid);
877 
878  if (!stmt->role)
879  {
880  /*
881  * If no role is specified, then this is effectively the same as
882  * ALTER DATABASE ... SET, so use the same permission check.
883  */
884  if (!pg_database_ownercheck(databaseid, GetUserId()))
886  stmt->database);
887  }
888  }
889 
890  if (!stmt->role && !stmt->database)
891  {
892  /* Must be superuser to alter settings globally. */
893  if (!superuser())
894  ereport(ERROR,
895  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
896  errmsg("must be superuser to alter settings globally")));
897  }
898 
899  AlterSetting(databaseid, roleid, stmt->setstmt);
900 
901  return roleid;
902 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:181
bool pg_database_ownercheck(Oid db_oid, Oid roleid)
Definition: aclchk.c:5238
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:3308
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:2059
@ OBJECT_DATABASE
Definition: parsenodes.h:1798
void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
void shdepLockAndCheckObject(Oid classId, Oid objectId)
Definition: pg_shdepend.c:1165
RoleSpec * role
Definition: parsenodes.h:2639
VariableSetStmt * setstmt
Definition: parsenodes.h:2641

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().

◆ CreateRole()

Oid CreateRole ( ParseState pstate,
CreateRoleStmt stmt 
)

Definition at line 72 of file user.c.

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 = boolVal(dissuper->arg);
221  if (dinherit)
222  inherit = boolVal(dinherit->arg);
223  if (dcreaterole)
224  createrole = boolVal(dcreaterole->arg);
225  if (dcreatedb)
226  createdb = boolVal(dcreatedb->arg);
227  if (dcanlogin)
228  canlogin = boolVal(dcanlogin->arg);
229  if (disreplication)
230  isreplication = boolVal(disreplication->arg);
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 = boolVal(dbypassRLS->arg);
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  */
332  (*check_password_hook) (stmt->role,
333  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  const char *logdetail = NULL;
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 }
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5094
#define OidIsValid(objectId)
Definition: c.h:710
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:381
bool IsReservedName(const char *name)
Definition: catalog.c:218
Oid createdb(ParseState *pstate, const CreatedbStmt *stmt)
Definition: dbcommands.c:99
int errdetail(const char *fmt,...)
Definition: elog.c:1037
#define WARNING
Definition: elog.h:30
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:631
bool IsBinaryUpgrade
Definition: globals.c:113
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
#define makeNode(_type_)
Definition: nodes.h:587
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:151
@ ROLESPEC_CSTRING
Definition: parsenodes.h:341
@ ROLESTMT_ROLE
Definition: parsenodes.h:2615
@ ROLESTMT_USER
Definition: parsenodes.h:2616
@ ROLESTMT_GROUP
Definition: parsenodes.h:2617
#define NIL
Definition: pg_list.h:65
#define list_make1_oid(x1)
Definition: pg_list.h:236
#define list_make1(x1)
Definition: pg_list.h:206
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
RoleStmtType stmt_type
Definition: parsenodes.h:2623
RoleSpecType roletype
Definition: parsenodes.h:351
int location
Definition: parsenodes.h:353
char * rolename
Definition: parsenodes.h:352
Oid binary_upgrade_next_pg_authid_oid
Definition: user.c:43

References AddRoleMems(), DefElem::arg, binary_upgrade_next_pg_authid_oid, BoolGetDatum, boolVal, 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(), if(), 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().

◆ DropOwnedObjects()

void DropOwnedObjects ( DropOwnedStmt stmt)

Definition at line 1286 of file user.c.

1287 {
1288  List *role_ids = roleSpecsToIds(stmt->roles);
1289  ListCell *cell;
1290 
1291  /* Check privileges */
1292  foreach(cell, role_ids)
1293  {
1294  Oid roleid = lfirst_oid(cell);
1295 
1296  if (!has_privs_of_role(GetUserId(), roleid))
1297  ereport(ERROR,
1298  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1299  errmsg("permission denied to drop objects")));
1300  }
1301 
1302  /* Ok, do it */
1303  shdepDropOwned(role_ids, stmt->behavior);
1304 }
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4843
#define lfirst_oid(lc)
Definition: pg_list.h:171
void shdepDropOwned(List *roleids, DropBehavior behavior)
Definition: pg_shdepend.c:1294
DropBehavior behavior
Definition: parsenodes.h:3589

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

Referenced by ProcessUtilitySlow().

◆ DropRole()

void DropRole ( DropRoleStmt stmt)

Definition at line 909 of file user.c.

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

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().

◆ GrantRole()

void GrantRole ( GrantRoleStmt stmt)

Definition at line 1227 of file user.c.

1228 {
1229  Relation pg_authid_rel;
1230  Oid grantor;
1231  List *grantee_ids;
1232  ListCell *item;
1233 
1234  if (stmt->grantor)
1235  grantor = get_rolespec_oid(stmt->grantor, false);
1236  else
1237  grantor = GetUserId();
1238 
1239  grantee_ids = roleSpecsToIds(stmt->grantee_roles);
1240 
1241  /* AccessShareLock is enough since we aren't modifying pg_authid */
1242  pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
1243 
1244  /*
1245  * Step through all of the granted roles and add/remove entries for the
1246  * grantees, or, if admin_opt is set, then just add/remove the admin
1247  * option.
1248  *
1249  * Note: Permissions checking is done by AddRoleMems/DelRoleMems
1250  */
1251  foreach(item, stmt->granted_roles)
1252  {
1253  AccessPriv *priv = (AccessPriv *) lfirst(item);
1254  char *rolename = priv->priv_name;
1255  Oid roleid;
1256 
1257  /* Must reject priv(columns) and ALL PRIVILEGES(columns) */
1258  if (rolename == NULL || priv->cols != NIL)
1259  ereport(ERROR,
1260  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1261  errmsg("column names cannot be included in GRANT/REVOKE ROLE")));
1262 
1263  roleid = get_role_oid(rolename, false);
1264  if (stmt->is_grant)
1265  AddRoleMems(rolename, roleid,
1266  stmt->grantee_roles, grantee_ids,
1267  grantor, stmt->admin_opt);
1268  else
1269  DelRoleMems(rolename, roleid,
1270  stmt->grantee_roles, grantee_ids,
1271  stmt->admin_opt);
1272  }
1273 
1274  /*
1275  * Close pg_authid, but keep lock till commit.
1276  */
1277  table_close(pg_authid_rel, NoLock);
1278 }
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5128
#define AccessShareLock
Definition: lockdefs.h:36
char * priv_name
Definition: parsenodes.h:2076
List * cols
Definition: parsenodes.h:2077
RoleSpec * grantor
Definition: parsenodes.h:2096
List * grantee_roles
Definition: parsenodes.h:2093
List * granted_roles
Definition: parsenodes.h:2092

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().

◆ ReassignOwnedObjects()

void ReassignOwnedObjects ( ReassignOwnedStmt stmt)

Definition at line 1312 of file user.c.

1313 {
1314  List *role_ids = roleSpecsToIds(stmt->roles);
1315  ListCell *cell;
1316  Oid newrole;
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 reassign objects")));
1327  }
1328 
1329  /* Must have privileges on the receiving side too */
1330  newrole = get_rolespec_oid(stmt->newrole, false);
1331 
1332  if (!has_privs_of_role(GetUserId(), newrole))
1333  ereport(ERROR,
1334  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1335  errmsg("permission denied to reassign objects")));
1336 
1337  /* Ok, do it */
1338  shdepReassignOwned(role_ids, newrole);
1339 }
void shdepReassignOwned(List *roleids, Oid newrole)
Definition: pg_shdepend.c:1447
RoleSpec * newrole
Definition: parsenodes.h:3599

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().

◆ RenameRole()

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

Definition at line 1087 of file user.c.

1088 {
1089  HeapTuple oldtuple,
1090  newtuple;
1091  TupleDesc dsc;
1092  Relation rel;
1093  Datum datum;
1094  bool isnull;
1095  Datum repl_val[Natts_pg_authid];
1096  bool repl_null[Natts_pg_authid];
1097  bool repl_repl[Natts_pg_authid];
1098  int i;
1099  Oid roleid;
1100  ObjectAddress address;
1101  Form_pg_authid authform;
1102 
1103  rel = table_open(AuthIdRelationId, RowExclusiveLock);
1104  dsc = RelationGetDescr(rel);
1105 
1106  oldtuple = SearchSysCache1(AUTHNAME, CStringGetDatum(oldname));
1107  if (!HeapTupleIsValid(oldtuple))
1108  ereport(ERROR,
1109  (errcode(ERRCODE_UNDEFINED_OBJECT),
1110  errmsg("role \"%s\" does not exist", oldname)));
1111 
1112  /*
1113  * XXX Client applications probably store the session user somewhere, so
1114  * renaming it could cause confusion. On the other hand, there may not be
1115  * an actual problem besides a little confusion, so think about this and
1116  * decide. Same for SET ROLE ... we don't restrict renaming the current
1117  * effective userid, though.
1118  */
1119 
1120  authform = (Form_pg_authid) GETSTRUCT(oldtuple);
1121  roleid = authform->oid;
1122 
1123  if (roleid == GetSessionUserId())
1124  ereport(ERROR,
1125  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1126  errmsg("session user cannot be renamed")));
1127  if (roleid == GetOuterUserId())
1128  ereport(ERROR,
1129  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1130  errmsg("current user cannot be renamed")));
1131 
1132  /*
1133  * Check that the user is not trying to rename a system role and not
1134  * trying to rename a role into the reserved "pg_" namespace.
1135  */
1136  if (IsReservedName(NameStr(authform->rolname)))
1137  ereport(ERROR,
1138  (errcode(ERRCODE_RESERVED_NAME),
1139  errmsg("role name \"%s\" is reserved",
1140  NameStr(authform->rolname)),
1141  errdetail("Role names starting with \"pg_\" are reserved.")));
1142 
1143  if (IsReservedName(newname))
1144  ereport(ERROR,
1145  (errcode(ERRCODE_RESERVED_NAME),
1146  errmsg("role name \"%s\" is reserved",
1147  newname),
1148  errdetail("Role names starting with \"pg_\" are reserved.")));
1149 
1150  /*
1151  * If built with appropriate switch, whine when regression-testing
1152  * conventions for role names are violated.
1153  */
1154 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
1155  if (strncmp(newname, "regress_", 8) != 0)
1156  elog(WARNING, "roles created by regression test cases should have names starting with \"regress_\"");
1157 #endif
1158 
1159  /* make sure the new name doesn't exist */
1161  ereport(ERROR,
1163  errmsg("role \"%s\" already exists", newname)));
1164 
1165  /*
1166  * createrole is enough privilege unless you want to mess with a superuser
1167  */
1168  if (((Form_pg_authid) GETSTRUCT(oldtuple))->rolsuper)
1169  {
1170  if (!superuser())
1171  ereport(ERROR,
1172  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1173  errmsg("must be superuser to rename superusers")));
1174  }
1175  else
1176  {
1178  ereport(ERROR,
1179  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1180  errmsg("permission denied to rename role")));
1181  }
1182 
1183  /* OK, construct the modified tuple */
1184  for (i = 0; i < Natts_pg_authid; i++)
1185  repl_repl[i] = false;
1186 
1187  repl_repl[Anum_pg_authid_rolname - 1] = true;
1188  repl_val[Anum_pg_authid_rolname - 1] = DirectFunctionCall1(namein,
1189  CStringGetDatum(newname));
1190  repl_null[Anum_pg_authid_rolname - 1] = false;
1191 
1192  datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull);
1193 
1194  if (!isnull && get_password_type(TextDatumGetCString(datum)) == PASSWORD_TYPE_MD5)
1195  {
1196  /* MD5 uses the username as salt, so just clear it on a rename */
1197  repl_repl[Anum_pg_authid_rolpassword - 1] = true;
1198  repl_null[Anum_pg_authid_rolpassword - 1] = true;
1199 
1200  ereport(NOTICE,
1201  (errmsg("MD5 password cleared because of role rename")));
1202  }
1203 
1204  newtuple = heap_modify_tuple(oldtuple, dsc, repl_val, repl_null, repl_repl);
1205  CatalogTupleUpdate(rel, &oldtuple->t_self, newtuple);
1206 
1207  InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
1208 
1209  ObjectAddressSet(address, AuthIdRelationId, roleid);
1210 
1211  ReleaseSysCache(oldtuple);
1212 
1213  /*
1214  * Close pg_authid, but keep lock till commit.
1215  */
1216  table_close(rel, NoLock);
1217 
1218  return address;
1219 }
#define TextDatumGetCString(d)
Definition: builtins.h:86
@ PASSWORD_TYPE_MD5
Definition: crypt.h:30
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:756
int i
Definition: isn.c:73
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:186

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().

◆ roleSpecsToIds()

List* roleSpecsToIds ( List memberNames)

Definition at line 1349 of file user.c.

1350 {
1351  List *result = NIL;
1352  ListCell *l;
1353 
1354  foreach(l, memberNames)
1355  {
1356  RoleSpec *rolespec = lfirst_node(RoleSpec, l);
1357  Oid roleid;
1358 
1359  roleid = get_rolespec_oid(rolespec, false);
1360  result = lappend_oid(result, roleid);
1361  }
1362  return result;
1363 }
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
#define lfirst_node(type, lc)
Definition: pg_list.h:172

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

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

Variable Documentation

◆ check_password_hook

PGDLLIMPORT check_password_hook_type check_password_hook
extern

Definition at line 50 of file user.c.

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

◆ Password_encryption

int Password_encryption
extern

Definition at line 47 of file user.c.

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