PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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 charcreaterole_self_grant
 
PGDLLIMPORT check_password_hook_type check_password_hook
 

Typedef Documentation

◆ check_password_hook_type

Definition at line 25 of file user.h.

Function Documentation

◆ AlterRole()

Oid AlterRole ( ParseState pstate,
AlterRoleStmt stmt 
)
extern

Definition at line 620 of file user.c.

621{
627 HeapTuple tuple,
628 new_tuple;
631 char *rolename;
632 char *password = NULL; /* user password */
633 int connlimit = -1; /* maximum connections allowed */
634 char *validUntil = NULL; /* time the login is valid until */
635 Datum validUntil_datum; /* same, as timestamptz Datum */
636 bool validUntil_null;
648 Oid roleid;
650 GrantRoleOptions popt;
651
653 _("Cannot alter reserved roles."));
654
655 /* Extract options from the statement node tree */
656 foreach(option, stmt->options)
657 {
659
660 if (strcmp(defel->defname, "password") == 0)
661 {
662 if (dpassword)
665 }
666 else if (strcmp(defel->defname, "superuser") == 0)
667 {
668 if (dissuper)
670 dissuper = defel;
671 }
672 else if (strcmp(defel->defname, "inherit") == 0)
673 {
674 if (dinherit)
676 dinherit = defel;
677 }
678 else if (strcmp(defel->defname, "createrole") == 0)
679 {
680 if (dcreaterole)
683 }
684 else if (strcmp(defel->defname, "createdb") == 0)
685 {
686 if (dcreatedb)
689 }
690 else if (strcmp(defel->defname, "canlogin") == 0)
691 {
692 if (dcanlogin)
695 }
696 else if (strcmp(defel->defname, "isreplication") == 0)
697 {
698 if (disreplication)
701 }
702 else if (strcmp(defel->defname, "connectionlimit") == 0)
703 {
704 if (dconnlimit)
707 }
708 else if (strcmp(defel->defname, "rolemembers") == 0 &&
709 stmt->action != 0)
710 {
711 if (drolemembers)
714 }
715 else if (strcmp(defel->defname, "validUntil") == 0)
716 {
717 if (dvalidUntil)
720 }
721 else if (strcmp(defel->defname, "bypassrls") == 0)
722 {
723 if (dbypassRLS)
726 }
727 else
728 elog(ERROR, "option \"%s\" not recognized",
729 defel->defname);
730 }
731
732 if (dpassword && dpassword->arg)
733 password = strVal(dpassword->arg);
734 if (dconnlimit)
735 {
737 if (connlimit < -1)
740 errmsg("invalid connection limit: %d", connlimit)));
741 }
742 if (dvalidUntil)
744
745 /*
746 * Scan the pg_authid relation to be certain the user exists.
747 */
750
751 tuple = get_rolespec_tuple(stmt->role);
753 rolename = pstrdup(NameStr(authform->rolname));
754 roleid = authform->oid;
755
756 /* To mess with a superuser in any way you gotta be superuser. */
757 if (!superuser() && authform->rolsuper)
760 errmsg("permission denied to alter role"),
761 errdetail("Only roles with the %s attribute may alter roles with the %s attribute.",
762 "SUPERUSER", "SUPERUSER")));
763 if (!superuser() && dissuper)
766 errmsg("permission denied to alter role"),
767 errdetail("Only roles with the %s attribute may change the %s attribute.",
768 "SUPERUSER", "SUPERUSER")));
769
770 /*
771 * Most changes to a role require that you both have CREATEROLE privileges
772 * and also ADMIN OPTION on the role.
773 */
775 !is_admin_of_role(GetUserId(), roleid))
776 {
777 /* things an unprivileged user certainly can't do */
782 errmsg("permission denied to alter role"),
783 errdetail("Only roles with the %s attribute and the %s option on role \"%s\" may alter this role.",
784 "CREATEROLE", "ADMIN", rolename)));
785
786 /* an unprivileged user can change their own password */
787 if (dpassword && roleid != currentUserId)
790 errmsg("permission denied to alter role"),
791 errdetail("To change another role's password, the current user must have the %s attribute and the %s option on the role.",
792 "CREATEROLE", "ADMIN")));
793 }
794 else if (!superuser())
795 {
796 /*
797 * Even if you have both CREATEROLE and ADMIN OPTION on a role, you
798 * can only change the CREATEDB, REPLICATION, or BYPASSRLS attributes
799 * if they are set for your own role (or you are the superuser).
800 */
804 errmsg("permission denied to alter role"),
805 errdetail("Only roles with the %s attribute may change the %s attribute.",
806 "CREATEDB", "CREATEDB")));
810 errmsg("permission denied to alter role"),
811 errdetail("Only roles with the %s attribute may change the %s attribute.",
812 "REPLICATION", "REPLICATION")));
816 errmsg("permission denied to alter role"),
817 errdetail("Only roles with the %s attribute may change the %s attribute.",
818 "BYPASSRLS", "BYPASSRLS")));
819 }
820
821 /* To add or drop members, you need ADMIN OPTION. */
825 errmsg("permission denied to alter role"),
826 errdetail("Only roles with the %s option on role \"%s\" may add or drop members.",
827 "ADMIN", rolename)));
828
829 /* Convert validuntil to internal form */
830 if (dvalidUntil)
831 {
835 Int32GetDatum(-1));
836 validUntil_null = false;
837 }
838 else
839 {
840 /* fetch existing setting in case hook needs it */
844 }
845
846 /*
847 * Call the password checking hook if there is one defined
848 */
850 (*check_password_hook) (rolename,
851 password,
855
856 /*
857 * Build an updated tuple, perusing the information just obtained
858 */
859
860 /*
861 * issuper/createrole/etc
862 */
863 if (dissuper)
864 {
865 bool should_be_super = boolVal(dissuper->arg);
866
867 if (!should_be_super && roleid == BOOTSTRAP_SUPERUSERID)
870 errmsg("permission denied to alter role"),
871 errdetail("The bootstrap superuser must have the %s attribute.",
872 "SUPERUSER")));
873
876 }
877
878 if (dinherit)
879 {
882 }
883
884 if (dcreaterole)
885 {
888 }
889
890 if (dcreatedb)
891 {
894 }
895
896 if (dcanlogin)
897 {
900 }
901
902 if (disreplication)
903 {
906 }
907
908 if (dconnlimit)
909 {
912 }
913
914 /* password */
915 if (password)
916 {
917 char *shadow_pass;
918 const char *logdetail = NULL;
919
920 /* Like in CREATE USER, don't allow an empty password. */
921 if (password[0] == '\0' ||
922 plain_crypt_verify(rolename, password, "", &logdetail) == STATUS_OK)
923 {
925 (errmsg("empty string is not a valid password, clearing password")));
927 }
928 else
929 {
930 /* Encrypt the password to the requested format. */
932 password);
935 }
937 }
938
939 /* unset password */
940 if (dpassword && dpassword->arg == NULL)
941 {
944 }
945
946 /* valid until */
950
951 if (dbypassRLS)
952 {
955 }
956
960
962
963 ReleaseSysCache(tuple);
965
967
968 /*
969 * Advance command counter so we can see new record; else tests in
970 * AddRoleMems may fail.
971 */
972 if (drolemembers)
973 {
974 List *rolemembers = (List *) drolemembers->arg;
975
977
978 if (stmt->action == +1) /* add members to role */
979 AddRoleMems(currentUserId, rolename, roleid,
981 InvalidOid, &popt);
982 else if (stmt->action == -1) /* drop members from role */
983 DelRoleMems(currentUserId, rolename, roleid,
985 InvalidOid, &popt, DROP_RESTRICT);
986 }
987
988 /*
989 * Close pg_authid, but keep lock till commit.
990 */
992
993 return roleid;
994}
bool is_admin_of_role(Oid member, Oid role)
Definition acl.c:5414
void check_rolespec_name(const RoleSpec *role, const char *detail_msg)
Definition acl.c:5693
HeapTuple get_rolespec_tuple(const RoleSpec *role)
Definition acl.c:5625
bool has_bypassrls_privilege(Oid roleid)
Definition aclchk.c:4188
Datum timestamptz_in(PG_FUNCTION_ARGS)
Definition timestamp.c:418
#define CStringGetTextDatum(s)
Definition builtins.h:97
#define NameStr(name)
Definition c.h:765
#define STATUS_OK
Definition c.h:1158
int plain_crypt_verify(const char *role, const char *shadow_pass, const char *client_pass, const char **logdetail)
Definition crypt.c:256
PasswordType get_password_type(const char *shadow_pass)
Definition crypt.c:90
char * encrypt_password(PasswordType target_type, const char *role, const char *password)
Definition crypt.c:117
bool have_createdb_privilege(void)
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition define.c:370
int errdetail(const char *fmt,...)
Definition elog.c:1216
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define _(x)
Definition elog.c:91
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:226
#define NOTICE
Definition elog.h:35
#define ereport(elevel,...)
Definition elog.h:150
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition fmgr.h:688
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1210
void heap_freetuple(HeapTuple htup)
Definition heaptuple.c:1435
static void * GETSTRUCT(const HeapTupleData *tuple)
#define stmt
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition indexing.c:313
#define NoLock
Definition lockdefs.h:34
#define RowExclusiveLock
Definition lockdefs.h:38
char * pstrdup(const char *in)
Definition mcxt.c:1781
Oid GetUserId(void)
Definition miscinit.c:469
bool has_rolreplication(Oid roleid)
Definition miscinit.c:688
#define InvokeObjectPostAlterHook(classId, objectId, subId)
@ DROP_RESTRICT
FormData_pg_authid * Form_pg_authid
Definition pg_authid.h:56
#define lfirst(lc)
Definition pg_list.h:172
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
uint64_t Datum
Definition postgres.h:70
static Datum CStringGetDatum(const char *X)
Definition postgres.h:380
static Datum Int32GetDatum(int32 X)
Definition postgres.h:222
#define InvalidOid
unsigned int Oid
static int fb(int x)
#define RelationGetDescr(relation)
Definition rel.h:540
static char * password
Definition streamutil.c:51
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:264
Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)
Definition syscache.c:595
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:2506
static void AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid, List *memberSpecs, List *memberIds, Oid grantorId, GrantRoleOptions *popt)
Definition user.c:1682
int Password_encryption
Definition user.c:86
List * roleSpecsToIds(List *memberNames)
Definition user.c:1653
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:1980
#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:1101

