PostgreSQL Source Code  git master
user.h File Reference
#include "catalog/objectaddress.h"
#include "libpq/crypt.h"
#include "nodes/parsenodes.h"
#include "parser/parse_node.h"
#include "utils/guc.h"
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 (ParseState *pstate, GrantRoleStmt *stmt)
 
ObjectAddress RenameRole (const char *oldname, const char *newname)
 
void DropOwnedObjects (DropOwnedStmt *stmt)
 
void ReassignOwnedObjects (ReassignOwnedStmt *stmt)
 
ListroleSpecsToIds (List *memberNames)
 
bool check_createrole_self_grant (char **newval, void **extra, GucSource source)
 
void assign_createrole_self_grant (const char *newval, void *extra)
 

Variables

PGDLLIMPORT int Password_encryption
 
PGDLLIMPORT char * createrole_self_grant
 
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 25 of file user.h.

Function Documentation

◆ AlterRole()

Oid AlterRole ( ParseState pstate,
AlterRoleStmt stmt 
)

Definition at line 610 of file user.c.

611 {
612  Datum new_record[Natts_pg_authid] = {0};
613  bool new_record_nulls[Natts_pg_authid] = {0};
614  bool new_record_repl[Natts_pg_authid] = {0};
615  Relation pg_authid_rel;
616  TupleDesc pg_authid_dsc;
617  HeapTuple tuple,
618  new_tuple;
619  Form_pg_authid authform;
620  ListCell *option;
621  char *rolename;
622  char *password = NULL; /* user password */
623  int connlimit = -1; /* maximum connections allowed */
624  char *validUntil = NULL; /* time the login is valid until */
625  Datum validUntil_datum; /* same, as timestamptz Datum */
626  bool validUntil_null;
627  DefElem *dpassword = NULL;
628  DefElem *dissuper = NULL;
629  DefElem *dinherit = NULL;
630  DefElem *dcreaterole = NULL;
631  DefElem *dcreatedb = NULL;
632  DefElem *dcanlogin = NULL;
633  DefElem *disreplication = NULL;
634  DefElem *dconnlimit = NULL;
635  DefElem *drolemembers = NULL;
636  DefElem *dvalidUntil = NULL;
637  DefElem *dbypassRLS = NULL;
638  Oid roleid;
639  Oid currentUserId = GetUserId();
640  GrantRoleOptions popt;
641 
643  _("Cannot alter reserved roles."));
644 
645  /* Extract options from the statement node tree */
646  foreach(option, stmt->options)
647  {
648  DefElem *defel = (DefElem *) lfirst(option);
649 
650  if (strcmp(defel->defname, "password") == 0)
651  {
652  if (dpassword)
653  errorConflictingDefElem(defel, pstate);
654  dpassword = defel;
655  }
656  else if (strcmp(defel->defname, "superuser") == 0)
657  {
658  if (dissuper)
659  errorConflictingDefElem(defel, pstate);
660  dissuper = defel;
661  }
662  else if (strcmp(defel->defname, "inherit") == 0)
663  {
664  if (dinherit)
665  errorConflictingDefElem(defel, pstate);
666  dinherit = defel;
667  }
668  else if (strcmp(defel->defname, "createrole") == 0)
669  {
670  if (dcreaterole)
671  errorConflictingDefElem(defel, pstate);
672  dcreaterole = defel;
673  }
674  else if (strcmp(defel->defname, "createdb") == 0)
675  {
676  if (dcreatedb)
677  errorConflictingDefElem(defel, pstate);
678  dcreatedb = defel;
679  }
680  else if (strcmp(defel->defname, "canlogin") == 0)
681  {
682  if (dcanlogin)
683  errorConflictingDefElem(defel, pstate);
684  dcanlogin = defel;
685  }
686  else if (strcmp(defel->defname, "isreplication") == 0)
687  {
688  if (disreplication)
689  errorConflictingDefElem(defel, pstate);
690  disreplication = defel;
691  }
692  else if (strcmp(defel->defname, "connectionlimit") == 0)
693  {
694  if (dconnlimit)
695  errorConflictingDefElem(defel, pstate);
696  dconnlimit = defel;
697  }
698  else if (strcmp(defel->defname, "rolemembers") == 0 &&
699  stmt->action != 0)
700  {
701  if (drolemembers)
702  errorConflictingDefElem(defel, pstate);
703  drolemembers = defel;
704  }
705  else if (strcmp(defel->defname, "validUntil") == 0)
706  {
707  if (dvalidUntil)
708  errorConflictingDefElem(defel, pstate);
709  dvalidUntil = defel;
710  }
711  else if (strcmp(defel->defname, "bypassrls") == 0)
712  {
713  if (dbypassRLS)
714  errorConflictingDefElem(defel, pstate);
715  dbypassRLS = defel;
716  }
717  else
718  elog(ERROR, "option \"%s\" not recognized",
719  defel->defname);
720  }
721 
722  if (dpassword && dpassword->arg)
723  password = strVal(dpassword->arg);
724  if (dconnlimit)
725  {
726  connlimit = intVal(dconnlimit->arg);
727  if (connlimit < -1)
728  ereport(ERROR,
729  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
730  errmsg("invalid connection limit: %d", connlimit)));
731  }
732  if (dvalidUntil)
733  validUntil = strVal(dvalidUntil->arg);
734 
735  /*
736  * Scan the pg_authid relation to be certain the user exists.
737  */
738  pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
739  pg_authid_dsc = RelationGetDescr(pg_authid_rel);
740 
741  tuple = get_rolespec_tuple(stmt->role);
742  authform = (Form_pg_authid) GETSTRUCT(tuple);
743  rolename = pstrdup(NameStr(authform->rolname));
744  roleid = authform->oid;
745 
746  /* To mess with a superuser in any way you gotta be superuser. */
747  if (!superuser() && (authform->rolsuper || dissuper))
748  ereport(ERROR,
749  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
750  errmsg("must be superuser to alter superuser roles or change superuser attribute")));
751 
752  /*
753  * Most changes to a role require that you both have CREATEROLE privileges
754  * and also ADMIN OPTION on the role.
755  */
756  if (!have_createrole_privilege() ||
757  !is_admin_of_role(GetUserId(), roleid))
758  {
759  /* things an unprivileged user certainly can't do */
760  if (dinherit || dcreaterole || dcreatedb || dcanlogin || dconnlimit ||
761  dvalidUntil || disreplication || dbypassRLS)
762  ereport(ERROR,
763  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
764  errmsg("permission denied")));
765 
766  /* an unprivileged user can change their own password */
767  if (dpassword && roleid != currentUserId)
768  ereport(ERROR,
769  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
770  errmsg("must have CREATEROLE privilege to change another user's password")));
771  }
772  else if (!superuser())
773  {
774  /*
775  * Even if you have both CREATEROLE and ADMIN OPTION on a role, you
776  * can only change the CREATEDB, REPLICATION, or BYPASSRLS attributes
777  * if they are set for your own role (or you are the superuser).
778  */
779  if (dcreatedb && !have_createdb_privilege())
780  ereport(ERROR,
781  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
782  errmsg("must have createdb privilege to change createdb attribute")));
783  if (disreplication && !has_rolreplication(currentUserId))
784  ereport(ERROR,
785  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
786  errmsg("must have replication privilege to change replication attribute")));
787  if (dbypassRLS && !has_bypassrls_privilege(currentUserId))
788  ereport(ERROR,
789  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
790  errmsg("must have bypassrls privilege to change bypassrls attribute")));
791  }
792 
793  /* To add members to a role, you need ADMIN OPTION. */
794  if (drolemembers && !is_admin_of_role(currentUserId, roleid))
795  ereport(ERROR,
796  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
797  errmsg("must have admin option on role \"%s\" to add members",
798  rolename)));
799 
800  /* Convert validuntil to internal form */
801  if (dvalidUntil)
802  {
803  validUntil_datum = DirectFunctionCall3(timestamptz_in,
804  CStringGetDatum(validUntil),
806  Int32GetDatum(-1));
807  validUntil_null = false;
808  }
809  else
810  {
811  /* fetch existing setting in case hook needs it */
812  validUntil_datum = SysCacheGetAttr(AUTHNAME, tuple,
813  Anum_pg_authid_rolvaliduntil,
814  &validUntil_null);
815  }
816 
817  /*
818  * Call the password checking hook if there is one defined
819  */
821  (*check_password_hook) (rolename,
822  password,
824  validUntil_datum,
825  validUntil_null);
826 
827  /*
828  * Build an updated tuple, perusing the information just obtained
829  */
830 
831  /*
832  * issuper/createrole/etc
833  */
834  if (dissuper)
835  {
836  bool should_be_super = boolVal(dissuper->arg);
837 
838  if (!should_be_super && roleid == BOOTSTRAP_SUPERUSERID)
839  ereport(ERROR,
840  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
841  errmsg("permission denied: bootstrap user must be superuser")));
842 
843  new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(should_be_super);
844  new_record_repl[Anum_pg_authid_rolsuper - 1] = true;
845  }
846 
847  if (dinherit)
848  {
849  new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(boolVal(dinherit->arg));
850  new_record_repl[Anum_pg_authid_rolinherit - 1] = true;
851  }
852 
853  if (dcreaterole)
854  {
855  new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(boolVal(dcreaterole->arg));
856  new_record_repl[Anum_pg_authid_rolcreaterole - 1] = true;
857  }
858 
859  if (dcreatedb)
860  {
861  new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(boolVal(dcreatedb->arg));
862  new_record_repl[Anum_pg_authid_rolcreatedb - 1] = true;
863  }
864 
865  if (dcanlogin)
866  {
867  new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(boolVal(dcanlogin->arg));
868  new_record_repl[Anum_pg_authid_rolcanlogin - 1] = true;
869  }
870 
871  if (disreplication)
872  {
873  new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(boolVal(disreplication->arg));
874  new_record_repl[Anum_pg_authid_rolreplication - 1] = true;
875  }
876 
877  if (dconnlimit)
878  {
879  new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
880  new_record_repl[Anum_pg_authid_rolconnlimit - 1] = true;
881  }
882 
883  /* password */
884  if (password)
885  {
886  char *shadow_pass;
887  const char *logdetail = NULL;
888 
889  /* Like in CREATE USER, don't allow an empty password. */
890  if (password[0] == '\0' ||
891  plain_crypt_verify(rolename, password, "", &logdetail) == STATUS_OK)
892  {
893  ereport(NOTICE,
894  (errmsg("empty string is not a valid password, clearing password")));
895  new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
896  }
897  else
898  {
899  /* Encrypt the password to the requested format. */
900  shadow_pass = encrypt_password(Password_encryption, rolename,
901  password);
902  new_record[Anum_pg_authid_rolpassword - 1] =
903  CStringGetTextDatum(shadow_pass);
904  }
905  new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
906  }
907 
908  /* unset password */
909  if (dpassword && dpassword->arg == NULL)
910  {
911  new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
912  new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
913  }
914 
915  /* valid until */
916  new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
917  new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
918  new_record_repl[Anum_pg_authid_rolvaliduntil - 1] = true;
919 
920  if (dbypassRLS)
921  {
922  new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(boolVal(dbypassRLS->arg));
923  new_record_repl[Anum_pg_authid_rolbypassrls - 1] = true;
924  }
925 
926  new_tuple = heap_modify_tuple(tuple, pg_authid_dsc, new_record,
927  new_record_nulls, new_record_repl);
928  CatalogTupleUpdate(pg_authid_rel, &tuple->t_self, new_tuple);
929 
930  InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
931 
932  ReleaseSysCache(tuple);
933  heap_freetuple(new_tuple);
934 
935  InitGrantRoleOptions(&popt);
936 
937  /*
938  * Advance command counter so we can see new record; else tests in
939  * AddRoleMems may fail.
940  */
941  if (drolemembers)
942  {
943  List *rolemembers = (List *) drolemembers->arg;
944 
946 
947  if (stmt->action == +1) /* add members to role */
948  AddRoleMems(currentUserId, rolename, roleid,
949  rolemembers, roleSpecsToIds(rolemembers),
950  InvalidOid, &popt);
951  else if (stmt->action == -1) /* drop members from role */
952  DelRoleMems(currentUserId, rolename, roleid,
953  rolemembers, roleSpecsToIds(rolemembers),
954  InvalidOid, &popt, DROP_RESTRICT);
955  }
956 
957  /*
958  * Close pg_authid, but keep lock till commit.
959  */
960  table_close(pg_authid_rel, NoLock);
961 
962  return roleid;
963 }
bool is_admin_of_role(Oid member, Oid role)
Definition: acl.c:5099
void check_rolespec_name(const RoleSpec *role, const char *detail_msg)
Definition: acl.c:5396
HeapTuple get_rolespec_tuple(const RoleSpec *role)
Definition: acl.c:5328
bool has_bypassrls_privilege(Oid roleid)
Definition: aclchk.c:4084
Datum timestamptz_in(PG_FUNCTION_ARGS)
Definition: timestamp.c:398
#define CStringGetTextDatum(s)
Definition: builtins.h:94
#define NameStr(name)
Definition: c.h:730
#define STATUS_OK
Definition: c.h:1159
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char **logdetail)
Definition: crypt.c:223
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:116
bool have_createdb_privilege(void)
Definition: dbcommands.c:2745
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:385
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define _(x)
Definition: elog.c:91
#define ERROR
Definition: elog.h:39
#define NOTICE
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:149
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:646
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:653
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:1624
Oid GetUserId(void)
Definition: miscinit.c:502
bool has_rolreplication(Oid roleid)
Definition: miscinit.c:699
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
@ DROP_RESTRICT
Definition: parsenodes.h:2042
FormData_pg_authid * Form_pg_authid
Definition: pg_authid.h:56
#define lfirst(lc)
Definition: pg_list.h:172
uintptr_t Datum
Definition: postgres.h:64
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetDescr(relation)
Definition: rel.h:527
static char * password
Definition: streamutil.c:53
List * options
Definition: parsenodes.h:2813
RoleSpec * role
Definition: parsenodes.h:2812
char * defname
Definition: parsenodes.h:810
Node * arg
Definition: parsenodes.h:811
ItemPointerData t_self
Definition: htup.h:65
Definition: pg_list.h:54
bool superuser(void)
Definition: superuser.c:46
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:865
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition: syscache.c:1078
@ AUTHNAME
Definition: syscache.h:44
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
static bool have_createrole_privilege(void)
Definition: user.c:123
static void InitGrantRoleOptions(GrantRoleOptions *popt)
Definition: user.c:2425
static void AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, Oid grantorId, GrantRoleOptions *popt)
Definition: user.c:1636
int Password_encryption
Definition: user.c:86
List * roleSpecsToIds(List *memberNames)
Definition: user.c:1607
check_password_hook_type check_password_hook
Definition: user.c:92
static void DelRoleMems(Oid currentUserId, const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, Oid grantorId, GrantRoleOptions *popt, DropBehavior behavior)
Definition: user.c:1931
#define boolVal(v)
Definition: value.h:81
#define intVal(v)
Definition: value.h:79
#define strVal(v)
Definition: value.h:82
void CommandCounterIncrement(void)
Definition: xact.c:1078

