38 #include "utils/fmgroids.h"
54 Oid grantorId,
bool admin_opt);
77 Datum new_record[Natts_pg_authid];
78 bool new_record_nulls[Natts_pg_authid];
85 bool createrole =
false;
87 bool canlogin =
false;
88 bool isreplication =
false;
89 bool bypassrls =
false;
94 char *validUntil = NULL;
95 Datum validUntil_datum;
103 DefElem *disreplication = NULL;
129 if (strcmp(defel->
defname,
"password") == 0)
135 else if (strcmp(defel->
defname,
"sysid") == 0)
138 (
errmsg(
"SYSID can no longer be specified")));
140 else if (strcmp(defel->
defname,
"superuser") == 0)
146 else if (strcmp(defel->
defname,
"inherit") == 0)
152 else if (strcmp(defel->
defname,
"createrole") == 0)
158 else if (strcmp(defel->
defname,
"createdb") == 0)
164 else if (strcmp(defel->
defname,
"canlogin") == 0)
170 else if (strcmp(defel->
defname,
"isreplication") == 0)
174 disreplication = defel;
176 else if (strcmp(defel->
defname,
"connectionlimit") == 0)
182 else if (strcmp(defel->
defname,
"addroleto") == 0)
188 else if (strcmp(defel->
defname,
"rolemembers") == 0)
192 drolemembers = defel;
194 else if (strcmp(defel->
defname,
"adminmembers") == 0)
198 dadminmembers = defel;
200 else if (strcmp(defel->
defname,
"validUntil") == 0)
206 else if (strcmp(defel->
defname,
"bypassrls") == 0)
213 elog(
ERROR,
"option \"%s\" not recognized",
217 if (dpassword && dpassword->
arg)
236 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
237 errmsg(
"invalid connection limit: %d", connlimit)));
240 addroleto = (
List *) daddroleto->
arg;
242 rolemembers = (
List *) drolemembers->
arg;
244 adminmembers = (
List *) dadminmembers->
arg;
255 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
256 errmsg(
"must be superuser to create superusers")));
258 else if (isreplication)
262 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
263 errmsg(
"must be superuser to create replication users")));
269 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
270 errmsg(
"must be superuser to create bypassrls users")));
276 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
277 errmsg(
"permission denied to create role")));
286 (
errcode(ERRCODE_RESERVED_NAME),
287 errmsg(
"role name \"%s\" is reserved",
289 errdetail(
"Role names starting with \"pg_\" are reserved.")));
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_\"");
310 errmsg(
"role \"%s\" already exists",
320 validUntil_null =
false;
324 validUntil_datum = (
Datum) 0;
325 validUntil_null =
true;
332 (*check_password_hook) (stmt->
role,
341 MemSet(new_record, 0,
sizeof(new_record));
342 MemSet(new_record_nulls,
false,
sizeof(new_record_nulls));
344 new_record[Anum_pg_authid_rolname - 1] =
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);
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);
358 const char *logdetail = NULL;
376 (
errmsg(
"empty string is not a valid password, clearing password")));
377 new_record_nulls[Anum_pg_authid_rolpassword - 1] =
true;
384 new_record[Anum_pg_authid_rolpassword - 1] =
389 new_record_nulls[Anum_pg_authid_rolpassword - 1] =
true;
391 new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
392 new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
394 new_record[Anum_pg_authid_rolbypassrls - 1] =
BoolGetDatum(bypassrls);
404 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
405 errmsg(
"pg_authid OID value not set when in binary upgrade mode")));
429 if (addroleto || adminmembers || rolemembers)
445 foreach(item, addroleto)
450 Oid oldroleid = oldroleform->oid;
451 char *oldrolename =
NameStr(oldroleform->rolname);
495 Datum new_record[Natts_pg_authid];
496 bool new_record_nulls[Natts_pg_authid];
497 bool new_record_repl[Natts_pg_authid];
507 char *validUntil = NULL;
508 Datum validUntil_datum;
509 bool validUntil_null;
516 DefElem *disreplication = NULL;
524 "Cannot alter reserved roles.");
531 if (strcmp(defel->
defname,
"password") == 0)
537 else if (strcmp(defel->
defname,
"superuser") == 0)
543 else if (strcmp(defel->
defname,
"inherit") == 0)
549 else if (strcmp(defel->
defname,
"createrole") == 0)
555 else if (strcmp(defel->
defname,
"createdb") == 0)
561 else if (strcmp(defel->
defname,
"canlogin") == 0)
567 else if (strcmp(defel->
defname,
"isreplication") == 0)
571 disreplication = defel;
573 else if (strcmp(defel->
defname,
"connectionlimit") == 0)
579 else if (strcmp(defel->
defname,
"rolemembers") == 0 &&
584 drolemembers = defel;
586 else if (strcmp(defel->
defname,
"validUntil") == 0)
592 else if (strcmp(defel->
defname,
"bypassrls") == 0)
599 elog(
ERROR,
"option \"%s\" not recognized",
603 if (dpassword && dpassword->
arg)
610 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
611 errmsg(
"invalid connection limit: %d", connlimit)));
625 roleid = authform->oid;
633 if (authform->rolsuper || dissuper)
637 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
638 errmsg(
"must be superuser to alter superuser roles or change superuser attribute")));
640 else if (authform->rolreplication || disreplication)
644 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
645 errmsg(
"must be superuser to alter replication roles or change replication attribute")));
651 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
652 errmsg(
"must be superuser to change bypassrls attribute")));
657 if (dinherit || dcreaterole || dcreatedb || dcanlogin || dconnlimit ||
658 drolemembers || dvalidUntil || !dpassword || roleid !=
GetUserId())
660 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
661 errmsg(
"permission denied")));
671 validUntil_null =
false;
677 Anum_pg_authid_rolvaliduntil,
685 (*check_password_hook) (rolename,
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));
704 new_record_repl[Anum_pg_authid_rolsuper - 1] =
true;
710 new_record_repl[Anum_pg_authid_rolinherit - 1] =
true;
716 new_record_repl[Anum_pg_authid_rolcreaterole - 1] =
true;
722 new_record_repl[Anum_pg_authid_rolcreatedb - 1] =
true;
728 new_record_repl[Anum_pg_authid_rolcanlogin - 1] =
true;
734 new_record_repl[Anum_pg_authid_rolreplication - 1] =
true;
739 new_record[Anum_pg_authid_rolconnlimit - 1] =
Int32GetDatum(connlimit);
740 new_record_repl[Anum_pg_authid_rolconnlimit - 1] =
true;
747 const char *logdetail = NULL;
754 (
errmsg(
"empty string is not a valid password, clearing password")));
755 new_record_nulls[Anum_pg_authid_rolpassword - 1] =
true;
762 new_record[Anum_pg_authid_rolpassword - 1] =
765 new_record_repl[Anum_pg_authid_rolpassword - 1] =
true;
769 if (dpassword && dpassword->
arg == NULL)
771 new_record_repl[Anum_pg_authid_rolpassword - 1] =
true;
772 new_record_nulls[Anum_pg_authid_rolpassword - 1] =
true;
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;
783 new_record_repl[Anum_pg_authid_rolbypassrls - 1] =
true;
787 new_record_nulls, new_record_repl);
809 else if (stmt->
action == -1)
838 "Cannot alter reserved roles.");
842 roleid = roleform->oid;
854 if (roleform->rolsuper)
858 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
859 errmsg(
"must be superuser to alter superusers")));
865 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
866 errmsg(
"permission denied")));
895 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
896 errmsg(
"must be superuser to alter settings globally")));
917 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
918 errmsg(
"permission denied to drop role")));
927 foreach(item, stmt->
roles)
942 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
943 errmsg(
"cannot use special role specifier in DROP ROLE")));
952 (
errcode(ERRCODE_UNDEFINED_OBJECT),
953 errmsg(
"role \"%s\" does not exist", role)));
958 (
errmsg(
"role \"%s\" does not exist, skipping",
966 roleid = roleform->oid;
970 (
errcode(ERRCODE_OBJECT_IN_USE),
971 errmsg(
"current user cannot be dropped")));
974 (
errcode(ERRCODE_OBJECT_IN_USE),
975 errmsg(
"current user cannot be dropped")));
978 (
errcode(ERRCODE_OBJECT_IN_USE),
979 errmsg(
"session user cannot be dropped")));
988 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
989 errmsg(
"must be superuser to drop superusers")));
1002 &detail, &detail_log))
1004 (
errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
1005 errmsg(
"role \"%s\" cannot be dropped because some objects depend on it",
1024 Anum_pg_auth_members_roleid,
1029 true, NULL, 1, &scankey);
1039 Anum_pg_auth_members_member,
1044 true, NULL, 1, &scankey);
1095 Datum repl_val[Natts_pg_authid];
1096 bool repl_null[Natts_pg_authid];
1097 bool repl_repl[Natts_pg_authid];
1109 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1110 errmsg(
"role \"%s\" does not exist", oldname)));
1121 roleid = authform->oid;
1125 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1126 errmsg(
"session user cannot be renamed")));
1129 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1130 errmsg(
"current user cannot be renamed")));
1138 (
errcode(ERRCODE_RESERVED_NAME),
1139 errmsg(
"role name \"%s\" is reserved",
1141 errdetail(
"Role names starting with \"pg_\" are reserved.")));
1145 (
errcode(ERRCODE_RESERVED_NAME),
1146 errmsg(
"role name \"%s\" is reserved",
1148 errdetail(
"Role names starting with \"pg_\" are reserved.")));
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_\"");
1163 errmsg(
"role \"%s\" already exists", newname)));
1172 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1173 errmsg(
"must be superuser to rename superusers")));
1179 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1180 errmsg(
"permission denied to rename role")));
1184 for (
i = 0;
i < Natts_pg_authid;
i++)
1185 repl_repl[
i] =
false;
1187 repl_repl[Anum_pg_authid_rolname - 1] =
true;
1190 repl_null[Anum_pg_authid_rolname - 1] =
false;
1192 datum =
heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull);
1197 repl_repl[Anum_pg_authid_rolpassword - 1] =
true;
1198 repl_null[Anum_pg_authid_rolpassword - 1] =
true;
1201 (
errmsg(
"MD5 password cleared because of role rename")));
1258 if (rolename == NULL || priv->
cols !=
NIL)
1260 (
errcode(ERRCODE_INVALID_GRANT_OPERATION),
1261 errmsg(
"column names cannot be included in GRANT/REVOKE ROLE")));
1292 foreach(cell, role_ids)
1298 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1299 errmsg(
"permission denied to drop objects")));
1319 foreach(cell, role_ids)
1325 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1326 errmsg(
"permission denied to reassign objects")));
1334 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1335 errmsg(
"permission denied to reassign objects")));
1354 foreach(l, memberNames)
1377 List *memberSpecs,
List *memberIds,
1378 Oid grantorId,
bool admin_opt)
1399 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1400 errmsg(
"must be superuser to alter superusers")));
1407 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1408 errmsg(
"must have admin option on role \"%s\"",
1420 if (roleid == ROLE_PG_DATABASE_OWNER)
1422 errmsg(
"role \"%s\" cannot have explicit members", rolename));
1431 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1432 errmsg(
"must be superuser to set grantor")));
1437 forboth(specitem, memberSpecs, iditem, memberIds)
1443 Datum new_record[Natts_pg_auth_members];
1444 bool new_record_nulls[Natts_pg_auth_members];
1445 bool new_record_repl[Natts_pg_auth_members];
1466 if (memberid == ROLE_PG_DATABASE_OWNER)
1468 errmsg(
"role \"%s\" cannot be a member of any role",
1480 (
errcode(ERRCODE_INVALID_GRANT_OPERATION),
1481 errmsg(
"role \"%s\" is a member of role \"%s\"",
1496 (
errmsg(
"role \"%s\" is already a member of role \"%s\"",
1503 MemSet(new_record, 0,
sizeof(new_record));
1504 MemSet(new_record_nulls,
false,
sizeof(new_record_nulls));
1505 MemSet(new_record_repl,
false,
sizeof(new_record_repl));
1509 new_record[Anum_pg_auth_members_grantor - 1] =
ObjectIdGetDatum(grantorId);
1510 new_record[Anum_pg_auth_members_admin_option - 1] =
BoolGetDatum(admin_opt);
1514 new_record_repl[Anum_pg_auth_members_grantor - 1] =
true;
1515 new_record_repl[Anum_pg_auth_members_admin_option - 1] =
true;
1518 new_record_nulls, new_record_repl);
1525 new_record, new_record_nulls);
1550 List *memberSpecs,
List *memberIds,
1572 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1573 errmsg(
"must be superuser to alter superusers")));
1580 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1581 errmsg(
"must have admin option on role \"%s\"",
1588 forboth(specitem, memberSpecs, iditem, memberIds)
1603 (
errmsg(
"role \"%s\" is not a member of role \"%s\"",
1617 Datum new_record[Natts_pg_auth_members];
1618 bool new_record_nulls[Natts_pg_auth_members];
1619 bool new_record_repl[Natts_pg_auth_members];
1622 MemSet(new_record, 0,
sizeof(new_record));
1623 MemSet(new_record_nulls,
false,
sizeof(new_record_nulls));
1624 MemSet(new_record_repl,
false,
sizeof(new_record_repl));
1626 new_record[Anum_pg_auth_members_admin_option - 1] =
BoolGetDatum(
false);
1627 new_record_repl[Anum_pg_auth_members_admin_option - 1] =
true;
1631 new_record_nulls, new_record_repl);
bool is_admin_of_role(Oid member, Oid role)
char * get_rolespec_name(const RoleSpec *role)
bool is_member_of_role_nosuper(Oid member, Oid role)
bool has_privs_of_role(Oid member, Oid role)
Oid get_role_oid(const char *rolname, bool missing_ok)
void check_rolespec_name(const RoleSpec *role, const char *detail_msg)
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
HeapTuple get_rolespec_tuple(const RoleSpec *role)
bool pg_database_ownercheck(Oid db_oid, Oid roleid)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
bool has_createrole_privilege(Oid roleid)
Datum timestamptz_in(PG_FUNCTION_ARGS)
#define CStringGetTextDatum(s)
#define TextDatumGetCString(d)
#define MemSet(start, val, len)
#define OidIsValid(objectId)
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
bool IsReservedName(const char *name)
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char **logdetail)
PasswordType get_password_type(const char *shadow_pass)
char * encrypt_password(PasswordType target_type, const char *role, const char *password)
@ PASSWORD_TYPE_SCRAM_SHA_256
Oid get_database_oid(const char *dbname, bool missing_ok)
Oid createdb(ParseState *pstate, const CreatedbStmt *stmt)
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
int errdetail_internal(const char *fmt,...)
int errdetail(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
int errdetail_log(const char *fmt,...)
#define ereport(elevel,...)
#define DirectFunctionCall1(func, arg1)
#define DirectFunctionCall3(func, arg1, arg2, arg3)
void systable_endscan(SysScanDesc sysscan)
HeapTuple systable_getnext(SysScanDesc sysscan)
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
void heap_freetuple(HeapTuple htup)
#define HeapTupleIsValid(tuple)
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend_oid(List *list, Oid datum)
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
#define AccessExclusiveLock
char * pstrdup(const char *in)
Oid GetSessionUserId(void)
Datum namein(PG_FUNCTION_ARGS)
#define InvokeObjectPostCreateHook(classId, objectId, subId)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
#define InvokeObjectDropHook(classId, objectId, subId)
#define ObjectAddressSet(addr, class_id, object_id)
FormData_pg_auth_members * Form_pg_auth_members
FormData_pg_authid * Form_pg_authid
void DropSetting(Oid databaseid, Oid roleid)
void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
#define lfirst_node(type, lc)
static int list_length(const List *l)
#define forboth(cell1, list1, cell2, list2)
#define list_make1_oid(x1)
bool checkSharedDependencies(Oid classId, Oid objectId, char **detail_msg, char **detail_log_msg)
void shdepDropOwned(List *roleids, DropBehavior behavior)
void shdepLockAndCheckObject(Oid classId, Oid objectId)
void shdepReassignOwned(List *roleids, Oid newrole)
#define CStringGetDatum(X)
#define ObjectIdGetDatum(X)
#define PointerGetDatum(X)
#define RelationGetDescr(relation)
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
void DeleteSharedSecurityLabel(Oid objectId, Oid classId)
#define BTEqualStrategyNumber
#define ERRCODE_DUPLICATE_OBJECT
VariableSetStmt * setstmt
bool superuser_arg(Oid roleid)
void ReleaseSysCache(HeapTuple tuple)
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
HeapTuple SearchSysCache2(int cacheId, Datum key1, Datum key2)
#define SearchSysCacheExists1(cacheId, key1)
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
static bool have_createrole_privilege(void)
ObjectAddress RenameRole(const char *oldname, const char *newname)
void ReassignOwnedObjects(ReassignOwnedStmt *stmt)
Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
static void DelRoleMems(const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, bool admin_opt)
Oid AlterRoleSet(AlterRoleSetStmt *stmt)
Oid binary_upgrade_next_pg_authid_oid
void DropRole(DropRoleStmt *stmt)
Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
static void AddRoleMems(const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, Oid grantorId, bool admin_opt)
List * roleSpecsToIds(List *memberNames)
check_password_hook_type check_password_hook
void GrantRole(GrantRoleStmt *stmt)
void DropOwnedObjects(DropOwnedStmt *stmt)
void(* check_password_hook_type)(const char *username, const char *shadow_pass, PasswordType password_type, Datum validuntil_time, bool validuntil_null)
void CommandCounterIncrement(void)