References _, AddRoleMems(), BoolGetDatum(), boolVal, CatalogTupleUpdate(), check_password_hook, check_rolespec_name(), CommandCounterIncrement(), CStringGetDatum(), CStringGetTextDatum, DelRoleMems(), DirectFunctionCall3, DROP_RESTRICT, elog, encrypt_password(), ereport, errcode(), errdetail(), errmsg(), ERROR, errorConflictingDefElem(), fb(), 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(), password, Password_encryption, plain_crypt_verify(), pstrdup(), RelationGetDescr, ReleaseSysCache(), roleSpecsToIds(), RowExclusiveLock, STATUS_OK, stmt, strVal, superuser(), SysCacheGetAttr(), HeapTupleData::t_self, table_close(), table_open(), and timestamptz_in().

Referenced by standard_ProcessUtility().

◆ AlterRoleSet()

Oid AlterRoleSet ( AlterRoleSetStmt stmt)
extern

Definition at line 1001 of file user.c.

1002{
1006 Oid roleid = InvalidOid;
1007
1008 if (stmt->role)
1009 {
1011 _("Cannot alter reserved roles."));
1012
1015 roleid = roleform->oid;
1016
1017 /*
1018 * Obtain a lock on the role and make sure it didn't go away in the
1019 * meantime.
1020 */
1022
1023 /*
1024 * To mess with a superuser you gotta be superuser; otherwise you need
1025 * CREATEROLE plus admin option on the target role; unless you're just
1026 * trying to change your own settings
1027 */
1028 if (roleform->rolsuper)
1029 {
1030 if (!superuser())
1031 ereport(ERROR,
1033 errmsg("permission denied to alter role"),
1034 errdetail("Only roles with the %s attribute may alter roles with the %s attribute.",
1035 "SUPERUSER", "SUPERUSER")));
1036 }
1037 else
1038 {
1039 if ((!have_createrole_privilege() ||
1040 !is_admin_of_role(GetUserId(), roleid))
1041 && roleid != GetUserId())
1042 ereport(ERROR,
1044 errmsg("permission denied to alter role"),
1045 errdetail("Only roles with the %s attribute and the %s option on role \"%s\" may alter this role.",
1046 "CREATEROLE", "ADMIN", NameStr(roleform->rolname))));
1047 }
1048
1050 }
1051
1052 /* look up and lock the database, if specified */
1053 if (stmt->database != NULL)
1054 {
1055 databaseid = get_database_oid(stmt->database, false);
1057
1058 if (!stmt->role)
1059 {
1060 /*
1061 * If no role is specified, then this is effectively the same as
1062 * ALTER DATABASE ... SET, so use the same permission check.
1063 */
1066 stmt->database);
1067 }
1068 }
1069
1070 if (!stmt->role && !stmt->database)
1071 {
1072 /* Must be superuser to alter settings globally. */
1073 if (!superuser())
1074 ereport(ERROR,
1076 errmsg("permission denied to alter setting"),
1077 errdetail("Only roles with the %s attribute may alter settings globally.",
1078 "SUPERUSER")));
1079 }
1080
1081 AlterSetting(databaseid, roleid, stmt->setstmt);
1082
1083 return roleid;
1084}
@ ACLCHECK_NOT_OWNER
Definition acl.h:185
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
Definition aclchk.c:2654
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Definition aclchk.c:4090
Oid get_database_oid(const char *dbname, bool missing_ok)
@ OBJECT_DATABASE
void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
void shdepLockAndCheckObject(Oid classId, Oid objectId)