References _, AlterRoleStmt::action, AddRoleMems(), DefElem::arg, AUTHNAME, BoolGetDatum(), boolVal, CatalogTupleUpdate(), check_password_hook, check_rolespec_name(), CommandCounterIncrement(), CStringGetDatum(), CStringGetTextDatum, DefElem::defname, DelRoleMems(), DirectFunctionCall3, DROP_RESTRICT, elog(), encrypt_password(), ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), get_password_type(), get_rolespec_tuple(), GETSTRUCT, GetUserId(), has_bypassrls_privilege(), has_rolreplication(), have_createdb_privilege(), have_createrole_privilege(), heap_freetuple(), heap_modify_tuple(), InitGrantRoleOptions(), Int32GetDatum(), intVal, InvalidOid, InvokeObjectPostAlterHook, is_admin_of_role(), lfirst, 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 970 of file user.c.

971 {
972  HeapTuple roletuple;
973  Form_pg_authid roleform;
974  Oid databaseid = InvalidOid;
975  Oid roleid = InvalidOid;
976 
977  if (stmt->role)
978  {
980  _("Cannot alter reserved roles."));
981 
982  roletuple = get_rolespec_tuple(stmt->role);
983  roleform = (Form_pg_authid) GETSTRUCT(roletuple);
984  roleid = roleform->oid;
985 
986  /*
987  * Obtain a lock on the role and make sure it didn't go away in the
988  * meantime.
989  */
990  shdepLockAndCheckObject(AuthIdRelationId, roleid);
991 
992  /*
993  * To mess with a superuser you gotta be superuser; otherwise you
994  * need CREATEROLE plus admin option on the target role; unless you're
995  * just trying to change your own settings
996  */
997  if (roleform->rolsuper)
998  {
999  if (!superuser())
1000  ereport(ERROR,
1001  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1002  errmsg("must be superuser to alter superusers")));
1003  }
1004  else
1005  {
1006  if ((!have_createrole_privilege() ||
1007  !is_admin_of_role(GetUserId(), roleid))
1008  && roleid != GetUserId())
1009  ereport(ERROR,
1010  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1011  errmsg("permission denied")));
1012  }
1013 
1014  ReleaseSysCache(roletuple);
1015  }
1016 
1017  /* look up and lock the database, if specified */
1018  if (stmt->database != NULL)
1019  {
1020  databaseid = get_database_oid(stmt->database, false);
1021  shdepLockAndCheckObject(DatabaseRelationId, databaseid);
1022 
1023  if (!stmt->role)
1024  {
1025  /*
1026  * If no role is specified, then this is effectively the same as
1027  * ALTER DATABASE ... SET, so use the same permission check.
1028  */
1029  if (!object_ownercheck(DatabaseRelationId, databaseid, GetUserId()))
1031  stmt->database);
1032  }
1033  }
1034 
1035  if (!stmt->role && !stmt->database)
1036  {
1037  /* Must be superuser to alter settings globally. */
1038  if (!superuser())
1039  ereport(ERROR,
1040  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1041  errmsg("must be superuser to alter settings globally")));
1042  }
1043 
1044  AlterSetting(databaseid, roleid, stmt->setstmt);
1045 
1046  return roleid;
1047 }
@ ACLCHECK_NOT_OWNER
Definition: acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition: aclchk.c:2679
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition: aclchk.c:3984
Oid get_database_oid(const char *dbname, bool missing_ok)
Definition: dbcommands.c:2933
@ OBJECT_DATABASE
Definition: parsenodes.h:1978
void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
void shdepLockAndCheckObject(Oid classId, Oid objectId)
Definition: pg_shdepend.c:1166
RoleSpec * role
Definition: parsenodes.h:2820
VariableSetStmt * setstmt
Definition: parsenodes.h:2822

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, is_admin_of_role(), OBJECT_DATABASE, object_ownercheck(), ReleaseSysCache(), AlterRoleSetStmt::role, AlterRoleSetStmt::setstmt, shdepLockAndCheckObject(), and superuser().

Referenced by standard_ProcessUtility().

◆ assign_createrole_self_grant()

void assign_createrole_self_grant ( const char *  newval,
void *  extra 
)

Definition at line 2488 of file user.c.

2489 {
2490  unsigned options = * (unsigned *) extra;
2491 
2501 }
unsigned specified
Definition: user.c:75
bool admin
Definition: user.c:76
bool set
Definition: user.c:78
bool inherit
Definition: user.c:77
#define GRANT_ROLE_SPECIFIED_ADMIN
Definition: user.c:81
GrantRoleOptions createrole_self_grant_options
Definition: user.c:89
bool createrole_self_grant_enabled
Definition: user.c:88
#define GRANT_ROLE_SPECIFIED_SET
Definition: user.c:83
#define GRANT_ROLE_SPECIFIED_INHERIT
Definition: user.c:82

References GrantRoleOptions::admin, createrole_self_grant_enabled, createrole_self_grant_options, GRANT_ROLE_SPECIFIED_ADMIN, GRANT_ROLE_SPECIFIED_INHERIT, GRANT_ROLE_SPECIFIED_SET, GrantRoleOptions::inherit, GrantRoleOptions::set, and GrantRoleOptions::specified.

◆ check_createrole_self_grant()

bool check_createrole_self_grant ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 2437 of file user.c.

2438 {
2439  char *rawstring;
2440  List *elemlist;
2441  ListCell *l;
2442  unsigned options = 0;
2443  unsigned *result;
2444 
2445  /* Need a modifiable copy of string */
2446  rawstring = pstrdup(*newval);
2447 
2448  if (!SplitIdentifierString(rawstring, ',', &elemlist))
2449  {
2450  /* syntax error in list */
2451  GUC_check_errdetail("List syntax is invalid.");
2452  pfree(rawstring);
2453  list_free(elemlist);
2454  return false;
2455  }
2456 
2457  foreach(l, elemlist)
2458  {
2459  char *tok = (char *) lfirst(l);
2460 
2461  if (pg_strcasecmp(tok, "SET") == 0)
2463  else if (pg_strcasecmp(tok, "INHERIT") == 0)
2465  else
2466  {
2467  GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
2468  pfree(rawstring);
2469  list_free(elemlist);
2470  return false;
2471  }
2472  }
2473 
2474  pfree(rawstring);
2475  list_free(elemlist);
2476 
2477  result = (unsigned *) guc_malloc(LOG, sizeof(unsigned));
2478  *result = options;
2479  *extra = result;
2480 
2481  return true;
2482 }
#define LOG
Definition: elog.h:31
void * guc_malloc(int elevel, size_t size)
Definition: guc.c:630
#define newval
#define GUC_check_errdetail
Definition: guc.h:437
void list_free(List *list)
Definition: list.c:1545
void pfree(void *pointer)
Definition: mcxt.c:1436
static char ** options
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3730

References GRANT_ROLE_SPECIFIED_INHERIT, GRANT_ROLE_SPECIFIED_SET, GUC_check_errdetail, guc_malloc(), lfirst, list_free(), LOG, newval, options, pfree(), pg_strcasecmp(), pstrdup(), and SplitIdentifierString().

◆ CreateRole()

Oid CreateRole ( ParseState pstate,
CreateRoleStmt stmt 
)

Definition at line 133 of file user.c.