References _, aclcheck_error(), ACLCHECK_NOT_OWNER, AlterSetting(), check_rolespec_name(), ereport, errcode(), errdetail(), errmsg(), ERROR, fb(), get_database_oid(), get_rolespec_tuple(), GETSTRUCT(), GetUserId(), have_createrole_privilege(), InvalidOid, is_admin_of_role(), NameStr, OBJECT_DATABASE, object_ownercheck(), ReleaseSysCache(), shdepLockAndCheckObject(), stmt, and superuser().

Referenced by standard_ProcessUtility().

◆ assign_createrole_self_grant()

void assign_createrole_self_grant ( const char newval,
void extra 
)
extern

◆ check_createrole_self_grant()

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

Definition at line 2518 of file user.c.

2519{
2520 char *rawstring;
2521 List *elemlist;
2522 ListCell *l;
2523 unsigned options = 0;
2524 unsigned *result;
2525
2526 /* Need a modifiable copy of string */
2528
2530 {
2531 /* syntax error in list */
2532 GUC_check_errdetail("List syntax is invalid.");
2535 return false;
2536 }
2537
2538 foreach(l, elemlist)
2539 {
2540 char *tok = (char *) lfirst(l);
2541
2542 if (pg_strcasecmp(tok, "SET") == 0)
2544 else if (pg_strcasecmp(tok, "INHERIT") == 0)
2546 else
2547 {
2548 GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
2551 return false;
2552 }
2553 }
2554
2557
2558 result = (unsigned *) guc_malloc(LOG, sizeof(unsigned));
2559 if (!result)
2560 return false;
2561 *result = options;
2562 *extra = result;
2563
2564 return true;
2565}
#define LOG
Definition elog.h:31
void * guc_malloc(int elevel, size_t size)
Definition guc.c:636
#define newval
#define GUC_check_errdetail
Definition guc.h:505
void list_free(List *list)
Definition list.c:1546
void pfree(void *pointer)
Definition mcxt.c:1616
int pg_strcasecmp(const char *s1, const char *s2)
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition varlena.c:2730

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

◆ CreateRole()

Oid CreateRole ( ParseState pstate,
CreateRoleStmt stmt 
)
extern

Definition at line 133 of file user.c.