134 {
135  Relation pg_authid_rel;
136  TupleDesc pg_authid_dsc;
137  HeapTuple tuple;
138  Datum new_record[Natts_pg_authid] = {0};
139  bool new_record_nulls[Natts_pg_authid] = {0};
140  Oid currentUserId = GetUserId();
141  Oid roleid;
142  ListCell *item;
143  ListCell *option;
144  char *password = NULL; /* user password */
145  bool issuper = false; /* Make the user a superuser? */
146  bool inherit = true; /* Auto inherit privileges? */
147  bool createrole = false; /* Can this user create roles? */
148  bool createdb = false; /* Can the user create databases? */
149  bool canlogin = false; /* Can this user login? */
150  bool isreplication = false; /* Is this a replication role? */
151  bool bypassrls = false; /* Is this a row security enabled role? */
152  int connlimit = -1; /* maximum connections allowed */
153  List *addroleto = NIL; /* roles to make this a member of */
154  List *rolemembers = NIL; /* roles to be members of this role */
155  List *adminmembers = NIL; /* roles to be admins of this role */
156  char *validUntil = NULL; /* time the login is valid until */
157  Datum validUntil_datum; /* same, as timestamptz Datum */
158  bool validUntil_null;
159  DefElem *dpassword = NULL;
160  DefElem *dissuper = NULL;
161  DefElem *dinherit = NULL;
162  DefElem *dcreaterole = NULL;
163  DefElem *dcreatedb = NULL;
164  DefElem *dcanlogin = NULL;
165  DefElem *disreplication = NULL;
166  DefElem *dconnlimit = NULL;
167  DefElem *daddroleto = NULL;
168  DefElem *drolemembers = NULL;
169  DefElem *dadminmembers = NULL;
170  DefElem *dvalidUntil = NULL;
171  DefElem *dbypassRLS = NULL;
172  GrantRoleOptions popt;
173 
174  /* The defaults can vary depending on the original statement type */
175  switch (stmt->stmt_type)
176  {
177  case ROLESTMT_ROLE:
178  break;
179  case ROLESTMT_USER:
180  canlogin = true;
181  /* may eventually want inherit to default to false here */
182  break;
183  case ROLESTMT_GROUP:
184  break;
185  }
186 
187  /* Extract options from the statement node tree */
188  foreach(option, stmt->options)
189  {
190  DefElem *defel = (DefElem *) lfirst(option);
191 
192  if (strcmp(defel->defname, "password") == 0)
193  {
194  if (dpassword)
195  errorConflictingDefElem(defel, pstate);
196  dpassword = defel;
197  }
198  else if (strcmp(defel->defname, "sysid") == 0)
199  {
200  ereport(NOTICE,
201  (errmsg("SYSID can no longer be specified")));
202  }
203  else if (strcmp(defel->defname, "superuser") == 0)
204  {
205  if (dissuper)
206  errorConflictingDefElem(defel, pstate);
207  dissuper = defel;
208  }
209  else if (strcmp(defel->defname, "inherit") == 0)
210  {
211  if (dinherit)
212  errorConflictingDefElem(defel, pstate);
213  dinherit = defel;
214  }
215  else if (strcmp(defel->defname, "createrole") == 0)
216  {
217  if (dcreaterole)
218  errorConflictingDefElem(defel, pstate);
219  dcreaterole = defel;
220  }
221  else if (strcmp(defel->defname, "createdb") == 0)
222  {
223  if (dcreatedb)
224  errorConflictingDefElem(defel, pstate);
225  dcreatedb = defel;
226  }
227  else if (strcmp(defel->defname, "canlogin") == 0)
228  {
229  if (dcanlogin)
230  errorConflictingDefElem(defel, pstate);
231  dcanlogin = defel;
232  }
233  else if (strcmp(defel->defname, "isreplication") == 0)
234  {
235  if (disreplication)
236  errorConflictingDefElem(defel, pstate);
237  disreplication = defel;
238  }
239  else if (strcmp(defel->defname, "connectionlimit") == 0)
240  {
241  if (dconnlimit)
242  errorConflictingDefElem(defel, pstate);
243  dconnlimit = defel;
244  }
245  else if (strcmp(defel->defname, "addroleto") == 0)
246  {
247  if (daddroleto)
248  errorConflictingDefElem(defel, pstate);
249  daddroleto = defel;
250  }
251  else if (strcmp(defel->defname, "rolemembers") == 0)
252  {
253  if (drolemembers)
254  errorConflictingDefElem(defel, pstate);
255  drolemembers = defel;
256  }
257  else if (strcmp(defel->defname, "adminmembers") == 0)
258  {
259  if (dadminmembers)
260  errorConflictingDefElem(defel, pstate);
261  dadminmembers = defel;
262  }
263  else if (strcmp(defel->defname, "validUntil") == 0)
264  {
265  if (dvalidUntil)
266  errorConflictingDefElem(defel, pstate);
267  dvalidUntil = defel;
268  }
269  else if (strcmp(defel->defname, "bypassrls") == 0)
270  {
271  if (dbypassRLS)
272  errorConflictingDefElem(defel, pstate);
273  dbypassRLS = defel;
274  }
275  else
276  elog(ERROR, "option \"%s\" not recognized",
277  defel->defname);
278  }
279 
280  if (dpassword && dpassword->arg)
281  password = strVal(dpassword->arg);
282  if (dissuper)
283  issuper = boolVal(dissuper->arg);
284  if (dinherit)
285  inherit = boolVal(dinherit->arg);
286  if (dcreaterole)
287  createrole = boolVal(dcreaterole->arg);
288  if (dcreatedb)
289  createdb = boolVal(dcreatedb->arg);
290  if (dcanlogin)
291  canlogin = boolVal(dcanlogin->arg);
292  if (disreplication)
293  isreplication = boolVal(disreplication->arg);
294  if (dconnlimit)
295  {
296  connlimit = intVal(dconnlimit->arg);
297  if (connlimit < -1)
298  ereport(ERROR,
299  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
300  errmsg("invalid connection limit: %d", connlimit)));
301  }
302  if (daddroleto)
303  addroleto = (List *) daddroleto->arg;
304  if (drolemembers)
305  rolemembers = (List *) drolemembers->arg;
306  if (dadminmembers)
307  adminmembers = (List *) dadminmembers->arg;
308  if (dvalidUntil)
309  validUntil = strVal(dvalidUntil->arg);
310  if (dbypassRLS)
311  bypassrls = boolVal(dbypassRLS->arg);
312 
313  /* Check some permissions first */
314  if (!superuser_arg(currentUserId))
315  {
316  if (!has_createrole_privilege(currentUserId))
317  ereport(ERROR,
318  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
319  errmsg("permission denied to create role")));
320  if (issuper)
321  ereport(ERROR,
322  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
323  errmsg("must be superuser to create superusers")));
325  ereport(ERROR,
326  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
327  errmsg("must have createdb permission to create createdb users")));
328  if (isreplication && !has_rolreplication(currentUserId))
329  ereport(ERROR,
330  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
331  errmsg("must have replication permission to create replication users")));
332  if (bypassrls && !has_bypassrls_privilege(currentUserId))
333  ereport(ERROR,
334  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
335  errmsg("must have bypassrls to create bypassrls users")));
336  }
337 
338  /*
339  * Check that the user is not trying to create a role in the reserved
340  * "pg_" namespace.
341  */
342  if (IsReservedName(stmt->role))
343  ereport(ERROR,
344  (errcode(ERRCODE_RESERVED_NAME),
345  errmsg("role name \"%s\" is reserved",
346  stmt->role),
347  errdetail("Role names starting with \"pg_\" are reserved.")));
348 
349  /*
350  * If built with appropriate switch, whine when regression-testing
351  * conventions for role names are violated.
352  */
353 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
354  if (strncmp(stmt->role, "regress_", 8) != 0)
355  elog(WARNING, "roles created by regression test cases should have names starting with \"regress_\"");
356 #endif
357 
358  /*
359  * Check the pg_authid relation to be certain the role doesn't already
360  * exist.
361  */
362  pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
363  pg_authid_dsc = RelationGetDescr(pg_authid_rel);
364 
365  if (OidIsValid(get_role_oid(stmt->role, true)))
366  ereport(ERROR,
368  errmsg("role \"%s\" already exists",
369  stmt->role)));
370 
371  /* Convert validuntil to internal form */
372  if (validUntil)
373  {
374  validUntil_datum = DirectFunctionCall3(timestamptz_in,
375  CStringGetDatum(validUntil),
377  Int32GetDatum(-1));
378  validUntil_null = false;
379  }
380  else
381  {
382  validUntil_datum = (Datum) 0;
383  validUntil_null = true;
384  }
385 
386  /*
387  * Call the password checking hook if there is one defined
388  */
390  (*check_password_hook) (stmt->role,
391  password,
393  validUntil_datum,
394  validUntil_null);
395 
396  /*
397  * Build a tuple to insert
398  */
399  new_record[Anum_pg_authid_rolname - 1] =
401  new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper);
402  new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit);
403  new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole);
404  new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb);
405  new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin);
406  new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication);
407  new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
408 
409  if (password)
410  {
411  char *shadow_pass;
412  const char *logdetail = NULL;
413 
414  /*
415  * Don't allow an empty password. Libpq treats an empty password the
416  * same as no password at all, and won't even try to authenticate. But
417  * other clients might, so allowing it would be confusing. By clearing
418  * the password when an empty string is specified, the account is
419  * consistently locked for all clients.
420  *
421  * Note that this only covers passwords stored in the database itself.
422  * There are also checks in the authentication code, to forbid an
423  * empty password from being used with authentication methods that
424  * fetch the password from an external system, like LDAP or PAM.
425  */
426  if (password[0] == '\0' ||
427  plain_crypt_verify(stmt->role, password, "", &logdetail) == STATUS_OK)
428  {
429  ereport(NOTICE,
430  (errmsg("empty string is not a valid password, clearing password")));
431  new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
432  }
433  else
434  {
435  /* Encrypt the password to the requested format. */
436  shadow_pass = encrypt_password(Password_encryption, stmt->role,
437  password);
438  new_record[Anum_pg_authid_rolpassword - 1] =
439  CStringGetTextDatum(shadow_pass);
440  }
441  }
442  else
443  new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
444 
445  new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
446  new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
447 
448  new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(bypassrls);
449 
450  /*
451  * pg_largeobject_metadata contains pg_authid.oid's, so we use the
452  * binary-upgrade override.
453  */
454  if (IsBinaryUpgrade)
455  {
457  ereport(ERROR,
458  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
459  errmsg("pg_authid OID value not set when in binary upgrade mode")));
460 
463  }
464  else
465  {
466  roleid = GetNewOidWithIndex(pg_authid_rel, AuthIdOidIndexId,
467  Anum_pg_authid_oid);
468  }
469 
470  new_record[Anum_pg_authid_oid - 1] = ObjectIdGetDatum(roleid);
471 
472  tuple = heap_form_tuple(pg_authid_dsc, new_record, new_record_nulls);
473 
474  /*
475  * Insert new record in the pg_authid table
476  */
477  CatalogTupleInsert(pg_authid_rel, tuple);
478 
479  /*
480  * Advance command counter so we can see new record; else tests in
481  * AddRoleMems may fail.
482  */
483  if (addroleto || adminmembers || rolemembers)
485 
486  /* Default grant. */
487  InitGrantRoleOptions(&popt);
488 
489  /*
490  * Add the new role to the specified existing roles.
491  */
492  if (addroleto)
493  {
494  RoleSpec *thisrole = makeNode(RoleSpec);
495  List *thisrole_list = list_make1(thisrole);
496  List *thisrole_oidlist = list_make1_oid(roleid);
497 
498  thisrole->roletype = ROLESPEC_CSTRING;
499  thisrole->rolename = stmt->role;
500  thisrole->location = -1;
501 
502  foreach(item, addroleto)
503  {
504  RoleSpec *oldrole = lfirst(item);
505  HeapTuple oldroletup = get_rolespec_tuple(oldrole);
506  Form_pg_authid oldroleform = (Form_pg_authid) GETSTRUCT(oldroletup);
507  Oid oldroleid = oldroleform->oid;
508  char *oldrolename = NameStr(oldroleform->rolname);
509 
510  /* can only add this role to roles for which you have rights */
511  check_role_membership_authorization(currentUserId, oldroleid, true);
512  AddRoleMems(currentUserId, oldrolename, oldroleid,
513  thisrole_list,
514  thisrole_oidlist,
515  InvalidOid, &popt);
516 
517  ReleaseSysCache(oldroletup);
518  }
519  }
520 
521  /*
522  * If the current user isn't a superuser, make them an admin of the new
523  * role so that they can administer the new object they just created.
524  * Superusers will be able to do that anyway.
525  *
526  * The grantor of record for this implicit grant is the bootstrap
527  * superuser, which means that the CREATEROLE user cannot revoke the
528  * grant. They can however grant the created role back to themselves
529  * with different options, since they enjoy ADMIN OPTION on it.
530  */
531  if (!superuser())
532  {
533  RoleSpec *current_role = makeNode(RoleSpec);
534  GrantRoleOptions poptself;
535  List *memberSpecs;
536  List *memberIds = list_make1_oid(currentUserId);
537 
538  current_role->roletype = ROLESPEC_CURRENT_ROLE;
539  current_role->location = -1;
540  memberSpecs = list_make1(current_role);
541 
545  poptself.admin = true;
546  poptself.inherit = false;
547  poptself.set = false;
548 
549  AddRoleMems(BOOTSTRAP_SUPERUSERID, stmt->role, roleid,
550  memberSpecs, memberIds,
551  BOOTSTRAP_SUPERUSERID, &poptself);
552 
553  /*
554  * We must make the implicit grant visible to the code below, else
555  * the additional grants will fail.
556  */
558 
559  /*
560  * Because of the implicit grant above, a CREATEROLE user who creates
561  * a role has the ability to grant that role back to themselves with
562  * the INHERIT or SET options, if they wish to inherit the role's
563  * privileges or be able to SET ROLE to it. The createrole_self_grant
564  * GUC can be used to make this happen automatically. This has no
565  * security implications since the same user is able to make the same
566  * grant using an explicit GRANT statement; it's just convenient.
567  */
569  AddRoleMems(currentUserId, stmt->role, roleid,
570  memberSpecs, memberIds,
571  currentUserId, &createrole_self_grant_options);
572  }
573 
574  /*
575  * Add the specified members to this new role. adminmembers get the admin
576  * option, rolemembers don't.
577  *
578  * NB: No permissions check is required here. If you have enough rights
579  * to create a role, you can add any members you like.
580  */
581  AddRoleMems(currentUserId, stmt->role, roleid,
582  rolemembers, roleSpecsToIds(rolemembers),
583  InvalidOid, &popt);
585  popt.admin = true;
586  AddRoleMems(currentUserId, stmt->role, roleid,
587  adminmembers, roleSpecsToIds(adminmembers),
588  InvalidOid, &popt);
589 
590  /* Post creation hook for new role */
591  InvokeObjectPostCreateHook(AuthIdRelationId, roleid, 0);
592 
593  /*
594  * Close pg_authid, but keep lock till commit.
595  */
596  table_close(pg_authid_rel, NoLock);
597 
598  return roleid;
599 }
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition: acl.c:5255
bool has_createrole_privilege(Oid roleid)
Definition: aclchk.c:4065
#define OidIsValid(objectId)
Definition: c.h:759
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition: catalog.c:393
bool IsReservedName(const char *name)
Definition: catalog.c:219
Oid createdb(ParseState *pstate, const CreatedbStmt *stmt)
Definition: dbcommands.c:670
int errdetail(const char *fmt,...)
Definition: elog.c:1202
#define WARNING
Definition: elog.h:36
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:642
bool IsBinaryUpgrade
Definition: globals.c:114
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
Datum namein(PG_FUNCTION_ARGS)
Definition: name.c:48
#define makeNode(_type_)
Definition: nodes.h:176
#define InvokeObjectPostCreateHook(classId, objectId, subId)
Definition: objectaccess.h:173
@ ROLESPEC_CSTRING
Definition: parsenodes.h:392
@ ROLESPEC_CURRENT_ROLE
Definition: parsenodes.h:393
@ ROLESTMT_ROLE
Definition: parsenodes.h:2796
@ ROLESTMT_USER
Definition: parsenodes.h:2797
@ ROLESTMT_GROUP
Definition: parsenodes.h:2798
#define NIL
Definition: pg_list.h:68
#define list_make1_oid(x1)
Definition: pg_list.h:242
#define list_make1(x1)
Definition: pg_list.h:212
#define ERRCODE_DUPLICATE_OBJECT
Definition: streamutil.c:32
RoleStmtType stmt_type
Definition: parsenodes.h:2804
RoleSpecType roletype
Definition: parsenodes.h:402
int location
Definition: parsenodes.h:404
char * rolename
Definition: parsenodes.h:403
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
static void check_role_membership_authorization(Oid currentUserId, Oid roleid, bool is_grant)
Definition: user.c:2063
Oid binary_upgrade_next_pg_authid_oid
Definition: user.c:71

References AddRoleMems(), GrantRoleOptions::admin, DefElem::arg, binary_upgrade_next_pg_authid_oid, BoolGetDatum(), boolVal, CatalogTupleInsert(), check_password_hook, check_role_membership_authorization(), CommandCounterIncrement(), createdb(), createrole_self_grant_enabled, createrole_self_grant_options, 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(), GRANT_ROLE_SPECIFIED_ADMIN, GRANT_ROLE_SPECIFIED_INHERIT, GRANT_ROLE_SPECIFIED_SET, has_bypassrls_privilege(), has_createrole_privilege(), has_rolreplication(), have_createdb_privilege(), heap_form_tuple(), if(), GrantRoleOptions::inherit, InitGrantRoleOptions(), Int32GetDatum(), intVal, InvalidOid, InvokeObjectPostCreateHook, IsBinaryUpgrade, IsReservedName(), lfirst, list_make1, list_make1_oid, RoleSpec::location, makeNode, namein(), NameStr, NIL, NoLock, NOTICE, ObjectIdGetDatum(), OidIsValid, CreateRoleStmt::options, password, Password_encryption, plain_crypt_verify(), RelationGetDescr, ReleaseSysCache(), CreateRoleStmt::role, RoleSpec::rolename, ROLESPEC_CSTRING, ROLESPEC_CURRENT_ROLE, roleSpecsToIds(), ROLESTMT_GROUP, ROLESTMT_ROLE, ROLESTMT_USER, RoleSpec::roletype, RowExclusiveLock, GrantRoleOptions::set, GrantRoleOptions::specified, STATUS_OK, CreateRoleStmt::stmt_type, strVal, superuser(), superuser_arg(), table_close(), table_open(), timestamptz_in(), and WARNING.

Referenced by standard_ProcessUtility().

◆ DropOwnedObjects()

void DropOwnedObjects ( DropOwnedStmt stmt)

Definition at line 1544 of file user.c.