134{
137 HeapTuple tuple;
141 Oid roleid;
142 ListCell *item;
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;
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 {
191
192 if (strcmp(defel->defname, "password") == 0)
193 {
194 if (dpassword)
197 }
198 else if (strcmp(defel->defname, "sysid") == 0)
199 {
201 (errmsg("SYSID can no longer be specified")));
202 }
203 else if (strcmp(defel->defname, "superuser") == 0)
204 {
205 if (dissuper)
207 dissuper = defel;
208 }
209 else if (strcmp(defel->defname, "inherit") == 0)
210 {
211 if (dinherit)
213 dinherit = defel;
214 }
215 else if (strcmp(defel->defname, "createrole") == 0)
216 {
217 if (dcreaterole)
220 }
221 else if (strcmp(defel->defname, "createdb") == 0)
222 {
223 if (dcreatedb)
226 }
227 else if (strcmp(defel->defname, "canlogin") == 0)
228 {
229 if (dcanlogin)
232 }
233 else if (strcmp(defel->defname, "isreplication") == 0)
234 {
235 if (disreplication)
238 }
239 else if (strcmp(defel->defname, "connectionlimit") == 0)
240 {
241 if (dconnlimit)
244 }
245 else if (strcmp(defel->defname, "addroleto") == 0)
246 {
247 if (daddroleto)
250 }
251 else if (strcmp(defel->defname, "rolemembers") == 0)
252 {
253 if (drolemembers)
256 }
257 else if (strcmp(defel->defname, "adminmembers") == 0)
258 {
259 if (dadminmembers)
262 }
263 else if (strcmp(defel->defname, "validUntil") == 0)
264 {
265 if (dvalidUntil)
268 }
269 else if (strcmp(defel->defname, "bypassrls") == 0)
270 {
271 if (dbypassRLS)
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)
288 if (dcreatedb)
289 createdb = boolVal(dcreatedb->arg);
290 if (dcanlogin)
291 canlogin = boolVal(dcanlogin->arg);
292 if (disreplication)
294 if (dconnlimit)
295 {
297 if (connlimit < -1)
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)
308 if (dvalidUntil)
310 if (dbypassRLS)
312
313 /* Check some permissions first */
315 {
319 errmsg("permission denied to create role"),
320 errdetail("Only roles with the %s attribute may create roles.",
321 "CREATEROLE")));
322 if (issuper)
325 errmsg("permission denied to create role"),
326 errdetail("Only roles with the %s attribute may create roles with the %s attribute.",
327 "SUPERUSER", "SUPERUSER")));
331 errmsg("permission denied to create role"),
332 errdetail("Only roles with the %s attribute may create roles with the %s attribute.",
333 "CREATEDB", "CREATEDB")));
337 errmsg("permission denied to create role"),
338 errdetail("Only roles with the %s attribute may create roles with the %s attribute.",
339 "REPLICATION", "REPLICATION")));
343 errmsg("permission denied to create role"),
344 errdetail("Only roles with the %s attribute may create roles with the %s attribute.",
345 "BYPASSRLS", "BYPASSRLS")));
346 }
347
348 /*
349 * Check that the user is not trying to create a role in the reserved
350 * "pg_" namespace.
351 */
352 if (IsReservedName(stmt->role))
355 errmsg("role name \"%s\" is reserved",
356 stmt->role),
357 errdetail("Role names starting with \"pg_\" are reserved.")));
358
359 /*
360 * If built with appropriate switch, whine when regression-testing
361 * conventions for role names are violated.
362 */
363#ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
364 if (strncmp(stmt->role, "regress_", 8) != 0)
365 elog(WARNING, "roles created by regression test cases should have names starting with \"regress_\"");
366#endif
367
368 /*
369 * Check the pg_authid relation to be certain the role doesn't already
370 * exist.
371 */
374
375 if (OidIsValid(get_role_oid(stmt->role, true)))
378 errmsg("role \"%s\" already exists",
379 stmt->role)));
380
381 /* Convert validuntil to internal form */
382 if (validUntil)
383 {
387 Int32GetDatum(-1));
388 validUntil_null = false;
389 }
390 else
391 {
393 validUntil_null = true;
394 }
395
396 /*
397 * Call the password checking hook if there is one defined
398 */
400 (*check_password_hook) (stmt->role,
401 password,
405
406 /*
407 * Build a tuple to insert
408 */
418
419 if (password)
420 {
421 char *shadow_pass;
422 const char *logdetail = NULL;
423
424 /*
425 * Don't allow an empty password. Libpq treats an empty password the
426 * same as no password at all, and won't even try to authenticate. But
427 * other clients might, so allowing it would be confusing. By clearing
428 * the password when an empty string is specified, the account is
429 * consistently locked for all clients.
430 *
431 * Note that this only covers passwords stored in the database itself.
432 * There are also checks in the authentication code, to forbid an
433 * empty password from being used with authentication methods that
434 * fetch the password from an external system, like LDAP or PAM.
435 */
436 if (password[0] == '\0' ||
437 plain_crypt_verify(stmt->role, password, "", &logdetail) == STATUS_OK)
438 {
440 (errmsg("empty string is not a valid password, clearing password")));
442 }
443 else
444 {
445 /* Encrypt the password to the requested format. */
447 password);
450 }
451 }
452 else
454
457
459
460 /*
461 * pg_largeobject_metadata contains pg_authid.oid's, so we use the
462 * binary-upgrade override.
463 */
464 if (IsBinaryUpgrade)
465 {
469 errmsg("pg_authid OID value not set when in binary upgrade mode")));
470
473 }
474 else
475 {
478 }
479
481
483
484 /*
485 * Insert new record in the pg_authid table
486 */
488
489 /*
490 * Advance command counter so we can see new record; else tests in
491 * AddRoleMems may fail.
492 */
495
496 /* Default grant. */
498
499 /*
500 * Add the new role to the specified existing roles.
501 */
502 if (addroleto)
503 {
507
508 thisrole->roletype = ROLESPEC_CSTRING;
509 thisrole->rolename = stmt->role;
510 thisrole->location = -1;
511
512 foreach(item, addroleto)
513 {
514 RoleSpec *oldrole = lfirst(item);
518 char *oldrolename = NameStr(oldroleform->rolname);
519
520 /* can only add this role to roles for which you have rights */
525 InvalidOid, &popt);
526
528 }
529 }
530
531 /*
532 * If the current user isn't a superuser, make them an admin of the new
533 * role so that they can administer the new object they just created.
534 * Superusers will be able to do that anyway.
535 *
536 * The grantor of record for this implicit grant is the bootstrap
537 * superuser, which means that the CREATEROLE user cannot revoke the
538 * grant. They can however grant the created role back to themselves with
539 * different options, since they enjoy ADMIN OPTION on it.
540 */
541 if (!superuser())
542 {
547
549 current_role->location = -1;
551
555 poptself.admin = true;
556 poptself.inherit = false;
557 poptself.set = false;
558
562
563 /*
564 * We must make the implicit grant visible to the code below, else the
565 * additional grants will fail.
566 */
568
569 /*
570 * Because of the implicit grant above, a CREATEROLE user who creates
571 * a role has the ability to grant that role back to themselves with
572 * the INHERIT or SET options, if they wish to inherit the role's
573 * privileges or be able to SET ROLE to it. The createrole_self_grant
574 * GUC can be used to make this happen automatically. This has no
575 * security implications since the same user is able to make the same
576 * grant using an explicit GRANT statement; it's just convenient.
577 */
579 AddRoleMems(currentUserId, stmt->role, roleid,
582 }
583
584 /*
585 * Add the specified members to this new role. adminmembers get the admin
586 * option, rolemembers don't.
587 *
588 * NB: No permissions check is required here. If you have enough rights to
589 * create a role, you can add any members you like.
590 */
591 AddRoleMems(currentUserId, stmt->role, roleid,
593 InvalidOid, &popt);
595 popt.admin = true;
596 AddRoleMems(currentUserId, stmt->role, roleid,
598 InvalidOid, &popt);
599
600 /* Post creation hook for new role */
602
603 /*
604 * Close pg_authid, but keep lock till commit.
605 */
607
608 return roleid;
609}
Oid get_role_oid(const char *rolname, bool missing_ok)
Definition acl.c:5552
bool has_createrole_privilege(Oid roleid)
Definition aclchk.c:4169
#define OidIsValid(objectId)
Definition c.h:788
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
Definition catalog.c:448
bool IsReservedName(const char *name)
Definition catalog.c:278
Oid createdb(ParseState *pstate, const CreatedbStmt *stmt)
Definition dbcommands.c:685
#define WARNING
Definition elog.h:36
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:684
bool IsBinaryUpgrade
Definition globals.c:121
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1117
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition indexing.c:233
Datum namein(PG_FUNCTION_ARGS)
Definition name.c:48
#define makeNode(_type_)
Definition nodes.h:161
#define InvokeObjectPostCreateHook(classId, objectId, subId)
@ ROLESPEC_CSTRING
Definition parsenodes.h:419
@ ROLESPEC_CURRENT_ROLE
Definition parsenodes.h:420
@ ROLESTMT_ROLE
@ ROLESTMT_USER
@ ROLESTMT_GROUP
#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:30
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:2112
Oid binary_upgrade_next_pg_authid_oid
Definition user.c:71