1545 {
1546  List *role_ids = roleSpecsToIds(stmt->roles);
1547  ListCell *cell;
1548 
1549  /* Check privileges */
1550  foreach(cell, role_ids)
1551  {
1552  Oid roleid = lfirst_oid(cell);
1553 
1554  if (!has_privs_of_role(GetUserId(), roleid))
1555  ereport(ERROR,
1556  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1557  errmsg("permission denied to drop objects")));
1558  }
1559 
1560  /* Ok, do it */
1561  shdepDropOwned(role_ids, stmt->behavior);
1562 }
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4969
#define lfirst_oid(lc)
Definition: pg_list.h:174
void shdepDropOwned(List *roleids, DropBehavior behavior)
Definition: pg_shdepend.c:1295
DropBehavior behavior
Definition: parsenodes.h:3781

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 1054 of file user.c.

1055 {
1056  Relation pg_authid_rel,
1057  pg_auth_members_rel;
1058  ListCell *item;
1059  List *role_addresses = NIL;
1060 
1062  ereport(ERROR,
1063  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1064  errmsg("permission denied to drop role")));
1065 
1066  /*
1067  * Scan the pg_authid relation to find the Oid of the role(s) to be
1068  * deleted and perform preliminary permissions and sanity checks.
1069  */
1070  pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
1071  pg_auth_members_rel = table_open(AuthMemRelationId, RowExclusiveLock);
1072 
1073  foreach(item, stmt->roles)
1074  {
1075  RoleSpec *rolspec = lfirst(item);
1076  char *role;
1077  HeapTuple tuple,
1078  tmp_tuple;
1079  Form_pg_authid roleform;
1080  ScanKeyData scankey;
1081  SysScanDesc sscan;
1082  Oid roleid;
1083  ObjectAddress *role_address;
1084 
1085  if (rolspec->roletype != ROLESPEC_CSTRING)
1086  ereport(ERROR,
1087  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1088  errmsg("cannot use special role specifier in DROP ROLE")));
1089  role = rolspec->rolename;
1090 
1091  tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
1092  if (!HeapTupleIsValid(tuple))
1093  {
1094  if (!stmt->missing_ok)
1095  {
1096  ereport(ERROR,
1097  (errcode(ERRCODE_UNDEFINED_OBJECT),
1098  errmsg("role \"%s\" does not exist", role)));
1099  }
1100  else
1101  {
1102  ereport(NOTICE,
1103  (errmsg("role \"%s\" does not exist, skipping",
1104  role)));
1105  }
1106 
1107  continue;
1108  }
1109 
1110  roleform = (Form_pg_authid) GETSTRUCT(tuple);
1111  roleid = roleform->oid;
1112 
1113  if (roleid == GetUserId())
1114  ereport(ERROR,
1115  (errcode(ERRCODE_OBJECT_IN_USE),
1116  errmsg("current user cannot be dropped")));
1117  if (roleid == GetOuterUserId())
1118  ereport(ERROR,
1119  (errcode(ERRCODE_OBJECT_IN_USE),
1120  errmsg("current user cannot be dropped")));
1121  if (roleid == GetSessionUserId())
1122  ereport(ERROR,
1123  (errcode(ERRCODE_OBJECT_IN_USE),
1124  errmsg("session user cannot be dropped")));
1125 
1126  /*
1127  * For safety's sake, we allow createrole holders to drop ordinary
1128  * roles but not superuser roles, and only if they also have ADMIN
1129  * OPTION.
1130  */
1131  if (roleform->rolsuper && !superuser())
1132  ereport(ERROR,
1133  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1134  errmsg("must be superuser to drop superusers")));
1135  if (!is_admin_of_role(GetUserId(), roleid))
1136  ereport(ERROR,
1137  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1138  errmsg("must have admin option on role \"%s\"",
1139  role)));
1140 
1141  /* DROP hook for the role being removed */
1142  InvokeObjectDropHook(AuthIdRelationId, roleid, 0);
1143 
1144  /* Don't leak the syscache tuple */
1145  ReleaseSysCache(tuple);
1146 
1147  /*
1148  * Lock the role, so nobody can add dependencies to her while we drop
1149  * her. We keep the lock until the end of transaction.
1150  */
1151  LockSharedObject(AuthIdRelationId, roleid, 0, AccessExclusiveLock);
1152 
1153  /*
1154  * If there is a pg_auth_members entry that has one of the roles to be
1155  * dropped as the roleid or member, it should be silently removed, but
1156  * if there is a pg_auth_members entry that has one of the roles to be
1157  * dropped as the grantor, the operation should fail.
1158  *
1159  * It's possible, however, that a single pg_auth_members entry could
1160  * fall into multiple categories - e.g. the user could do "GRANT foo
1161  * TO bar GRANTED BY baz" and then "DROP ROLE baz, bar". We want such
1162  * an operation to succeed regardless of the order in which the
1163  * to-be-dropped roles are passed to DROP ROLE.
1164  *
1165  * To make that work, we remove all pg_auth_members entries that can
1166  * be silently removed in this loop, and then below we'll make a
1167  * second pass over the list of roles to be removed and check for any
1168  * remaining dependencies.
1169  */
1170  ScanKeyInit(&scankey,
1171  Anum_pg_auth_members_roleid,
1172  BTEqualStrategyNumber, F_OIDEQ,
1173  ObjectIdGetDatum(roleid));
1174 
1175  sscan = systable_beginscan(pg_auth_members_rel, AuthMemRoleMemIndexId,
1176  true, NULL, 1, &scankey);
1177 
1178  while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
1179  {
1180  Form_pg_auth_members authmem_form;
1181 
1182  authmem_form = (Form_pg_auth_members) GETSTRUCT(tmp_tuple);
1183  deleteSharedDependencyRecordsFor(AuthMemRelationId,
1184  authmem_form->oid, 0);
1185  CatalogTupleDelete(pg_auth_members_rel, &tmp_tuple->t_self);
1186  }
1187 
1188  systable_endscan(sscan);
1189 
1190  ScanKeyInit(&scankey,
1191  Anum_pg_auth_members_member,
1192  BTEqualStrategyNumber, F_OIDEQ,
1193  ObjectIdGetDatum(roleid));
1194 
1195  sscan = systable_beginscan(pg_auth_members_rel, AuthMemMemRoleIndexId,
1196  true, NULL, 1, &scankey);
1197 
1198  while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
1199  {
1200  Form_pg_auth_members authmem_form;
1201 
1202  authmem_form = (Form_pg_auth_members) GETSTRUCT(tmp_tuple);
1203  deleteSharedDependencyRecordsFor(AuthMemRelationId,
1204  authmem_form->oid, 0);
1205  CatalogTupleDelete(pg_auth_members_rel, &tmp_tuple->t_self);
1206  }
1207 
1208  systable_endscan(sscan);
1209 
1210  /*
1211  * Advance command counter so that later iterations of this loop will
1212  * see the changes already made. This is essential if, for example,
1213  * we are trying to drop both a role and one of its direct members ---
1214  * we'll get an error if we try to delete the linking pg_auth_members
1215  * tuple twice. (We do not need a CCI between the two delete loops
1216  * above, because it's not allowed for a role to directly contain
1217  * itself.)
1218  */
1220 
1221  /* Looks tentatively OK, add it to the list. */
1222  role_address = palloc(sizeof(ObjectAddress));
1223  role_address->classId = AuthIdRelationId;
1224  role_address->objectId = roleid;
1225  role_address->objectSubId = 0;
1226  role_addresses = lappend(role_addresses, role_address);
1227  }
1228 
1229  /*
1230  * Second pass over the roles to be removed.
1231  */
1232  foreach(item, role_addresses)
1233  {
1234  ObjectAddress *role_address = lfirst(item);
1235  Oid roleid = role_address->objectId;
1236  HeapTuple tuple;
1237  Form_pg_authid roleform;
1238  char *detail;
1239  char *detail_log;
1240 
1241  /*
1242  * Re-find the pg_authid tuple.
1243  *
1244  * Since we've taken a lock on the role OID, it shouldn't be possible
1245  * for the tuple to have been deleted -- or for that matter updated --
1246  * unless the user is manually modifying the system catalogs.
1247  */
1248  tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
1249  if (!HeapTupleIsValid(tuple))
1250  elog(ERROR, "could not find tuple for role %u", roleid);
1251  roleform = (Form_pg_authid) GETSTRUCT(tuple);
1252 
1253  /*
1254  * Check for pg_shdepend entries depending on this role.
1255  *
1256  * This needs to happen after we've completed removing any
1257  * pg_auth_members entries that can be removed silently, in order to
1258  * avoid spurious failures. See notes above for more details.
1259  */
1260  if (checkSharedDependencies(AuthIdRelationId, roleid,
1261  &detail, &detail_log))
1262  ereport(ERROR,
1263  (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1264  errmsg("role \"%s\" cannot be dropped because some objects depend on it",
1265  NameStr(roleform->rolname)),
1266  errdetail_internal("%s", detail),
1267  errdetail_log("%s", detail_log)));
1268 
1269  /*
1270  * Remove the role from the pg_authid table
1271  */
1272  CatalogTupleDelete(pg_authid_rel, &tuple->t_self);
1273 
1274  ReleaseSysCache(tuple);
1275 
1276  /*
1277  * Remove any comments or security labels on this role.
1278  */
1279  DeleteSharedComments(roleid, AuthIdRelationId);
1280  DeleteSharedSecurityLabel(roleid, AuthIdRelationId);
1281 
1282  /*
1283  * Remove settings for this role.
1284  */
1285  DropSetting(InvalidOid, roleid);
1286  }
1287 
1288  /*
1289  * Now we can clean up; but keep locks until commit.
1290  */
1291  table_close(pg_auth_members_rel, NoLock);
1292  table_close(pg_authid_rel, NoLock);
1293 }
void DeleteSharedComments(Oid oid, Oid classoid)
Definition: comment.c:374
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1229
int errdetail_log(const char *fmt,...)
Definition: elog.c:1250
void systable_endscan(SysScanDesc sysscan)
Definition: genam.c:599
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition: genam.c:506
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition: genam.c:387
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
List * lappend(List *list, void *datum)
Definition: list.c:338
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition: lmgr.c:1046
#define AccessExclusiveLock
Definition: lockdefs.h:43
void * palloc(Size size)
Definition: mcxt.c:1210
Oid GetOuterUserId(void)
Definition: miscinit.c:513
Oid GetSessionUserId(void)
Definition: miscinit.c:536
#define InvokeObjectDropHook(classId, objectId, subId)
Definition: objectaccess.h:182
FormData_pg_auth_members * Form_pg_auth_members
void DropSetting(Oid databaseid, Oid roleid)
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
Definition: pg_shdepend.c:1002
bool checkSharedDependencies(Oid classId, Oid objectId, char **detail_msg, char **detail_log_msg)
Definition: pg_shdepend.c:631
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
Definition: scankey.c:76
void DeleteSharedSecurityLabel(Oid objectId, Oid classId)
Definition: seclabel.c:491
#define BTEqualStrategyNumber
Definition: stratnum.h:31
List * roles
Definition: parsenodes.h:2828
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:817
@ AUTHOID
Definition: syscache.h:45