References AddRoleMems(), GrantRoleOptions::admin, 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, DirectFunctionCall1, DirectFunctionCall3, elog, encrypt_password(), ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errdetail(), errmsg(), ERROR, errorConflictingDefElem(), fb(), 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(), InitGrantRoleOptions(), Int32GetDatum(), intVal, InvalidOid, InvokeObjectPostCreateHook, IsBinaryUpgrade, IsReservedName(), lfirst, list_make1, list_make1_oid, makeNode, namein(), NameStr, NIL, NoLock, NOTICE, ObjectIdGetDatum(), OidIsValid, password, Password_encryption, plain_crypt_verify(), RelationGetDescr, ReleaseSysCache(), ROLESPEC_CSTRING, ROLESPEC_CURRENT_ROLE, roleSpecsToIds(), ROLESTMT_GROUP, ROLESTMT_ROLE, ROLESTMT_USER, RowExclusiveLock, GrantRoleOptions::specified, STATUS_OK, stmt, strVal, superuser(), superuser_arg(), table_close(), table_open(), timestamptz_in(), and WARNING.

Referenced by standard_ProcessUtility().

◆ DropOwnedObjects()

void DropOwnedObjects ( DropOwnedStmt stmt)
extern

Definition at line 1584 of file user.c.

1585{
1586 List *role_ids = roleSpecsToIds(stmt->roles);
1587 ListCell *cell;
1588
1589 /* Check privileges */
1590 foreach(cell, role_ids)
1591 {
1592 Oid roleid = lfirst_oid(cell);
1593
1594 if (!has_privs_of_role(GetUserId(), roleid))
1595 ereport(ERROR,
1597 errmsg("permission denied to drop objects"),
1598 errdetail("Only roles with privileges of role \"%s\" may drop objects owned by it.",
1599 GetUserNameFromId(roleid, false))));
1600 }
1601
1602 /* Ok, do it */
1603 shdepDropOwned(role_ids, stmt->behavior);
1604}
bool has_privs_of_role(Oid member, Oid role)
Definition acl.c:5284
char * GetUserNameFromId(Oid roleid, bool noerr)
Definition miscinit.c:988
#define lfirst_oid(lc)
Definition pg_list.h:174
void shdepDropOwned(List *roleids, DropBehavior behavior)

References ereport, errcode(), errdetail(), errmsg(), ERROR, fb(), GetUserId(), GetUserNameFromId(), has_privs_of_role(), lfirst_oid, roleSpecsToIds(), shdepDropOwned(), and stmt.

Referenced by ProcessUtilitySlow().

◆ DropRole()

void DropRole ( DropRoleStmt stmt)
extern

Definition at line 1091 of file user.c.