References AccessExclusiveLock, AUTHNAME, AUTHOID, BTEqualStrategyNumber, CatalogTupleDelete(), checkSharedDependencies(), ObjectAddress::classId, CommandCounterIncrement(), DeleteSharedComments(), deleteSharedDependencyRecordsFor(), DeleteSharedSecurityLabel(), DropSetting(), elog(), ereport, errcode(), errdetail_internal(), errdetail_log(), errmsg(), ERROR, GetOuterUserId(), GetSessionUserId(), GETSTRUCT, GetUserId(), have_createrole_privilege(), HeapTupleIsValid, InvalidOid, InvokeObjectDropHook, is_admin_of_role(), lappend(), lfirst, LockSharedObject(), DropRoleStmt::missing_ok, NameStr, NIL, NoLock, NOTICE, ObjectAddress::objectId, ObjectIdGetDatum(), ObjectAddress::objectSubId, palloc(), 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 ( ParseState pstate,
GrantRoleStmt stmt 
)

Definition at line 1441 of file user.c.

1442 {
1443  Relation pg_authid_rel;
1444  Oid grantor;
1445  List *grantee_ids;
1446  ListCell *item;
1447  GrantRoleOptions popt;
1448  Oid currentUserId = GetUserId();
1449 
1450  /* Parse options list. */
1451  InitGrantRoleOptions(&popt);
1452  foreach(item, stmt->opt)
1453  {
1454  DefElem *opt = (DefElem *) lfirst(item);
1455  char *optval = defGetString(opt);
1456 
1457  if (strcmp(opt->defname, "admin") == 0)
1458  {
1460 
1461  if (parse_bool(optval, &popt.admin))
1462  continue;
1463  }
1464  else if (strcmp(opt->defname, "inherit") == 0)
1465  {
1467  if (parse_bool(optval, &popt.inherit))
1468  continue;
1469  }
1470  else if (strcmp(opt->defname, "set") == 0)
1471  {
1473  if (parse_bool(optval, &popt.set))
1474  continue;
1475  }
1476  else
1477  ereport(ERROR,
1478  errcode(ERRCODE_SYNTAX_ERROR),
1479  errmsg("unrecognized role option \"%s\"", opt->defname),
1480  parser_errposition(pstate, opt->location));
1481 
1482  ereport(ERROR,
1483  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1484  errmsg("unrecognized value for role option \"%s\": \"%s\"",
1485  opt->defname, optval),
1486  parser_errposition(pstate, opt->location)));
1487  }
1488 
1489  /* Lookup OID of grantor, if specified. */
1490  if (stmt->grantor)
1491  grantor = get_rolespec_oid(stmt->grantor, false);
1492  else
1493  grantor = InvalidOid;
1494 
1495  grantee_ids = roleSpecsToIds(stmt->grantee_roles);
1496 
1497  /* AccessShareLock is enough since we aren't modifying pg_authid */
1498  pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
1499 
1500  /*
1501  * Step through all of the granted roles and add, update, or remove
1502  * entries in pg_auth_members as appropriate. If stmt->is_grant is true,
1503  * we are adding new grants or, if they already exist, updating options
1504  * on those grants. If stmt->is_grant is false, we are revoking grants or
1505  * removing options from them.
1506  */
1507  foreach(item, stmt->granted_roles)
1508  {
1509  AccessPriv *priv = (AccessPriv *) lfirst(item);
1510  char *rolename = priv->priv_name;
1511  Oid roleid;
1512 
1513  /* Must reject priv(columns) and ALL PRIVILEGES(columns) */
1514  if (rolename == NULL || priv->cols != NIL)
1515  ereport(ERROR,
1516  (errcode(ERRCODE_INVALID_GRANT_OPERATION),
1517  errmsg("column names cannot be included in GRANT/REVOKE ROLE")));
1518 
1519  roleid = get_role_oid(rolename, false);
1521  roleid, stmt->is_grant);
1522  if (stmt->is_grant)
1523  AddRoleMems(currentUserId, rolename, roleid,
1524  stmt->grantee_roles, grantee_ids,
1525  grantor, &popt);
1526  else
1527  DelRoleMems(currentUserId, rolename, roleid,
1528  stmt->grantee_roles, grantee_ids,
1529  grantor, &popt, stmt->behavior);
1530  }
1531 
1532  /*
1533  * Close pg_authid, but keep lock till commit.
1534  */
1535  table_close(pg_authid_rel, NoLock);
1536 }
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition: acl.c:5289
bool parse_bool(const char *value, bool *result)
Definition: bool.c:30
char * defGetString(DefElem *def)
Definition: define.c:49
#define AccessShareLock
Definition: lockdefs.h:36
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
char * priv_name
Definition: parsenodes.h:2253
List * cols
Definition: parsenodes.h:2254
int location
Definition: parsenodes.h:814
DropBehavior behavior
Definition: parsenodes.h:2274
RoleSpec * grantor
Definition: parsenodes.h:2273
List * grantee_roles
Definition: parsenodes.h:2270
List * granted_roles
Definition: parsenodes.h:2269