1092{
1095 ListCell *item;
1096 List *role_oids = NIL;
1097
1099 ereport(ERROR,
1101 errmsg("permission denied to drop role"),
1102 errdetail("Only roles with the %s attribute and the %s option on the target roles may drop roles.",
1103 "CREATEROLE", "ADMIN")));
1104
1105 /*
1106 * Scan the pg_authid relation to find the Oid of the role(s) to be
1107 * deleted and perform preliminary permissions and sanity checks.
1108 */
1111
1112 foreach(item, stmt->roles)
1113 {
1114 RoleSpec *rolspec = lfirst(item);
1115 char *role;
1116 HeapTuple tuple,
1117 tmp_tuple;
1121 Oid roleid;
1122
1123 if (rolspec->roletype != ROLESPEC_CSTRING)
1124 ereport(ERROR,
1126 errmsg("cannot use special role specifier in DROP ROLE")));
1127 role = rolspec->rolename;
1128
1130 if (!HeapTupleIsValid(tuple))
1131 {
1132 if (!stmt->missing_ok)
1133 {
1134 ereport(ERROR,
1136 errmsg("role \"%s\" does not exist", role)));
1137 }
1138 else
1139 {
1141 (errmsg("role \"%s\" does not exist, skipping",
1142 role)));
1143 }
1144
1145 continue;
1146 }
1147
1149 roleid = roleform->oid;
1150
1151 if (roleid == GetUserId())
1152 ereport(ERROR,
1154 errmsg("current user cannot be dropped")));
1155 if (roleid == GetOuterUserId())
1156 ereport(ERROR,
1158 errmsg("current user cannot be dropped")));
1159 if (roleid == GetSessionUserId())
1160 ereport(ERROR,
1162 errmsg("session user cannot be dropped")));
1163
1164 /*
1165 * For safety's sake, we allow createrole holders to drop ordinary
1166 * roles but not superuser roles, and only if they also have ADMIN
1167 * OPTION.
1168 */
1169 if (roleform->rolsuper && !superuser())
1170 ereport(ERROR,
1172 errmsg("permission denied to drop role"),
1173 errdetail("Only roles with the %s attribute may drop roles with the %s attribute.",
1174 "SUPERUSER", "SUPERUSER")));
1175 if (!is_admin_of_role(GetUserId(), roleid))
1176 ereport(ERROR,
1178 errmsg("permission denied to drop role"),
1179 errdetail("Only roles with the %s attribute and the %s option on role \"%s\" may drop this role.",
1180 "CREATEROLE", "ADMIN", NameStr(roleform->rolname))));
1181
1182 /* DROP hook for the role being removed */
1184
1185 /* Don't leak the syscache tuple */
1186 ReleaseSysCache(tuple);
1187
1188 /*
1189 * Lock the role, so nobody can add dependencies to her while we drop
1190 * her. We keep the lock until the end of transaction.
1191 */
1193
1194 /*
1195 * If there is a pg_auth_members entry that has one of the roles to be
1196 * dropped as the roleid or member, it should be silently removed, but
1197 * if there is a pg_auth_members entry that has one of the roles to be
1198 * dropped as the grantor, the operation should fail.
1199 *
1200 * It's possible, however, that a single pg_auth_members entry could
1201 * fall into multiple categories - e.g. the user could do "GRANT foo
1202 * TO bar GRANTED BY baz" and then "DROP ROLE baz, bar". We want such
1203 * an operation to succeed regardless of the order in which the
1204 * to-be-dropped roles are passed to DROP ROLE.
1205 *
1206 * To make that work, we remove all pg_auth_members entries that can
1207 * be silently removed in this loop, and then below we'll make a
1208 * second pass over the list of roles to be removed and check for any
1209 * remaining dependencies.
1210 */
1214 ObjectIdGetDatum(roleid));
1215
1217 true, NULL, 1, &scankey);
1218
1220 {
1222
1225 authmem_form->oid, 0);
1227 }
1228
1230
1234 ObjectIdGetDatum(roleid));
1235
1237 true, NULL, 1, &scankey);
1238
1240 {
1242
1245 authmem_form->oid, 0);
1247 }
1248
1250
1251 /*
1252 * Advance command counter so that later iterations of this loop will
1253 * see the changes already made. This is essential if, for example,
1254 * we are trying to drop both a role and one of its direct members ---
1255 * we'll get an error if we try to delete the linking pg_auth_members
1256 * tuple twice. (We do not need a CCI between the two delete loops
1257 * above, because it's not allowed for a role to directly contain
1258 * itself.)
1259 */
1261
1262 /* Looks tentatively OK, add it to the list if not there yet. */
1264 }
1265
1266 /*
1267 * Second pass over the roles to be removed.
1268 */
1269 foreach(item, role_oids)
1270 {
1271 Oid roleid = lfirst_oid(item);
1272 HeapTuple tuple;
1274 char *detail;
1275 char *detail_log;
1276
1277 /*
1278 * Re-find the pg_authid tuple.
1279 *
1280 * Since we've taken a lock on the role OID, it shouldn't be possible
1281 * for the tuple to have been deleted -- or for that matter updated --
1282 * unless the user is manually modifying the system catalogs.
1283 */
1284 tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
1285 if (!HeapTupleIsValid(tuple))
1286 elog(ERROR, "could not find tuple for role %u", roleid);
1288
1289 /*
1290 * Check for pg_shdepend entries depending on this role.
1291 *
1292 * This needs to happen after we've completed removing any
1293 * pg_auth_members entries that can be removed silently, in order to
1294 * avoid spurious failures. See notes above for more details.
1295 */
1297 &detail, &detail_log))
1298 ereport(ERROR,
1300 errmsg("role \"%s\" cannot be dropped because some objects depend on it",
1301 NameStr(roleform->rolname)),
1302 errdetail_internal("%s", detail),
1303 errdetail_log("%s", detail_log)));
1304
1305 /*
1306 * Remove the role from the pg_authid table
1307 */
1309
1310 ReleaseSysCache(tuple);
1311
1312 /*
1313 * Remove any comments or security labels on this role.
1314 */
1317
1318 /*
1319 * Remove settings for this role.
1320 */
1321 DropSetting(InvalidOid, roleid);
1322 }
1323
1324 /*
1325 * Now we can clean up; but keep locks until commit.
1326 */
1329}
void DeleteSharedComments(Oid oid, Oid classoid)
Definition comment.c:374
int errdetail_internal(const char *fmt,...)
Definition elog.c:1243
int errdetail_log(const char *fmt,...)
Definition elog.c:1264
void systable_endscan(SysScanDesc sysscan)
Definition genam.c:603
HeapTuple systable_getnext(SysScanDesc sysscan)
Definition genam.c:514
SysScanDesc systable_beginscan(Relation heapRelation, Oid indexId, bool indexOK, Snapshot snapshot, int nkeys, ScanKey key)
Definition genam.c:388
#define HeapTupleIsValid(tuple)
Definition htup.h:78
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition indexing.c:365
List * list_append_unique_oid(List *list, Oid datum)
Definition list.c:1380
void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode)
Definition lmgr.c:1088
#define AccessExclusiveLock
Definition lockdefs.h:43
Oid GetOuterUserId(void)
Definition miscinit.c:480
Oid GetSessionUserId(void)
Definition miscinit.c:508
#define InvokeObjectDropHook(classId, objectId, subId)
FormData_pg_auth_members * Form_pg_auth_members
void DropSetting(Oid databaseid, Oid roleid)
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
bool checkSharedDependencies(Oid classId, Oid objectId, char **detail_msg, char **detail_log_msg)
static Datum PointerGetDatum(const void *X)
Definition postgres.h:352
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
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition syscache.c:220

References AccessExclusiveLock, BTEqualStrategyNumber, CatalogTupleDelete(), checkSharedDependencies(), CommandCounterIncrement(), DeleteSharedComments(), deleteSharedDependencyRecordsFor(), DeleteSharedSecurityLabel(), DropSetting(), elog, ereport, errcode(), errdetail(), errdetail_internal(), errdetail_log(), errmsg(), ERROR, fb(), GetOuterUserId(), GetSessionUserId(), GETSTRUCT(), GetUserId(), have_createrole_privilege(), HeapTupleIsValid, InvalidOid, InvokeObjectDropHook, is_admin_of_role(), lfirst, lfirst_oid, list_append_unique_oid(), LockSharedObject(), NameStr, NIL, NoLock, NOTICE, ObjectIdGetDatum(), PointerGetDatum(), ReleaseSysCache(), ROLESPEC_CSTRING, RowExclusiveLock, ScanKeyInit(), SearchSysCache1(), stmt, 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 
)
extern

Definition at line 1481 of file user.c.

1482{
1484 Oid grantor;
1486 ListCell *item;
1487 GrantRoleOptions popt;
1489
1490 /* Parse options list. */
1491 InitGrantRoleOptions(&popt);
1492 foreach(item, stmt->opt)
1493 {
1494 DefElem *opt = (DefElem *) lfirst(item);
1495 char *optval = defGetString(opt);
1496
1497 if (strcmp(opt->defname, "admin") == 0)
1498 {
1500
1501 if (parse_bool(optval, &popt.admin))
1502 continue;
1503 }
1504 else if (strcmp(opt->defname, "inherit") == 0)
1505 {
1507 if (parse_bool(optval, &popt.inherit))
1508 continue;
1509 }
1510 else if (strcmp(opt->defname, "set") == 0)
1511 {
1513 if (parse_bool(optval, &popt.set))
1514 continue;
1515 }
1516 else
1517 ereport(ERROR,
1519 errmsg("unrecognized role option \"%s\"", opt->defname),
1520 parser_errposition(pstate, opt->location));
1521
1522 ereport(ERROR,
1524 errmsg("unrecognized value for role option \"%s\": \"%s\"",
1525 opt->defname, optval),
1526 parser_errposition(pstate, opt->location)));
1527 }
1528
1529 /* Lookup OID of grantor, if specified. */
1530 if (stmt->grantor)
1531 grantor = get_rolespec_oid(stmt->grantor, false);
1532 else
1533 grantor = InvalidOid;
1534
1535 grantee_ids = roleSpecsToIds(stmt->grantee_roles);
1536
1537 /* AccessShareLock is enough since we aren't modifying pg_authid */
1539
1540 /*
1541 * Step through all of the granted roles and add, update, or remove
1542 * entries in pg_auth_members as appropriate. If stmt->is_grant is true,
1543 * we are adding new grants or, if they already exist, updating options on
1544 * those grants. If stmt->is_grant is false, we are revoking grants or
1545 * removing options from them.
1546 */
1547 foreach(item, stmt->granted_roles)
1548 {
1549 AccessPriv *priv = (AccessPriv *) lfirst(item);
1550 char *rolename = priv->priv_name;
1551 Oid roleid;
1552
1553 /* Must reject priv(columns) and ALL PRIVILEGES(columns) */
1554 if (rolename == NULL || priv->cols != NIL)
1555 ereport(ERROR,
1557 errmsg("column names cannot be included in GRANT/REVOKE ROLE")));
1558
1559 roleid = get_role_oid(rolename, false);
1561 roleid, stmt->is_grant);
1562 if (stmt->is_grant)
1563 AddRoleMems(currentUserId, rolename, roleid,
1564 stmt->grantee_roles, grantee_ids,
1565 grantor, &popt);
1566 else
1567 DelRoleMems(currentUserId, rolename, roleid,
1568 stmt->grantee_roles, grantee_ids,
1569 grantor, &popt, stmt->behavior);
1570 }
1571
1572 /*
1573 * Close pg_authid, but keep lock till commit.
1574 */
1576}
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
Definition acl.c:5586
bool parse_bool(const char *value, bool *result)
Definition bool.c:31
char * defGetString(DefElem *def)
Definition define.c:34
#define AccessShareLock
Definition lockdefs.h:36
int parser_errposition(ParseState *pstate, int location)
Definition parse_node.c:106
char * priv_name
List * cols
char * defname
Definition parsenodes.h:844
ParseLoc location
Definition parsenodes.h:848

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

Referenced by standard_ProcessUtility().

◆ ReassignOwnedObjects()

void ReassignOwnedObjects ( ReassignOwnedStmt stmt)
extern

Definition at line 1612 of file user.c.

1613{
1614 List *role_ids = roleSpecsToIds(stmt->roles);
1615 ListCell *cell;
1616 Oid newrole;
1617
1618 /* Check privileges */
1619 foreach(cell, role_ids)
1620 {
1621 Oid roleid = lfirst_oid(cell);
1622
1623 if (!has_privs_of_role(GetUserId(), roleid))
1624 ereport(ERROR,
1626 errmsg("permission denied to reassign objects"),
1627 errdetail("Only roles with privileges of role \"%s\" may reassign objects owned by it.",
1628 GetUserNameFromId(roleid, false))));
1629 }
1630
1631 /* Must have privileges on the receiving side too */
1632 newrole = get_rolespec_oid(stmt->newrole, false);
1633
1634 if (!has_privs_of_role(GetUserId(), newrole))
1635 ereport(ERROR,
1637 errmsg("permission denied to reassign objects"),
1638 errdetail("Only roles with privileges of role \"%s\" may reassign objects to it.",
1639 GetUserNameFromId(newrole, false))));
1640
1641 /* Ok, do it */
1642 shdepReassignOwned(role_ids, newrole);
1643}
void shdepReassignOwned(List *roleids, Oid newrole)