References AccessShareLock, AddRoleMems(), GrantRoleOptions::admin, GrantRoleStmt::behavior, check_role_membership_authorization(), AccessPriv::cols, defGetString(), DefElem::defname, DelRoleMems(), ereport, errcode(), errmsg(), ERROR, get_role_oid(), get_rolespec_oid(), GetUserId(), GRANT_ROLE_SPECIFIED_ADMIN, GRANT_ROLE_SPECIFIED_INHERIT, GRANT_ROLE_SPECIFIED_SET, GrantRoleStmt::granted_roles, GrantRoleStmt::grantee_roles, GrantRoleStmt::grantor, GrantRoleOptions::inherit, InitGrantRoleOptions(), InvalidOid, GrantRoleStmt::is_grant, lfirst, DefElem::location, NIL, NoLock, GrantRoleStmt::opt, parse_bool(), parser_errposition(), AccessPriv::priv_name, roleSpecsToIds(), GrantRoleOptions::set, GrantRoleOptions::specified, table_close(), and table_open().

Referenced by standard_ProcessUtility().

◆ ReassignOwnedObjects()

void ReassignOwnedObjects ( ReassignOwnedStmt stmt)

Definition at line 1570 of file user.c.

1571 {
1572  List *role_ids = roleSpecsToIds(stmt->roles);
1573  ListCell *cell;
1574  Oid newrole;
1575 
1576  /* Check privileges */
1577  foreach(cell, role_ids)
1578  {
1579  Oid roleid = lfirst_oid(cell);
1580 
1581  if (!has_privs_of_role(GetUserId(), roleid))
1582  ereport(ERROR,
1583  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1584  errmsg("permission denied to reassign objects")));
1585  }
1586 
1587  /* Must have privileges on the receiving side too */
1588  newrole = get_rolespec_oid(stmt->newrole, false);
1589 
1590  if (!has_privs_of_role(GetUserId(), newrole))
1591  ereport(ERROR,
1592  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1593  errmsg("permission denied to reassign objects")));
1594 
1595  /* Ok, do it */
1596  shdepReassignOwned(role_ids, newrole);
1597 }
void shdepReassignOwned(List *roleids, Oid newrole)
Definition: pg_shdepend.c:1467
RoleSpec * newrole
Definition: parsenodes.h:3791

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 1299 of file user.c.

1300 {
1301  HeapTuple oldtuple,
1302  newtuple;
1303  TupleDesc dsc;
1304  Relation rel;
1305  Datum datum;
1306  bool isnull;
1307  Datum repl_val[Natts_pg_authid];
1308  bool repl_null[Natts_pg_authid];
1309  bool repl_repl[Natts_pg_authid];
1310  int i;
1311  Oid roleid;
1312  ObjectAddress address;
1313  Form_pg_authid authform;
1314 
1315  rel = table_open(AuthIdRelationId, RowExclusiveLock);
1316  dsc = RelationGetDescr(rel);
1317 
1318  oldtuple = SearchSysCache1(AUTHNAME, CStringGetDatum(oldname));
1319  if (!HeapTupleIsValid(oldtuple))
1320  ereport(ERROR,
1321  (errcode(ERRCODE_UNDEFINED_OBJECT),
1322  errmsg("role \"%s\" does not exist", oldname)));
1323 
1324  /*
1325  * XXX Client applications probably store the session user somewhere, so
1326  * renaming it could cause confusion. On the other hand, there may not be
1327  * an actual problem besides a little confusion, so think about this and
1328  * decide. Same for SET ROLE ... we don't restrict renaming the current
1329  * effective userid, though.
1330  */
1331 
1332  authform = (Form_pg_authid) GETSTRUCT(oldtuple);
1333  roleid = authform->oid;
1334 
1335  if (roleid == GetSessionUserId())
1336  ereport(ERROR,
1337  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1338  errmsg("session user cannot be renamed")));
1339  if (roleid == GetOuterUserId())
1340  ereport(ERROR,
1341  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1342  errmsg("current user cannot be renamed")));
1343 
1344  /*
1345  * Check that the user is not trying to rename a system role and not
1346  * trying to rename a role into the reserved "pg_" namespace.
1347  */
1348  if (IsReservedName(NameStr(authform->rolname)))
1349  ereport(ERROR,
1350  (errcode(ERRCODE_RESERVED_NAME),
1351  errmsg("role name \"%s\" is reserved",
1352  NameStr(authform->rolname)),
1353  errdetail("Role names starting with \"pg_\" are reserved.")));
1354 
1355  if (IsReservedName(newname))
1356  ereport(ERROR,
1357  (errcode(ERRCODE_RESERVED_NAME),
1358  errmsg("role name \"%s\" is reserved",
1359  newname),
1360  errdetail("Role names starting with \"pg_\" are reserved.")));
1361 
1362  /*
1363  * If built with appropriate switch, whine when regression-testing
1364  * conventions for role names are violated.
1365  */
1366 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
1367  if (strncmp(newname, "regress_", 8) != 0)
1368  elog(WARNING, "roles created by regression test cases should have names starting with \"regress_\"");
1369 #endif
1370 
1371  /* make sure the new name doesn't exist */
1373  ereport(ERROR,
1375  errmsg("role \"%s\" already exists", newname)));
1376 
1377  /*
1378  * Only superusers can mess with superusers. Otherwise, a user with
1379  * CREATEROLE can rename a role for which they have ADMIN OPTION.
1380  */
1381  if (((Form_pg_authid) GETSTRUCT(oldtuple))->rolsuper)
1382  {
1383  if (!superuser())
1384  ereport(ERROR,
1385  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1386  errmsg("must be superuser to rename superusers")));
1387  }
1388  else
1389  {
1390  if (!have_createrole_privilege() ||
1391  !is_admin_of_role(GetUserId(), roleid))
1392  ereport(ERROR,
1393  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1394  errmsg("permission denied to rename role")));
1395  }
1396 
1397  /* OK, construct the modified tuple */
1398  for (i = 0; i < Natts_pg_authid; i++)
1399  repl_repl[i] = false;
1400 
1401  repl_repl[Anum_pg_authid_rolname - 1] = true;
1402  repl_val[Anum_pg_authid_rolname - 1] = DirectFunctionCall1(namein,
1403  CStringGetDatum(newname));
1404  repl_null[Anum_pg_authid_rolname - 1] = false;
1405 
1406  datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull);
1407 
1408  if (!isnull && get_password_type(TextDatumGetCString(datum)) == PASSWORD_TYPE_MD5)
1409  {
1410  /* MD5 uses the username as salt, so just clear it on a rename */
1411  repl_repl[Anum_pg_authid_rolpassword - 1] = true;
1412  repl_null[Anum_pg_authid_rolpassword - 1] = true;
1413 
1414  ereport(NOTICE,
1415  (errmsg("MD5 password cleared because of role rename")));
1416  }
1417 
1418  newtuple = heap_modify_tuple(oldtuple, dsc, repl_val, repl_null, repl_repl);
1419  CatalogTupleUpdate(rel, &oldtuple->t_self, newtuple);
1420 
1421  InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
1422 
1423  ObjectAddressSet(address, AuthIdRelationId, roleid);
1424 
1425  ReleaseSysCache(oldtuple);
1426 
1427  /*
1428  * Close pg_authid, but keep lock till commit.
1429  */
1430  table_close(rel, NoLock);
1431 
1432  return address;
1433 }
#define TextDatumGetCString(d)
Definition: builtins.h:95
@ PASSWORD_TYPE_MD5
Definition: crypt.h:30
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
int i
Definition: isn.c:73
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:188

References AUTHNAME, CatalogTupleUpdate(), CStringGetDatum(), DirectFunctionCall1, elog(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errdetail(), errmsg(), ERROR, get_password_type(), GetOuterUserId(), GetSessionUserId(), GETSTRUCT, GetUserId(), have_createrole_privilege(), heap_getattr(), heap_modify_tuple(), HeapTupleIsValid, i, InvokeObjectPostAlterHook, is_admin_of_role(), 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 1607 of file user.c.

1608 {
1609  List *result = NIL;
1610  ListCell *l;
1611 
1612  foreach(l, memberNames)
1613  {
1614  RoleSpec *rolespec = lfirst_node(RoleSpec, l);
1615  Oid roleid;
1616 
1617  roleid = get_rolespec_oid(rolespec, false);
1618  result = lappend_oid(result, roleid);
1619  }
1620  return result;
1621 }
List * lappend_oid(List *list, Oid datum)
Definition: list.c:374
#define lfirst_node(type, lc)
Definition: pg_list.h:176

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 92 of file user.c.

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

◆ createrole_self_grant

PGDLLIMPORT char* createrole_self_grant
extern

Definition at line 87 of file user.c.

◆ Password_encryption

PGDLLIMPORT int Password_encryption
extern

Definition at line 86 of file user.c.

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