References ereport, errcode(), errdetail(), errmsg(), ERROR, fb(), get_rolespec_oid(), GetUserId(), GetUserNameFromId(), has_privs_of_role(), lfirst_oid, roleSpecsToIds(), shdepReassignOwned(), and stmt.

Referenced by standard_ProcessUtility().

◆ RenameRole()

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

Definition at line 1335 of file user.c.

1336{
1337 HeapTuple oldtuple,
1338 newtuple;
1339 TupleDesc dsc;
1340 Relation rel;
1341 Datum datum;
1342 bool isnull;
1346 int i;
1347 Oid roleid;
1348 ObjectAddress address;
1350
1352 dsc = RelationGetDescr(rel);
1353
1355 if (!HeapTupleIsValid(oldtuple))
1356 ereport(ERROR,
1358 errmsg("role \"%s\" does not exist", oldname)));
1359
1360 /*
1361 * XXX Client applications probably store the session user somewhere, so
1362 * renaming it could cause confusion. On the other hand, there may not be
1363 * an actual problem besides a little confusion, so think about this and
1364 * decide. Same for SET ROLE ... we don't restrict renaming the current
1365 * effective userid, though.
1366 */
1367
1368 authform = (Form_pg_authid) GETSTRUCT(oldtuple);
1369 roleid = authform->oid;
1370
1371 if (roleid == GetSessionUserId())
1372 ereport(ERROR,
1374 errmsg("session user cannot be renamed")));
1375 if (roleid == GetOuterUserId())
1376 ereport(ERROR,
1378 errmsg("current user cannot be renamed")));
1379
1380 /*
1381 * Check that the user is not trying to rename a system role and not
1382 * trying to rename a role into the reserved "pg_" namespace.
1383 */
1384 if (IsReservedName(NameStr(authform->rolname)))
1385 ereport(ERROR,
1387 errmsg("role name \"%s\" is reserved",
1388 NameStr(authform->rolname)),
1389 errdetail("Role names starting with \"pg_\" are reserved.")));
1390
1391 if (IsReservedName(newname))
1392 ereport(ERROR,
1394 errmsg("role name \"%s\" is reserved",
1395 newname),
1396 errdetail("Role names starting with \"pg_\" are reserved.")));
1397
1398 /*
1399 * If built with appropriate switch, whine when regression-testing
1400 * conventions for role names are violated.
1401 */
1402#ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
1403 if (strncmp(newname, "regress_", 8) != 0)
1404 elog(WARNING, "roles created by regression test cases should have names starting with \"regress_\"");
1405#endif
1406
1407 /* make sure the new name doesn't exist */
1409 ereport(ERROR,
1411 errmsg("role \"%s\" already exists", newname)));
1412
1413 /*
1414 * Only superusers can mess with superusers. Otherwise, a user with
1415 * CREATEROLE can rename a role for which they have ADMIN OPTION.
1416 */
1417 if (authform->rolsuper)
1418 {
1419 if (!superuser())
1420 ereport(ERROR,
1422 errmsg("permission denied to rename role"),
1423 errdetail("Only roles with the %s attribute may rename roles with the %s attribute.",
1424 "SUPERUSER", "SUPERUSER")));
1425 }
1426 else
1427 {
1429 !is_admin_of_role(GetUserId(), roleid))
1430 ereport(ERROR,
1432 errmsg("permission denied to rename role"),
1433 errdetail("Only roles with the %s attribute and the %s option on role \"%s\" may rename this role.",
1434 "CREATEROLE", "ADMIN", NameStr(authform->rolname))));
1435 }
1436
1437 /* OK, construct the modified tuple */
1438 for (i = 0; i < Natts_pg_authid; i++)
1439 repl_repl[i] = false;
1440
1443 CStringGetDatum(newname));
1444 repl_null[Anum_pg_authid_rolname - 1] = false;
1445
1446 datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull);
1447
1449 {
1450 /* MD5 uses the username as salt, so just clear it on a rename */
1453
1455 (errmsg("MD5 password cleared because of role rename")));
1456 }
1457
1458 newtuple = heap_modify_tuple(oldtuple, dsc, repl_val, repl_null, repl_repl);
1459 CatalogTupleUpdate(rel, &oldtuple->t_self, newtuple);
1460
1462
1463 ObjectAddressSet(address, AuthIdRelationId, roleid);
1464
1465 ReleaseSysCache(oldtuple);
1466
1467 /*
1468 * Close pg_authid, but keep lock till commit.
1469 */
1470 table_close(rel, NoLock);
1471
1472 return address;
1473}
#define TextDatumGetCString(d)
Definition builtins.h:98
@ PASSWORD_TYPE_MD5
Definition crypt.h:43
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
int i
Definition isn.c:77
#define ObjectAddressSet(addr, class_id, object_id)
#define SearchSysCacheExists1(cacheId, key1)
Definition syscache.h:100

References CatalogTupleUpdate(), CStringGetDatum(), DirectFunctionCall1, elog, ereport, errcode(), ERRCODE_DUPLICATE_OBJECT, errdetail(), errmsg(), ERROR, fb(), 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)
extern

Definition at line 1653 of file user.c.

1654{
1655 List *result = NIL;
1656 ListCell *l;
1657
1658 foreach(l, memberNames)
1659 {
1661 Oid roleid;
1662
1663 roleid = get_rolespec_oid(rolespec, false);
1664 result = lappend_oid(result, roleid);
1665 }
1666 return result;
1667}
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
#define lfirst_node(type, lc)
Definition pg_list.h:176

References fb(), 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().