LCOV - differential code coverage report
Current view: top level - src/backend/commands - user.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 88.9 % 862 766 315 18 41 2 13 280 323 150 38 255 15 91
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 21 21 9 12 19 2
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 [..60] days: 80.0 % 10 8 2 8
Legend: Lines: hit not hit (60,120] days: 89.0 % 100 89 10 1 89 1 2
(120,180] days: 95.0 % 20 19 1 19
(180,240] days: 90.4 % 219 198 21 2 195 1 5
(240..) days: 88.1 % 513 452 1 18 41 1 13 278 12 149 37 248
Function coverage date bins:
(60,120] days: 100.0 % 5 5 5
(180,240] days: 87.5 % 8 7 7 1
(240..) days: 60.0 % 15 9 9 6

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * user.c
                                  4                 :  *    Commands for manipulating roles (formerly called users).
                                  5                 :  *
                                  6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  7                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :  *
                                  9                 :  * src/backend/commands/user.c
                                 10                 :  *
                                 11                 :  *-------------------------------------------------------------------------
                                 12                 :  */
                                 13                 : #include "postgres.h"
                                 14                 : 
                                 15                 : #include "access/genam.h"
                                 16                 : #include "access/htup_details.h"
                                 17                 : #include "access/table.h"
                                 18                 : #include "access/xact.h"
                                 19                 : #include "catalog/binary_upgrade.h"
                                 20                 : #include "catalog/catalog.h"
                                 21                 : #include "catalog/dependency.h"
                                 22                 : #include "catalog/indexing.h"
                                 23                 : #include "catalog/objectaccess.h"
                                 24                 : #include "catalog/pg_auth_members.h"
                                 25                 : #include "catalog/pg_authid.h"
                                 26                 : #include "catalog/pg_database.h"
                                 27                 : #include "catalog/pg_db_role_setting.h"
                                 28                 : #include "commands/comment.h"
                                 29                 : #include "commands/dbcommands.h"
                                 30                 : #include "commands/defrem.h"
                                 31                 : #include "commands/seclabel.h"
                                 32                 : #include "commands/user.h"
                                 33                 : #include "libpq/crypt.h"
                                 34                 : #include "miscadmin.h"
                                 35                 : #include "storage/lmgr.h"
                                 36                 : #include "utils/acl.h"
                                 37                 : #include "utils/builtins.h"
                                 38                 : #include "utils/catcache.h"
                                 39                 : #include "utils/fmgroids.h"
                                 40                 : #include "utils/syscache.h"
                                 41                 : #include "utils/timestamp.h"
                                 42                 : #include "utils/varlena.h"
                                 43                 : 
                                 44                 : /*
                                 45                 :  * Removing a role grant - or the admin option on it - might recurse to
                                 46                 :  * dependent grants. We use these values to reason about what would need to
                                 47                 :  * be done in such cases.
                                 48                 :  *
                                 49                 :  * RRG_NOOP indicates a grant that would not need to be altered by the
                                 50                 :  * operation.
                                 51                 :  *
                                 52                 :  * RRG_REMOVE_ADMIN_OPTION indicates a grant that would need to have
                                 53                 :  * admin_option set to false by the operation.
                                 54                 :  *
                                 55                 :  * Similarly, RRG_REMOVE_INHERIT_OPTION and RRG_REMOVE_SET_OPTION indicate
                                 56                 :  * grants that would need to have the corresponding options set to false.
                                 57                 :  *
                                 58                 :  * RRG_DELETE_GRANT indicates a grant that would need to be removed entirely
                                 59                 :  * by the operation.
                                 60                 :  */
                                 61                 : typedef enum
                                 62                 : {
                                 63                 :     RRG_NOOP,
                                 64                 :     RRG_REMOVE_ADMIN_OPTION,
                                 65                 :     RRG_REMOVE_INHERIT_OPTION,
                                 66                 :     RRG_REMOVE_SET_OPTION,
                                 67                 :     RRG_DELETE_GRANT
                                 68                 : } RevokeRoleGrantAction;
                                 69                 : 
                                 70                 : /* Potentially set by pg_upgrade_support functions */
                                 71                 : Oid         binary_upgrade_next_pg_authid_oid = InvalidOid;
                                 72                 : 
                                 73                 : typedef struct
                                 74                 : {
                                 75                 :     unsigned    specified;
                                 76                 :     bool        admin;
                                 77                 :     bool        inherit;
                                 78                 :     bool        set;
                                 79                 : } GrantRoleOptions;
                                 80                 : 
                                 81                 : #define GRANT_ROLE_SPECIFIED_ADMIN          0x0001
                                 82                 : #define GRANT_ROLE_SPECIFIED_INHERIT        0x0002
                                 83                 : #define GRANT_ROLE_SPECIFIED_SET            0x0004
                                 84                 : 
                                 85                 : /* GUC parameters */
                                 86                 : int         Password_encryption = PASSWORD_TYPE_SCRAM_SHA_256;
                                 87                 : char       *createrole_self_grant = "";
                                 88                 : bool        createrole_self_grant_enabled = false;
                                 89                 : GrantRoleOptions    createrole_self_grant_options;
                                 90                 : 
                                 91                 : /* Hook to check passwords in CreateRole() and AlterRole() */
                                 92                 : check_password_hook_type check_password_hook = NULL;
                                 93                 : 
                                 94                 : static void AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
                                 95                 :                         List *memberSpecs, List *memberIds,
                                 96                 :                         Oid grantorId, GrantRoleOptions *popt);
                                 97                 : static void DelRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
                                 98                 :                         List *memberSpecs, List *memberIds,
                                 99                 :                         Oid grantorId, GrantRoleOptions *popt,
                                100                 :                         DropBehavior behavior);
                                101                 : static void check_role_membership_authorization(Oid currentUserId, Oid roleid,
                                102                 :                                                 bool is_grant);
                                103                 : static Oid  check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId,
                                104                 :                                bool is_grant);
                                105                 : static RevokeRoleGrantAction *initialize_revoke_actions(CatCList *memlist);
                                106                 : static bool plan_single_revoke(CatCList *memlist,
                                107                 :                                RevokeRoleGrantAction *actions,
                                108                 :                                Oid member, Oid grantor,
                                109                 :                                GrantRoleOptions *popt,
                                110                 :                                DropBehavior behavior);
                                111                 : static void plan_member_revoke(CatCList *memlist,
                                112                 :                                RevokeRoleGrantAction *actions, Oid member);
                                113                 : static void plan_recursive_revoke(CatCList *memlist,
                                114                 :                                   RevokeRoleGrantAction *actions,
                                115                 :                                   int index,
                                116                 :                                   bool revoke_admin_option_only,
                                117                 :                                   DropBehavior behavior);
                                118                 : static void InitGrantRoleOptions(GrantRoleOptions *popt);
                                119                 : 
                                120                 : 
                                121                 : /* Check if current user has createrole privileges */
                                122                 : static bool
 3029 alvherre                  123 GIC        1014 : have_createrole_privilege(void)
                                124                 : {
                                125            1014 :     return has_createrole_privilege(GetUserId());
                                126                 : }
                                127                 : 
                                128                 : 
                                129                 : /*
                                130                 :  * CREATE ROLE
                                131                 :  */
                                132                 : Oid
 2406 peter_e                   133             799 : CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
                                134                 : {
                                135                 :     Relation    pg_authid_rel;
                                136                 :     TupleDesc   pg_authid_dsc;
                                137                 :     HeapTuple   tuple;
  267 peter                     138 GNC         799 :     Datum       new_record[Natts_pg_authid] = {0};
                                139             799 :     bool        new_record_nulls[Natts_pg_authid] = {0};
   94 rhaas                     140             799 :     Oid         currentUserId = GetUserId();
                                141                 :     Oid         roleid;
                                142                 :     ListCell   *item;
                                143                 :     ListCell   *option;
 6385 bruce                     144 GIC         799 :     char       *password = NULL;    /* user password */
 3029 alvherre                  145             799 :     bool        issuper = false;    /* Make the user a superuser? */
                                146             799 :     bool        inherit = true; /* Auto inherit privileges? */
 2118 tgl                       147             799 :     bool        createrole = false; /* Can this user create roles? */
                                148             799 :     bool        createdb = false;   /* Can the user create databases? */
                                149             799 :     bool        canlogin = false;   /* Can this user login? */
 3029 alvherre                  150             799 :     bool        isreplication = false;  /* Is this a replication role? */
 2118 tgl                       151             799 :     bool        bypassrls = false;  /* Is this a row security enabled role? */
 6385 bruce                     152             799 :     int         connlimit = -1; /* maximum connections allowed */
                                153             799 :     List       *addroleto = NIL;    /* roles to make this a member of */
 2118 tgl                       154             799 :     List       *rolemembers = NIL;  /* roles to be members of this role */
                                155             799 :     List       *adminmembers = NIL; /* roles to be admins of this role */
                                156             799 :     char       *validUntil = NULL;  /* time the login is valid until */
                                157                 :     Datum       validUntil_datum;   /* same, as timestamptz Datum */
                                158                 :     bool        validUntil_null;
 7907 bruce                     159             799 :     DefElem    *dpassword = NULL;
 6493 tgl                       160             799 :     DefElem    *dissuper = NULL;
 6466                           161             799 :     DefElem    *dinherit = NULL;
 6494                           162             799 :     DefElem    *dcreaterole = NULL;
 6493                           163             799 :     DefElem    *dcreatedb = NULL;
 6494                           164             799 :     DefElem    *dcanlogin = NULL;
 4382 bruce                     165             799 :     DefElem    *disreplication = NULL;
 6461 tgl                       166             799 :     DefElem    *dconnlimit = NULL;
 6494                           167             799 :     DefElem    *daddroleto = NULL;
                                168             799 :     DefElem    *drolemembers = NULL;
                                169             799 :     DefElem    *dadminmembers = NULL;
 7907 bruce                     170             799 :     DefElem    *dvalidUntil = NULL;
 3124 sfrost                    171             799 :     DefElem    *dbypassRLS = NULL;
                                172                 :     GrantRoleOptions    popt;
                                173                 : 
                                174                 :     /* The defaults can vary depending on the original statement type */
 6466 tgl                       175             799 :     switch (stmt->stmt_type)
                                176                 :     {
                                177             574 :         case ROLESTMT_ROLE:
                                178             574 :             break;
                                179             213 :         case ROLESTMT_USER:
 3029 alvherre                  180             213 :             canlogin = true;
                                181                 :             /* may eventually want inherit to default to false here */
 6466 tgl                       182             213 :             break;
                                183              12 :         case ROLESTMT_GROUP:
                                184              12 :             break;
                                185                 :     }
 6466 tgl                       186 ECB             : 
                                187                 :     /* Extract options from the statement node tree */
 7943 tgl                       188 CBC        1317 :     foreach(option, stmt->options)
                                189                 :     {
 7836 bruce                     190 GIC         518 :         DefElem    *defel = (DefElem *) lfirst(option);
                                191                 : 
 2162 heikki.linnakangas        192             518 :         if (strcmp(defel->defname, "password") == 0)
                                193                 :         {
 7907 bruce                     194              57 :             if (dpassword)
  633 dean.a.rasheed            195 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 7907 bruce                     196 CBC          57 :             dpassword = defel;
                                197                 :         }
 7836 bruce                     198 GIC         461 :         else if (strcmp(defel->defname, "sysid") == 0)
                                199                 :         {
 6466 tgl                       200               3 :             ereport(NOTICE,
 6494 tgl                       201 ECB             :                     (errmsg("SYSID can no longer be specified")));
                                202                 :         }
 6493 tgl                       203 CBC         458 :         else if (strcmp(defel->defname, "superuser") == 0)
                                204                 :         {
 6493 tgl                       205 GIC          84 :             if (dissuper)
  633 dean.a.rasheed            206 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 6493 tgl                       207 CBC          84 :             dissuper = defel;
 6493 tgl                       208 ECB             :         }
 6466 tgl                       209 CBC         374 :         else if (strcmp(defel->defname, "inherit") == 0)
 6466 tgl                       210 ECB             :         {
 6466 tgl                       211 CBC          28 :             if (dinherit)
  633 dean.a.rasheed            212 LBC           0 :                 errorConflictingDefElem(defel, pstate);
 6466 tgl                       213 CBC          28 :             dinherit = defel;
 6466 tgl                       214 ECB             :         }
 6494 tgl                       215 CBC         346 :         else if (strcmp(defel->defname, "createrole") == 0)
 6494 tgl                       216 ECB             :         {
 6494 tgl                       217 CBC          41 :             if (dcreaterole)
  633 dean.a.rasheed            218 LBC           0 :                 errorConflictingDefElem(defel, pstate);
 6494 tgl                       219 CBC          41 :             dcreaterole = defel;
                                220                 :         }
 7836 bruce                     221 GIC         305 :         else if (strcmp(defel->defname, "createdb") == 0)
 7836 bruce                     222 ECB             :         {
 7907 bruce                     223 CBC          31 :             if (dcreatedb)
  633 dean.a.rasheed            224 LBC           0 :                 errorConflictingDefElem(defel, pstate);
 7907 bruce                     225 CBC          31 :             dcreatedb = defel;
 7907 bruce                     226 ECB             :         }
 6494 tgl                       227 CBC         274 :         else if (strcmp(defel->defname, "canlogin") == 0)
 7836 bruce                     228 ECB             :         {
 6494 tgl                       229 CBC         124 :             if (dcanlogin)
  633 dean.a.rasheed            230 LBC           0 :                 errorConflictingDefElem(defel, pstate);
 6494 tgl                       231 CBC         124 :             dcanlogin = defel;
 7907 bruce                     232 ECB             :         }
 4484 magnus                    233 CBC         150 :         else if (strcmp(defel->defname, "isreplication") == 0)
 4484 magnus                    234 ECB             :         {
 4484 magnus                    235 GIC          38 :             if (disreplication)
  633 dean.a.rasheed            236 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 4484 magnus                    237 GIC          38 :             disreplication = defel;
 4484 magnus                    238 ECB             :         }
 6461 tgl                       239 GIC         112 :         else if (strcmp(defel->defname, "connectionlimit") == 0)
 6461 tgl                       240 ECB             :         {
 6461 tgl                       241 CBC           6 :             if (dconnlimit)
  633 dean.a.rasheed            242 LBC           0 :                 errorConflictingDefElem(defel, pstate);
 6461 tgl                       243 CBC           6 :             dconnlimit = defel;
                                244                 :         }
 6494                           245             106 :         else if (strcmp(defel->defname, "addroleto") == 0)
 7836 bruce                     246 ECB             :         {
 6494 tgl                       247 CBC          48 :             if (daddroleto)
  633 dean.a.rasheed            248 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 6494 tgl                       249 GIC          48 :             daddroleto = defel;
                                250                 :         }
 6494 tgl                       251 CBC          58 :         else if (strcmp(defel->defname, "rolemembers") == 0)
                                252                 :         {
                                253              10 :             if (drolemembers)
  633 dean.a.rasheed            254 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 6494 tgl                       255 CBC          10 :             drolemembers = defel;
                                256                 :         }
                                257              48 :         else if (strcmp(defel->defname, "adminmembers") == 0)
 6494 tgl                       258 EUB             :         {
 6494 tgl                       259 CBC          10 :             if (dadminmembers)
  633 dean.a.rasheed            260 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 6494 tgl                       261 CBC          10 :             dadminmembers = defel;
                                262                 :         }
 7836 bruce                     263              38 :         else if (strcmp(defel->defname, "validUntil") == 0)
                                264                 :         {
 7907 bruce                     265 GIC           1 :             if (dvalidUntil)
  633 dean.a.rasheed            266 LBC           0 :                 errorConflictingDefElem(defel, pstate);
 7907 bruce                     267 GIC           1 :             dvalidUntil = defel;
 7907 bruce                     268 ECB             :         }
 3124 sfrost                    269 GBC          37 :         else if (strcmp(defel->defname, "bypassrls") == 0)
 3124 sfrost                    270 ECB             :         {
 3124 sfrost                    271 GIC          37 :             if (dbypassRLS)
  633 dean.a.rasheed            272 LBC           0 :                 errorConflictingDefElem(defel, pstate);
 3124 sfrost                    273 GIC          37 :             dbypassRLS = defel;
 3124 sfrost                    274 ECB             :         }
 7907 bruce                     275 EUB             :         else
 7205 tgl                       276 LBC           0 :             elog(ERROR, "option \"%s\" not recognized",
                                277                 :                  defel->defname);
 7907 bruce                     278 ECB             :     }
                                279                 : 
 6316 peter_e                   280 CBC         799 :     if (dpassword && dpassword->arg)
 6493 tgl                       281 GBC          51 :         password = strVal(dpassword->arg);
 6493 tgl                       282 CBC         799 :     if (dissuper)
  450 peter                     283 GIC          84 :         issuper = boolVal(dissuper->arg);
 6466 tgl                       284 CBC         799 :     if (dinherit)
  450 peter                     285 GIC          28 :         inherit = boolVal(dinherit->arg);
 6494 tgl                       286 CBC         799 :     if (dcreaterole)
  450 peter                     287 GBC          41 :         createrole = boolVal(dcreaterole->arg);
 6493 tgl                       288 CBC         799 :     if (dcreatedb)
  450 peter                     289 GIC          31 :         createdb = boolVal(dcreatedb->arg);
 6494 tgl                       290 CBC         799 :     if (dcanlogin)
  450 peter                     291 GIC         124 :         canlogin = boolVal(dcanlogin->arg);
 4484 magnus                    292 CBC         799 :     if (disreplication)
  450 peter                     293 GBC          38 :         isreplication = boolVal(disreplication->arg);
 6461 tgl                       294 CBC         799 :     if (dconnlimit)
                                295                 :     {
                                296               6 :         connlimit = intVal(dconnlimit->arg);
 5182 heikki.linnakangas        297 GIC           6 :         if (connlimit < -1)
 5182 heikki.linnakangas        298 LBC           0 :             ereport(ERROR,
 5182 heikki.linnakangas        299 EUB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 5182 heikki.linnakangas        300 ECB             :                      errmsg("invalid connection limit: %d", connlimit)));
                                301                 :     }
 6494 tgl                       302 CBC         799 :     if (daddroleto)
 6494 tgl                       303 GIC          48 :         addroleto = (List *) daddroleto->arg;
 6494 tgl                       304 CBC         799 :     if (drolemembers)
 6494 tgl                       305 GBC          10 :         rolemembers = (List *) drolemembers->arg;
 6494 tgl                       306 CBC         799 :     if (dadminmembers)
 6494 tgl                       307 GIC          10 :         adminmembers = (List *) dadminmembers->arg;
 6493 tgl                       308 CBC         799 :     if (dvalidUntil)
 6493 tgl                       309 GIC           1 :         validUntil = strVal(dvalidUntil->arg);
 3029 alvherre                  310 CBC         799 :     if (dbypassRLS)
  450 peter                     311 GBC          37 :         bypassrls = boolVal(dbypassRLS->arg);
 8773 tgl                       312 ECB             : 
                                313                 :     /* Check some permissions first */
   75 rhaas                     314 GNC         799 :     if (!superuser_arg(currentUserId))
                                315                 :     {
                                316             111 :         if (!has_createrole_privilege(currentUserId))
   75 rhaas                     317 UBC           0 :             ereport(ERROR,
   75 rhaas                     318 ECB             :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                319                 :                      errmsg("permission denied to create role"),
                                320                 :                      errdetail("Only roles with the %s attribute may create roles.",
                                321                 :                                "CREATEROLE")));
   75 rhaas                     322 GNC         111 :         if (issuper)
 3029 alvherre                  323 CBC           3 :             ereport(ERROR,
                                324                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                325                 :                      errmsg("permission denied to create role"),
                                326                 :                      errdetail("Only roles with the %s attribute may create roles with %s.",
                                327                 :                                "SUPERUSER", "SUPERUSER")));
   75 rhaas                     328 GNC         108 :         if (createdb && !have_createdb_privilege())
 3029 alvherre                  329 GIC           3 :             ereport(ERROR,
 3029 alvherre                  330 ECB             :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                331                 :                      errmsg("permission denied to create role"),
                                332                 :                      errdetail("Only roles with the %s attribute may create roles with %s.",
                                333                 :                                "CREATEDB", "CREATEDB")));
   75 rhaas                     334 GNC         105 :         if (isreplication && !has_rolreplication(currentUserId))
 3029 alvherre                  335 GIC           6 :             ereport(ERROR,
 3029 alvherre                  336 EUB             :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                337                 :                      errmsg("permission denied to create role"),
                                338                 :                      errdetail("Only roles with the %s attribute may create roles with %s.",
                                339                 :                                "REPLICATION", "REPLICATION")));
   75 rhaas                     340 GNC          99 :         if (bypassrls && !has_bypassrls_privilege(currentUserId))
 3029 alvherre                  341               3 :             ereport(ERROR,
                                342                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                343                 :                      errmsg("permission denied to create role"),
                                344                 :                      errdetail("Only roles with the %s attribute may create roles with %s.",
                                345                 :                                "BYPASSRLS", "BYPASSRLS")));
                                346                 :     }
                                347                 : 
 2557 sfrost                    348 ECB             :     /*
                                349                 :      * Check that the user is not trying to create a role in the reserved
                                350                 :      * "pg_" namespace.
                                351                 :      */
 2557 sfrost                    352 CBC         784 :     if (IsReservedName(stmt->role))
                                353               4 :         ereport(ERROR,
 2557 sfrost                    354 ECB             :                 (errcode(ERRCODE_RESERVED_NAME),
                                355                 :                  errmsg("role name \"%s\" is reserved",
 2495 rhaas                     356                 :                         stmt->role),
 2118 tgl                       357                 :                  errdetail("Role names starting with \"pg_\" are reserved.")));
 2557 sfrost                    358                 : 
 1380 tgl                       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_\"");
 1380 tgl                       366 EUB             : #endif
                                367                 : 
                                368                 :     /*
                                369                 :      * Check the pg_authid relation to be certain the role doesn't already
 6184 tgl                       370 ECB             :      * exist.
 9173 bruce                     371                 :      */
 1539 andres                    372 CBC         780 :     pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
 6494 tgl                       373             780 :     pg_authid_dsc = RelationGetDescr(pg_authid_rel);
 9173 bruce                     374 ECB             : 
 4630 rhaas                     375 CBC         780 :     if (OidIsValid(get_role_oid(stmt->role, true)))
 7205 tgl                       376               3 :         ereport(ERROR,
 7205 tgl                       377 ECB             :                 (errcode(ERRCODE_DUPLICATE_OBJECT),
 6494                           378                 :                  errmsg("role \"%s\" already exists",
                                379                 :                         stmt->role)));
                                380                 : 
                                381                 :     /* Convert validuntil to internal form */
 4890 tgl                       382 CBC         777 :     if (validUntil)
                                383                 :     {
                                384               1 :         validUntil_datum = DirectFunctionCall3(timestamptz_in,
 4890 tgl                       385 EUB             :                                                CStringGetDatum(validUntil),
                                386                 :                                                ObjectIdGetDatum(InvalidOid),
                                387                 :                                                Int32GetDatum(-1));
 4890 tgl                       388 GIC           1 :         validUntil_null = false;
                                389                 :     }
 4890 tgl                       390 ECB             :     else
                                391                 :     {
 4890 tgl                       392 GIC         776 :         validUntil_datum = (Datum) 0;
                                393             776 :         validUntil_null = true;
                                394                 :     }
                                395                 : 
 4890 tgl                       396 ECB             :     /*
                                397                 :      * Call the password checking hook if there is one defined
                                398                 :      */
 4890 tgl                       399 GIC         777 :     if (check_password_hook && password)
 4890 tgl                       400 UIC           0 :         (*check_password_hook) (stmt->role,
                                401                 :                                 password,
 2258 heikki.linnakangas        402 ECB             :                                 get_password_type(password),
 4890 tgl                       403                 :                                 validUntil_datum,
                                404                 :                                 validUntil_null);
                                405                 : 
                                406                 :     /*
                                407                 :      * Build a tuple to insert
 8397 bruce                     408                 :      */
 6494 tgl                       409 GIC         777 :     new_record[Anum_pg_authid_rolname - 1] =
                                410             777 :         DirectFunctionCall1(namein, CStringGetDatum(stmt->role));
 3029 alvherre                  411             777 :     new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(issuper);
                                412             777 :     new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(inherit);
                                413             777 :     new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(createrole);
                                414             777 :     new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(createdb);
                                415             777 :     new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(canlogin);
 3029 alvherre                  416 CBC         777 :     new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(isreplication);
 6461 tgl                       417             777 :     new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
                                418                 : 
 7943 tgl                       419 GIC         777 :     if (password)
                                420                 :     {
                                421                 :         char       *shadow_pass;
  453 michael                   422              51 :         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                 :          */
 2071 heikki.linnakangas        436 CBC          99 :         if (password[0] == '\0' ||
                                437              48 :             plain_crypt_verify(stmt->role, password, "", &logdetail) == STATUS_OK)
                                438                 :         {
                                439               3 :             ereport(NOTICE,
 2071 heikki.linnakangas        440 ECB             :                     (errmsg("empty string is not a valid password, clearing password")));
 2071 heikki.linnakangas        441 GIC           3 :             new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
                                442                 :         }
                                443                 :         else
                                444                 :         {
                                445                 :             /* Encrypt the password to the requested format. */
 2071 heikki.linnakangas        446 CBC          48 :             shadow_pass = encrypt_password(Password_encryption, stmt->role,
                                447                 :                                            password);
                                448              48 :             new_record[Anum_pg_authid_rolpassword - 1] =
 2071 heikki.linnakangas        449 GIC          48 :                 CStringGetTextDatum(shadow_pass);
                                450                 :         }
                                451                 :     }
 7652 tgl                       452 ECB             :     else
 5271 tgl                       453 GIC         726 :         new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
                                454                 : 
 4890                           455             777 :     new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
 4890 tgl                       456 CBC         777 :     new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
 8397 bruce                     457 ECB             : 
 3029 alvherre                  458 GIC         777 :     new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(bypassrls);
                                459                 : 
                                460                 :     /*
                                461                 :      * pg_largeobject_metadata contains pg_authid.oid's, so we use the
                                462                 :      * binary-upgrade override.
 4475 bruce                     463 ECB             :      */
 3149 bruce                     464 GBC         777 :     if (IsBinaryUpgrade)
                                465                 :     {
 3149 bruce                     466 UIC           0 :         if (!OidIsValid(binary_upgrade_next_pg_authid_oid))
                                467               0 :             ereport(ERROR,
                                468                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                469                 :                      errmsg("pg_authid OID value not set when in binary upgrade mode")));
                                470                 : 
 1601 andres                    471               0 :         roleid = binary_upgrade_next_pg_authid_oid;
 4475 bruce                     472               0 :         binary_upgrade_next_pg_authid_oid = InvalidOid;
 4475 bruce                     473 ECB             :     }
 1601 andres                    474                 :     else
                                475                 :     {
 1601 andres                    476 CBC         777 :         roleid = GetNewOidWithIndex(pg_authid_rel, AuthIdOidIndexId,
 1601 andres                    477 ECB             :                                     Anum_pg_authid_oid);
                                478                 :     }
                                479                 : 
 1601 andres                    480 CBC         777 :     new_record[Anum_pg_authid_oid - 1] = ObjectIdGetDatum(roleid);
 1601 andres                    481 ECB             : 
 1601 andres                    482 GIC         777 :     tuple = heap_form_tuple(pg_authid_dsc, new_record, new_record_nulls);
 4475 bruce                     483 ECB             : 
                                484                 :     /*
                                485                 :      * Insert new record in the pg_authid table
 8397                           486                 :      */
 1601 andres                    487 GIC         777 :     CatalogTupleInsert(pg_authid_rel, tuple);
                                488                 : 
                                489                 :     /*
                                490                 :      * Advance command counter so we can see new record; else tests in
                                491                 :      * AddRoleMems may fail.
                                492                 :      */
 6493 tgl                       493             777 :     if (addroleto || adminmembers || rolemembers)
                                494              65 :         CommandCounterIncrement();
                                495                 : 
                                496                 :     /* Default grant. */
  227 rhaas                     497 GNC         777 :     InitGrantRoleOptions(&popt);
                                498                 : 
                                499                 :     /*
                                500                 :      * Add the new role to the specified existing roles.
                                501                 :      */
 1079 rhodiumtoad               502 GIC         777 :     if (addroleto)
 8397 bruce                     503 ECB             :     {
 1079 rhodiumtoad               504 CBC          48 :         RoleSpec   *thisrole = makeNode(RoleSpec);
 1079 rhodiumtoad               505 GIC          48 :         List       *thisrole_list = list_make1(thisrole);
 1079 rhodiumtoad               506 CBC          48 :         List       *thisrole_oidlist = list_make1_oid(roleid);
                                507                 : 
                                508              48 :         thisrole->roletype = ROLESPEC_CSTRING;
 1079 rhodiumtoad               509 GIC          48 :         thisrole->rolename = stmt->role;
                                510              48 :         thisrole->location = -1;
                                511                 : 
                                512              60 :         foreach(item, addroleto)
 1079 rhodiumtoad               513 ECB             :         {
 1079 rhodiumtoad               514 GIC          48 :             RoleSpec   *oldrole = lfirst(item);
 1079 rhodiumtoad               515 CBC          48 :             HeapTuple   oldroletup = get_rolespec_tuple(oldrole);
                                516              48 :             Form_pg_authid oldroleform = (Form_pg_authid) GETSTRUCT(oldroletup);
 1079 rhodiumtoad               517 GIC          48 :             Oid         oldroleid = oldroleform->oid;
                                518              48 :             char       *oldrolename = NameStr(oldroleform->rolname);
                                519                 : 
                                520                 :             /* can only add this role to roles for which you have rights */
   94 rhaas                     521 GNC          48 :             check_role_membership_authorization(currentUserId, oldroleid, true);
                                522              12 :             AddRoleMems(currentUserId, oldrolename, oldroleid,
                                523                 :                         thisrole_list,
 1079 rhodiumtoad               524 ECB             :                         thisrole_oidlist,
                                525                 :                         InvalidOid, &popt);
                                526                 : 
 1079 rhodiumtoad               527 CBC          12 :             ReleaseSysCache(oldroletup);
                                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
                                539                 :      * with different options, since they enjoy ADMIN OPTION on it.
                                540                 :      */
   89 rhaas                     541 GNC         741 :     if (!superuser())
                                542                 :     {
                                543              60 :         RoleSpec   *current_role = makeNode(RoleSpec);
                                544                 :         GrantRoleOptions poptself;
                                545                 :         List       *memberSpecs;
                                546              60 :         List       *memberIds = list_make1_oid(currentUserId);
                                547                 : 
                                548              60 :         current_role->roletype = ROLESPEC_CURRENT_ROLE;
                                549              60 :         current_role->location = -1;
                                550              60 :         memberSpecs = list_make1(current_role);
                                551                 : 
                                552              60 :         poptself.specified = GRANT_ROLE_SPECIFIED_ADMIN
                                553                 :             | GRANT_ROLE_SPECIFIED_INHERIT
                                554                 :             | GRANT_ROLE_SPECIFIED_SET;
                                555              60 :         poptself.admin = true;
                                556              60 :         poptself.inherit = false;
                                557              60 :         poptself.set = false;
                                558                 : 
                                559              60 :         AddRoleMems(BOOTSTRAP_SUPERUSERID, stmt->role, roleid,
                                560                 :                     memberSpecs, memberIds,
                                561                 :                     BOOTSTRAP_SUPERUSERID, &poptself);
                                562                 : 
                                563                 :         /*
                                564                 :          * We must make the implicit grant visible to the code below, else
                                565                 :          * the additional grants will fail.
                                566                 :          */
                                567              60 :         CommandCounterIncrement();
                                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                 :          */
                                578              60 :         if (createrole_self_grant_enabled)
                                579               3 :             AddRoleMems(currentUserId, stmt->role, roleid,
                                580                 :                         memberSpecs, memberIds,
                                581                 :                         currentUserId, &createrole_self_grant_options);
                                582                 :     }
                                583                 : 
                                584                 :     /*
                                585                 :      * Add the specified members to this new role. adminmembers get the admin
 6385 bruce                     586 ECB             :      * option, rolemembers don't.
                                587                 :      *
                                588                 :      * NB: No permissions check is required here. If you have enough rights
                                589                 :      * to create a role, you can add any members you like.
                                590                 :      */
   94 rhaas                     591 GNC         741 :     AddRoleMems(currentUserId, stmt->role, roleid,
                                592                 :                 rolemembers, roleSpecsToIds(rolemembers),
                                593                 :                 InvalidOid, &popt);
  227                           594             738 :     popt.specified |= GRANT_ROLE_SPECIFIED_ADMIN;
                                595             738 :     popt.admin = true;
   94                           596             738 :     AddRoleMems(currentUserId, stmt->role, roleid,
                                597                 :                 adminmembers, roleSpecsToIds(adminmembers),
                                598                 :                 InvalidOid, &popt);
 6494 tgl                       599 EUB             : 
                                600                 :     /* Post creation hook for new role */
 3686 rhaas                     601 GIC         735 :     InvokeObjectPostCreateHook(AuthIdRelationId, roleid, 0);
                                602                 : 
 8604 tgl                       603 ECB             :     /*
                                604                 :      * Close pg_authid, but keep lock till commit.
                                605                 :      */
 1539 andres                    606 GIC         735 :     table_close(pg_authid_rel, NoLock);
 3753 rhaas                     607 ECB             : 
 3753 rhaas                     608 GIC         735 :     return roleid;
 9257 scrappy                   609 ECB             : }
                                610                 : 
                                611                 : 
                                612                 : /*
                                613                 :  * ALTER ROLE
 6466 tgl                       614                 :  *
                                615                 :  * Note: the rolemembers option accepted here is intended to support the
                                616                 :  * backwards-compatible ALTER GROUP syntax.  Although it will work to say
                                617                 :  * "ALTER ROLE role ROLE rolenames", we don't document it.
                                618                 :  */
                                619                 : Oid
  633 dean.a.rasheed            620 CBC         197 : AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
 9173 bruce                     621 ECB             : {
  267 peter                     622 GNC         197 :     Datum       new_record[Natts_pg_authid] = {0};
                                623             197 :     bool        new_record_nulls[Natts_pg_authid] = {0};
                                624             197 :     bool        new_record_repl[Natts_pg_authid] = {0};
                                625                 :     Relation    pg_authid_rel;
                                626                 :     TupleDesc   pg_authid_dsc;
                                627                 :     HeapTuple   tuple,
                                628                 :                 new_tuple;
 2953 alvherre                  629 ECB             :     Form_pg_authid authform;
                                630                 :     ListCell   *option;
  450 peter                     631                 :     char       *rolename;
 6385 bruce                     632 CBC         197 :     char       *password = NULL;    /* user password */
                                633             197 :     int         connlimit = -1; /* maximum connections allowed */
 2118 tgl                       634 GIC         197 :     char       *validUntil = NULL;  /* time the login is valid until */
 2118 tgl                       635 ECB             :     Datum       validUntil_datum;   /* same, as timestamptz Datum */
 4890                           636                 :     bool        validUntil_null;
 7943 tgl                       637 CBC         197 :     DefElem    *dpassword = NULL;
 6493 tgl                       638 GIC         197 :     DefElem    *dissuper = NULL;
 6466 tgl                       639 CBC         197 :     DefElem    *dinherit = NULL;
 6494 tgl                       640 GIC         197 :     DefElem    *dcreaterole = NULL;
 6493 tgl                       641 CBC         197 :     DefElem    *dcreatedb = NULL;
 6494                           642             197 :     DefElem    *dcanlogin = NULL;
 4382 bruce                     643             197 :     DefElem    *disreplication = NULL;
 6461 tgl                       644             197 :     DefElem    *dconnlimit = NULL;
 6494                           645             197 :     DefElem    *drolemembers = NULL;
 6493 tgl                       646 GIC         197 :     DefElem    *dvalidUntil = NULL;
 3124 sfrost                    647             197 :     DefElem    *dbypassRLS = NULL;
 6494 tgl                       648 ECB             :     Oid         roleid;
   94 rhaas                     649 GNC         197 :     Oid         currentUserId = GetUserId();
                                650                 :     GrantRoleOptions    popt;
 7943 tgl                       651 ECB             : 
 2557 sfrost                    652 GIC         197 :     check_rolespec_name(stmt->role,
  193 alvherre                  653             197 :                         _("Cannot alter reserved roles."));
                                654                 : 
                                655                 :     /* Extract options from the statement node tree */
 7836 bruce                     656 CBC         472 :     foreach(option, stmt->options)
                                657                 :     {
 7836 bruce                     658 GIC         275 :         DefElem    *defel = (DefElem *) lfirst(option);
                                659                 : 
 2162 heikki.linnakangas        660             275 :         if (strcmp(defel->defname, "password") == 0)
                                661                 :         {
 7943 tgl                       662              33 :             if (dpassword)
  633 dean.a.rasheed            663 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 7943 tgl                       664 GIC          33 :             dpassword = defel;
                                665                 :         }
 6493                           666             242 :         else if (strcmp(defel->defname, "superuser") == 0)
                                667                 :         {
                                668              37 :             if (dissuper)
  633 dean.a.rasheed            669 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 6493 tgl                       670 CBC          37 :             dissuper = defel;
                                671                 :         }
 6466                           672             205 :         else if (strcmp(defel->defname, "inherit") == 0)
                                673                 :         {
 6466 tgl                       674 GIC          26 :             if (dinherit)
  633 dean.a.rasheed            675 LBC           0 :                 errorConflictingDefElem(defel, pstate);
 6466 tgl                       676 GIC          26 :             dinherit = defel;
 6466 tgl                       677 ECB             :         }
 6494 tgl                       678 CBC         179 :         else if (strcmp(defel->defname, "createrole") == 0)
 7836 bruce                     679 ECB             :         {
 6494 tgl                       680 GIC          17 :             if (dcreaterole)
  633 dean.a.rasheed            681 LBC           0 :                 errorConflictingDefElem(defel, pstate);
 6494 tgl                       682 GIC          17 :             dcreaterole = defel;
                                683                 :         }
 6493 tgl                       684 CBC         162 :         else if (strcmp(defel->defname, "createdb") == 0)
 6494 tgl                       685 ECB             :         {
 6493 tgl                       686 CBC          26 :             if (dcreatedb)
  633 dean.a.rasheed            687 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 6493 tgl                       688 CBC          26 :             dcreatedb = defel;
                                689                 :         }
 6493 tgl                       690 GIC         136 :         else if (strcmp(defel->defname, "canlogin") == 0)
                                691                 :         {
                                692              29 :             if (dcanlogin)
  633 dean.a.rasheed            693 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 6493 tgl                       694 GIC          29 :             dcanlogin = defel;
                                695                 :         }
 4484 magnus                    696 CBC         107 :         else if (strcmp(defel->defname, "isreplication") == 0)
                                697                 :         {
 4484 magnus                    698 GIC          60 :             if (disreplication)
  633 dean.a.rasheed            699 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 4484 magnus                    700 GIC          60 :             disreplication = defel;
                                701                 :         }
 6461 tgl                       702              47 :         else if (strcmp(defel->defname, "connectionlimit") == 0)
                                703                 :         {
                                704               6 :             if (dconnlimit)
  633 dean.a.rasheed            705 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 6461 tgl                       706 GIC           6 :             dconnlimit = defel;
 6461 tgl                       707 ECB             :         }
 6494 tgl                       708 CBC          41 :         else if (strcmp(defel->defname, "rolemembers") == 0 &&
 6494 tgl                       709 GIC          15 :                  stmt->action != 0)
                                710                 :         {
                                711              15 :             if (drolemembers)
  633 dean.a.rasheed            712 UIC           0 :                 errorConflictingDefElem(defel, pstate);
 6494 tgl                       713 GIC          15 :             drolemembers = defel;
                                714                 :         }
 6493                           715              26 :         else if (strcmp(defel->defname, "validUntil") == 0)
                                716                 :         {
 6493 tgl                       717 UIC           0 :             if (dvalidUntil)
  633 dean.a.rasheed            718               0 :                 errorConflictingDefElem(defel, pstate);
 6493 tgl                       719               0 :             dvalidUntil = defel;
 6493 tgl                       720 ECB             :         }
 3124 sfrost                    721 GIC          26 :         else if (strcmp(defel->defname, "bypassrls") == 0)
                                722                 :         {
 3124 sfrost                    723 CBC          26 :             if (dbypassRLS)
  633 dean.a.rasheed            724 LBC           0 :                 errorConflictingDefElem(defel, pstate);
 3124 sfrost                    725 CBC          26 :             dbypassRLS = defel;
                                726                 :         }
                                727                 :         else
 7205 tgl                       728 UIC           0 :             elog(ERROR, "option \"%s\" not recognized",
                                729                 :                  defel->defname);
 7943 tgl                       730 ECB             :     }
                                731                 : 
 6316 peter_e                   732 GIC         197 :     if (dpassword && dpassword->arg)
 6493 tgl                       733              33 :         password = strVal(dpassword->arg);
 6461                           734             197 :     if (dconnlimit)
 5182 heikki.linnakangas        735 ECB             :     {
 6461 tgl                       736 GIC           6 :         connlimit = intVal(dconnlimit->arg);
 5182 heikki.linnakangas        737 CBC           6 :         if (connlimit < -1)
 5182 heikki.linnakangas        738 UIC           0 :             ereport(ERROR,
                                739                 :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                740                 :                      errmsg("invalid connection limit: %d", connlimit)));
                                741                 :     }
 6493 tgl                       742 GIC         197 :     if (dvalidUntil)
 6493 tgl                       743 UIC           0 :         validUntil = strVal(dvalidUntil->arg);
                                744                 : 
                                745                 :     /*
                                746                 :      * Scan the pg_authid relation to be certain the user exists.
                                747                 :      */
 1539 andres                    748 GIC         197 :     pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
 6494 tgl                       749 CBC         197 :     pg_authid_dsc = RelationGetDescr(pg_authid_rel);
                                750                 : 
 2953 alvherre                  751             197 :     tuple = get_rolespec_tuple(stmt->role);
                                752             189 :     authform = (Form_pg_authid) GETSTRUCT(tuple);
                                753             189 :     rolename = pstrdup(NameStr(authform->rolname));
 1601 andres                    754 GIC         189 :     roleid = authform->oid;
                                755                 : 
                                756                 :     /* To mess with a superuser in any way you gotta be superuser. */
   23 peter                     757 GNC         189 :     if (!superuser() && authform->rolsuper)
   75 rhaas                     758 UNC           0 :         ereport(ERROR,
                                759                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                760                 :                  errmsg("permission denied to alter role"),
                                761                 :                  errdetail("Only roles with the %s attribute may alter roles with %s.",
                                762                 :                            "SUPERUSER", "SUPERUSER")));
   23 peter                     763 GNC         189 :     if (!superuser() && dissuper)
                                764               9 :         ereport(ERROR,
                                765                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                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.
   89 rhaas                     773 ECB             :      */
   89 rhaas                     774 GNC         180 :     if (!have_createrole_privilege() ||
                                775             168 :         !is_admin_of_role(GetUserId(), roleid))
 6493 tgl                       776 ECB             :     {
                                777                 :         /* things an unprivileged user certainly can't do */
  450 peter                     778 GIC          15 :         if (dinherit || dcreaterole || dcreatedb || dcanlogin || dconnlimit ||
   75 rhaas                     779 GNC          12 :             dvalidUntil || disreplication || dbypassRLS)
 6493 tgl                       780 GIC           3 :             ereport(ERROR,
 6493 tgl                       781 ECB             :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                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 */
   94 rhaas                     787 GNC          12 :         if (dpassword && roleid != currentUserId)
  230                           788               3 :             ereport(ERROR,
                                789                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                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")));
 6493 tgl                       793 ECB             :     }
   75 rhaas                     794 GNC         165 :     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                 :          */
                                801              30 :         if (dcreatedb && !have_createdb_privilege())
                                802               3 :             ereport(ERROR,
                                803                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                804                 :                      errmsg("permission denied to alter role"),
                                805                 :                      errdetail("Only roles with the %s attribute may change the %s attribute.",
                                806                 :                                "CREATEDB", "CREATEDB")));
                                807              27 :         if (disreplication && !has_rolreplication(currentUserId))
                                808               3 :             ereport(ERROR,
                                809                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                810                 :                      errmsg("permission denied to alter role"),
                                811                 :                      errdetail("Only roles with the %s attribute may change the %s attribute.",
                                812                 :                                "REPLICATION", "REPLICATION")));
                                813              24 :         if (dbypassRLS && !has_bypassrls_privilege(currentUserId))
                                814               3 :             ereport(ERROR,
                                815                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                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 members to a role, you need ADMIN OPTION. */
   89                           822             165 :     if (drolemembers && !is_admin_of_role(currentUserId, roleid))
   89 rhaas                     823 UNC           0 :         ereport(ERROR,
                                824                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                825                 :                  errmsg("permission denied to alter role"),
                                826                 :                  errdetail("Only roles with the %s option on role \"%s\" may add members.",
                                827                 :                            "ADMIN", rolename)));
   89 rhaas                     828 EUB             : 
 4890 tgl                       829 ECB             :     /* Convert validuntil to internal form */
  450 peter                     830 GIC         165 :     if (dvalidUntil)
 4890 tgl                       831 ECB             :     {
 4890 tgl                       832 UIC           0 :         validUntil_datum = DirectFunctionCall3(timestamptz_in,
 4890 tgl                       833 ECB             :                                                CStringGetDatum(validUntil),
 4890 tgl                       834 EUB             :                                                ObjectIdGetDatum(InvalidOid),
 4890 tgl                       835 ECB             :                                                Int32GetDatum(-1));
 4890 tgl                       836 UIC           0 :         validUntil_null = false;
 4890 tgl                       837 ECB             :     }
                                838                 :     else
                                839                 :     {
 4890 tgl                       840 EUB             :         /* fetch existing setting in case hook needs it */
 4890 tgl                       841 CBC         165 :         validUntil_datum = SysCacheGetAttr(AUTHNAME, tuple,
                                842                 :                                            Anum_pg_authid_rolvaliduntil,
 4890 tgl                       843 ECB             :                                            &validUntil_null);
                                844                 :     }
                                845                 : 
 4890 tgl                       846 EUB             :     /*
 4890 tgl                       847 ECB             :      * Call the password checking hook if there is one defined
                                848                 :      */
 4890 tgl                       849 CBC         165 :     if (check_password_hook && password)
 2878 bruce                     850 GIC           6 :         (*check_password_hook) (rolename,
 2878 bruce                     851 ECB             :                                 password,
 2258 heikki.linnakangas        852 EUB             :                                 get_password_type(password),
 2878 bruce                     853 ECB             :                                 validUntil_datum,
                                854                 :                                 validUntil_null);
 4890 tgl                       855                 : 
                                856                 :     /*
 7652                           857                 :      * Build an updated tuple, perusing the information just obtained
 8397 bruce                     858 EUB             :      */
                                859                 : 
 7883 peter_e                   860 ECB             :     /*
 2956 peter_e                   861 EUB             :      * issuper/createrole/etc
 7883 peter_e                   862 ECB             :      */
  450 peter                     863 GIC         161 :     if (dissuper)
 8397 bruce                     864 ECB             :     {
  257 rhaas                     865 GNC          28 :         bool    should_be_super = boolVal(dissuper->arg);
                                866                 : 
                                867              28 :         if (!should_be_super && roleid == BOOTSTRAP_SUPERUSERID)
  257 rhaas                     868 UNC           0 :             ereport(ERROR,
                                869                 :                     (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                870                 :                      errmsg("permission denied to alter role"),
                                871                 :                      errdetail("The bootstrap user must have the %s attribute.",
                                872                 :                                "SUPERUSER")));
                                873                 : 
  257 rhaas                     874 GNC          28 :         new_record[Anum_pg_authid_rolsuper - 1] = BoolGetDatum(should_be_super);
 3029 alvherre                  875 CBC          28 :         new_record_repl[Anum_pg_authid_rolsuper - 1] = true;
 6494 tgl                       876 EUB             :     }
 6494 tgl                       877 ECB             : 
  450 peter                     878 GIC         161 :     if (dinherit)
 6466 tgl                       879 ECB             :     {
  450 peter                     880 CBC          23 :         new_record[Anum_pg_authid_rolinherit - 1] = BoolGetDatum(boolVal(dinherit->arg));
 3029 alvherre                  881 GIC          23 :         new_record_repl[Anum_pg_authid_rolinherit - 1] = true;
 6466 tgl                       882 ECB             :     }
 6466 tgl                       883 EUB             : 
  450 peter                     884 CBC         161 :     if (dcreaterole)
                                885                 :     {
                                886              17 :         new_record[Anum_pg_authid_rolcreaterole - 1] = BoolGetDatum(boolVal(dcreaterole->arg));
 3029 alvherre                  887 GIC          17 :         new_record_repl[Anum_pg_authid_rolcreaterole - 1] = true;
 6494 tgl                       888 EUB             :     }
                                889                 : 
  450 peter                     890 GBC         161 :     if (dcreatedb)
                                891                 :     {
  450 peter                     892 CBC          23 :         new_record[Anum_pg_authid_rolcreatedb - 1] = BoolGetDatum(boolVal(dcreatedb->arg));
 3029 alvherre                  893 GIC          23 :         new_record_repl[Anum_pg_authid_rolcreatedb - 1] = true;
 6494 tgl                       894 ECB             :     }
 6494 tgl                       895 EUB             : 
  450 peter                     896 CBC         161 :     if (dcanlogin)
                                897                 :     {
  450 peter                     898 GIC          26 :         new_record[Anum_pg_authid_rolcanlogin - 1] = BoolGetDatum(boolVal(dcanlogin->arg));
 3029 alvherre                  899 GBC          26 :         new_record_repl[Anum_pg_authid_rolcanlogin - 1] = true;
                                900                 :     }
                                901                 : 
  450 peter                     902 GIC         161 :     if (disreplication)
 4484 magnus                    903 ECB             :     {
  450 peter                     904 CBC          49 :         new_record[Anum_pg_authid_rolreplication - 1] = BoolGetDatum(boolVal(disreplication->arg));
 3029 alvherre                  905              49 :         new_record_repl[Anum_pg_authid_rolreplication - 1] = true;
                                906                 :     }
 4484 magnus                    907 ECB             : 
 6461 tgl                       908 CBC         161 :     if (dconnlimit)
 6461 tgl                       909 EUB             :     {
 6461 tgl                       910 GIC           3 :         new_record[Anum_pg_authid_rolconnlimit - 1] = Int32GetDatum(connlimit);
 5271                           911               3 :         new_record_repl[Anum_pg_authid_rolconnlimit - 1] = true;
                                912                 :     }
 6461 tgl                       913 ECB             : 
 8397 bruce                     914 EUB             :     /* password */
 7943 tgl                       915 GIC         161 :     if (password)
                                916                 :     {
                                917                 :         char       *shadow_pass;
  453 michael                   918              26 :         const char *logdetail = NULL;
 2258 heikki.linnakangas        919 ECB             : 
 2071                           920                 :         /* Like in CREATE USER, don't allow an empty password. */
 2071 heikki.linnakangas        921 GIC          52 :         if (password[0] == '\0' ||
 2071 heikki.linnakangas        922 CBC          26 :             plain_crypt_verify(rolename, password, "", &logdetail) == STATUS_OK)
 2071 heikki.linnakangas        923 ECB             :         {
 2071 heikki.linnakangas        924 CBC           6 :             ereport(NOTICE,
 2071 heikki.linnakangas        925 ECB             :                     (errmsg("empty string is not a valid password, clearing password")));
 2071 heikki.linnakangas        926 GIC           6 :             new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
                                927                 :         }
 2071 heikki.linnakangas        928 ECB             :         else
 2071 heikki.linnakangas        929 EUB             :         {
                                930                 :             /* Encrypt the password to the requested format. */
 2071 heikki.linnakangas        931 GIC          20 :             shadow_pass = encrypt_password(Password_encryption, rolename,
                                932                 :                                            password);
                                933              20 :             new_record[Anum_pg_authid_rolpassword - 1] =
 2071 heikki.linnakangas        934 CBC          20 :                 CStringGetTextDatum(shadow_pass);
 2071 heikki.linnakangas        935 ECB             :         }
 5271 tgl                       936 GIC          26 :         new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
                                937                 :     }
                                938                 : 
                                939                 :     /* unset password */
 6316 peter_e                   940             161 :     if (dpassword && dpassword->arg == NULL)
                                941                 :     {
 5271 tgl                       942 UIC           0 :         new_record_repl[Anum_pg_authid_rolpassword - 1] = true;
                                943               0 :         new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
                                944                 :     }
 6316 peter_e                   945 ECB             : 
 8397 bruce                     946                 :     /* valid until */
 4890 tgl                       947 GIC         161 :     new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
                                948             161 :     new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
 4890 tgl                       949 CBC         161 :     new_record_repl[Anum_pg_authid_rolvaliduntil - 1] = true;
 7709 peter_e                   950 ECB             : 
  450 peter                     951 CBC         161 :     if (dbypassRLS)
                                952                 :     {
  450 peter                     953 GIC          23 :         new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(boolVal(dbypassRLS->arg));
 3029 alvherre                  954              23 :         new_record_repl[Anum_pg_authid_rolbypassrls - 1] = true;
                                955                 :     }
                                956                 : 
 5271 tgl                       957             161 :     new_tuple = heap_modify_tuple(tuple, pg_authid_dsc, new_record,
 5050 bruce                     958 ECB             :                                   new_record_nulls, new_record_repl);
 2259 alvherre                  959 CBC         161 :     CatalogTupleUpdate(pg_authid_rel, &tuple->t_self, new_tuple);
                                960                 : 
 3675 rhaas                     961 GIC         161 :     InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
                                962                 : 
 8179 tgl                       963             161 :     ReleaseSysCache(tuple);
                                964             161 :     heap_freetuple(new_tuple);
 8179 tgl                       965 ECB             : 
  227 rhaas                     966 GNC         161 :     InitGrantRoleOptions(&popt);
                                967                 : 
                                968                 :     /*
                                969                 :      * Advance command counter so we can see new record; else tests in
                                970                 :      * AddRoleMems may fail.
                                971                 :      */
  450 peter                     972 GIC         161 :     if (drolemembers)
                                973                 :     {
  332 tgl                       974 CBC          15 :         List       *rolemembers = (List *) drolemembers->arg;
  450 peter                     975 ECB             : 
 6493 tgl                       976 GIC          15 :         CommandCounterIncrement();
                                977                 : 
  332                           978              15 :         if (stmt->action == +1) /* add members to role */
   94 rhaas                     979 GNC           9 :             AddRoleMems(currentUserId, rolename, roleid,
  450 peter                     980 ECB             :                         rolemembers, roleSpecsToIds(rolemembers),
                                981                 :                         InvalidOid, &popt);
  450 peter                     982 GIC           6 :         else if (stmt->action == -1) /* drop members from role */
   94 rhaas                     983 GNC           6 :             DelRoleMems(currentUserId, rolename, roleid,
                                984                 :                         rolemembers, roleSpecsToIds(rolemembers),
                                985                 :                         InvalidOid, &popt, DROP_RESTRICT);
  450 peter                     986 ECB             :     }
 9173 bruce                     987                 : 
                                988                 :     /*
                                989                 :      * Close pg_authid, but keep lock till commit.
                                990                 :      */
 1539 andres                    991 GIC         161 :     table_close(pg_authid_rel, NoLock);
                                992                 : 
 3753 rhaas                     993             161 :     return roleid;
                                994                 : }
 9257 scrappy                   995 ECB             : 
 9257 scrappy                   996 EUB             : 
                                997                 : /*
                                998                 :  * ALTER ROLE ... SET
                                999                 :  */
                               1000                 : Oid
 6494 tgl                      1001 GIC          46 : AlterRoleSet(AlterRoleSetStmt *stmt)
                               1002                 : {
 4932 alvherre                 1003 ECB             :     HeapTuple   roletuple;
                               1004                 :     Form_pg_authid roleform;
 4932 alvherre                 1005 GBC          46 :     Oid         databaseid = InvalidOid;
 3602 bruce                    1006 GIC          46 :     Oid         roleid = InvalidOid;
                               1007                 : 
 3703 peter_e                  1008              46 :     if (stmt->role)
 6493 tgl                      1009 EUB             :     {
 2557 sfrost                   1010 GIC          42 :         check_rolespec_name(stmt->role,
  193 alvherre                 1011              42 :                             _("Cannot alter reserved roles."));
                               1012                 : 
 2953                          1013              42 :         roletuple = get_rolespec_tuple(stmt->role);
 1601 andres                   1014 CBC          38 :         roleform = (Form_pg_authid) GETSTRUCT(roletuple);
 1601 andres                   1015 GIC          38 :         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                 :          */
                               1021              38 :         shdepLockAndCheckObject(AuthIdRelationId, roleid);
 3703 peter_e                  1022 ECB             : 
                               1023                 :         /*
                               1024                 :          * To mess with a superuser you gotta be superuser; otherwise you
                               1025                 :          * need CREATEROLE plus admin option on the target role; unless you're
                               1026                 :          * just trying to change your own settings
                               1027                 :          */
 1601 andres                   1028 GIC          38 :         if (roleform->rolsuper)
                               1029                 :         {
 3703 peter_e                  1030              14 :             if (!superuser())
 3703 peter_e                  1031 UIC           0 :                 ereport(ERROR,
                               1032                 :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               1033                 :                          errmsg("permission denied to alter role"),
                               1034                 :                          errdetail("Only roles with the %s attribute may alter roles with %s.",
                               1035                 :                                    "SUPERUSER", "SUPERUSER")));
                               1036                 :         }
                               1037                 :         else
                               1038                 :         {
   89 rhaas                    1039 GNC          24 :             if ((!have_createrole_privilege() ||
                               1040              13 :                 !is_admin_of_role(GetUserId(), roleid))
                               1041              11 :                 && roleid != GetUserId())
 3703 peter_e                  1042 UIC           0 :                 ereport(ERROR,
 3703 peter_e                  1043 ECB             :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               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                 :         }
 3703 peter_e                  1048 EUB             : 
 3703 peter_e                  1049 GIC          38 :         ReleaseSysCache(roletuple);
                               1050                 :     }
                               1051                 : 
                               1052                 :     /* look up and lock the database, if specified */
 4932 alvherre                 1053              42 :     if (stmt->database != NULL)
 7709 peter_e                  1054 ECB             :     {
 4630 rhaas                    1055 LBC           0 :         databaseid = get_database_oid(stmt->database, false);
 4932 alvherre                 1056 UIC           0 :         shdepLockAndCheckObject(DatabaseRelationId, databaseid);
                               1057                 : 
 3703 peter_e                  1058 LBC           0 :         if (!stmt->role)
                               1059                 :         {
 3703 peter_e                  1060 ECB             :             /*
                               1061                 :              * If no role is specified, then this is effectively the same as
                               1062                 :              * ALTER DATABASE ... SET, so use the same permission check.
                               1063                 :              */
  147 peter                    1064 UNC           0 :             if (!object_ownercheck(DatabaseRelationId, databaseid, GetUserId()))
 1954 peter_e                  1065 UIC           0 :                 aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_DATABASE,
 3703 peter_e                  1066 LBC           0 :                                stmt->database);
 3703 peter_e                  1067 ECB             :         }
                               1068                 :     }
                               1069                 : 
 3703 peter_e                  1070 CBC          42 :     if (!stmt->role && !stmt->database)
                               1071                 :     {
 3703 peter_e                  1072 ECB             :         /* Must be superuser to alter settings globally. */
 3703 peter_e                  1073 CBC           4 :         if (!superuser())
 3703 peter_e                  1074 UIC           0 :             ereport(ERROR,
                               1075                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               1076                 :                      errmsg("permission denied to alter setting"),
                               1077                 :                      errdetail("Only roles with the %s attribute may alter settings globally.",
                               1078                 :                                "SUPERUSER")));
                               1079                 :     }
 7709 peter_e                  1080 ECB             : 
 3703 peter_e                  1081 CBC          42 :     AlterSetting(databaseid, roleid, stmt->setstmt);
                               1082                 : 
 3753 rhaas                    1083 GIC          38 :     return roleid;
 7709 peter_e                  1084 ECB             : }
                               1085                 : 
                               1086                 : 
 8486                          1087                 : /*
                               1088                 :  * DROP ROLE
                               1089                 :  */
                               1090                 : void
 6494 tgl                      1091 GIC         798 : DropRole(DropRoleStmt *stmt)
 9173 bruce                    1092 ECB             : {
 6385                          1093                 :     Relation    pg_authid_rel,
                               1094                 :                 pg_auth_members_rel;
                               1095                 :     ListCell   *item;
  234 rhaas                    1096 GNC         798 :     List       *role_addresses = NIL;
                               1097                 : 
 3029 alvherre                 1098 CBC         798 :     if (!have_createrole_privilege())
 7205 tgl                      1099 UIC           0 :         ereport(ERROR,
                               1100                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               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                 :     /*
 6493 tgl                      1106 ECB             :      * 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                 :      */
 1539 andres                   1109 CBC         798 :     pg_authid_rel = table_open(AuthIdRelationId, RowExclusiveLock);
 1539 andres                   1110 GIC         798 :     pg_auth_members_rel = table_open(AuthMemRelationId, RowExclusiveLock);
 9173 bruce                    1111 ECB             : 
 6494 tgl                      1112 GIC        1584 :     foreach(item, stmt->roles)
                               1113                 :     {
 2953 alvherre                 1114             841 :         RoleSpec   *rolspec = lfirst(item);
                               1115                 :         char       *role;
 8397 bruce                    1116 ECB             :         HeapTuple   tuple,
                               1117                 :                     tmp_tuple;
 1601 andres                   1118                 :         Form_pg_authid roleform;
 6385 bruce                    1119                 :         ScanKeyData scankey;
                               1120                 :         SysScanDesc sscan;
                               1121                 :         Oid         roleid;
                               1122                 :         ObjectAddress *role_address;
                               1123                 : 
 2953 alvherre                 1124 CBC         841 :         if (rolspec->roletype != ROLESPEC_CSTRING)
 2953 alvherre                 1125 UIC           0 :             ereport(ERROR,
 2953 alvherre                 1126 EUB             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 2118 tgl                      1127                 :                      errmsg("cannot use special role specifier in DROP ROLE")));
 2953 alvherre                 1128 GIC         841 :         role = rolspec->rolename;
                               1129                 : 
 4802 rhaas                    1130             841 :         tuple = SearchSysCache1(AUTHNAME, PointerGetDatum(role));
 8397 bruce                    1131 CBC         841 :         if (!HeapTupleIsValid(tuple))
 6273 andrew                   1132 ECB             :         {
 6273 andrew                   1133 CBC         151 :             if (!stmt->missing_ok)
                               1134                 :             {
                               1135              46 :                 ereport(ERROR,
                               1136                 :                         (errcode(ERRCODE_UNDEFINED_OBJECT),
 6273 andrew                   1137 ECB             :                          errmsg("role \"%s\" does not exist", role)));
                               1138                 :             }
                               1139                 :             else
                               1140                 :             {
 6273 andrew                   1141 CBC         105 :                 ereport(NOTICE,
                               1142                 :                         (errmsg("role \"%s\" does not exist, skipping",
 6273 andrew                   1143 ECB             :                                 role)));
                               1144                 :             }
                               1145                 : 
 6273 andrew                   1146 GIC         105 :             continue;
 6273 andrew                   1147 ECB             :         }
 8397 bruce                    1148                 : 
 1601 andres                   1149 GIC         690 :         roleform = (Form_pg_authid) GETSTRUCT(tuple);
 1601 andres                   1150 CBC         690 :         roleid = roleform->oid;
                               1151                 : 
 6494 tgl                      1152 GIC         690 :         if (roleid == GetUserId())
 7205                          1153               3 :             ereport(ERROR,
                               1154                 :                     (errcode(ERRCODE_OBJECT_IN_USE),
                               1155                 :                      errmsg("current user cannot be dropped")));
 6467 tgl                      1156 CBC         687 :         if (roleid == GetOuterUserId())
 6467 tgl                      1157 UIC           0 :             ereport(ERROR,
 6467 tgl                      1158 ECB             :                     (errcode(ERRCODE_OBJECT_IN_USE),
                               1159                 :                      errmsg("current user cannot be dropped")));
 6494 tgl                      1160 CBC         687 :         if (roleid == GetSessionUserId())
 7205 tgl                      1161 UIC           0 :             ereport(ERROR,
 7205 tgl                      1162 ECB             :                     (errcode(ERRCODE_OBJECT_IN_USE),
 6467                          1163                 :                      errmsg("session user cannot be dropped")));
                               1164                 : 
                               1165                 :         /*
 6493                          1166                 :          * For safety's sake, we allow createrole holders to drop ordinary
                               1167                 :          * roles but not superuser roles, and only if they also have ADMIN
                               1168                 :          * OPTION.
                               1169                 :          */
 1601 andres                   1170 GIC         687 :         if (roleform->rolsuper && !superuser())
 6493 tgl                      1171               3 :             ereport(ERROR,
                               1172                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               1173                 :                      errmsg("permission denied to drop role"),
                               1174                 :                      errdetail("Only roles with the %s attribute may drop roles with %s.",
                               1175                 :                                "SUPERUSER", "SUPERUSER")));
   89 rhaas                    1176 GNC         684 :         if (!is_admin_of_role(GetUserId(), roleid))
                               1177               3 :             ereport(ERROR,
                               1178                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               1179                 :                      errmsg("permission denied to drop role"),
                               1180                 :                      errdetail("Only roles with the %s attribute and the %s option on role \"%s\" may drop this role.",
                               1181                 :                                "CREATEROLE", "ADMIN", NameStr(roleform->rolname))));
                               1182                 : 
 4048 rhaas                    1183 ECB             :         /* DROP hook for the role being removed */
 3686 rhaas                    1184 GIC         681 :         InvokeObjectDropHook(AuthIdRelationId, roleid, 0);
 4048 rhaas                    1185 ECB             : 
                               1186                 :         /* Don't leak the syscache tuple */
  234 rhaas                    1187 GNC         681 :         ReleaseSysCache(tuple);
                               1188                 : 
                               1189                 :         /*
                               1190                 :          * Lock the role, so nobody can add dependencies to her while we drop
                               1191                 :          * her.  We keep the lock until the end of transaction.
                               1192                 :          */
 6485 tgl                      1193 GIC         681 :         LockSharedObject(AuthIdRelationId, roleid, 0, AccessExclusiveLock);
                               1194                 : 
 8397 bruce                    1195 ECB             :         /*
                               1196                 :          * If there is a pg_auth_members entry that has one of the roles to be
                               1197                 :          * dropped as the roleid or member, it should be silently removed, but
                               1198                 :          * if there is a pg_auth_members entry that has one of the roles to be
                               1199                 :          * dropped as the grantor, the operation should fail.
                               1200                 :          *
                               1201                 :          * It's possible, however, that a single pg_auth_members entry could
                               1202                 :          * fall into multiple categories - e.g. the user could do "GRANT foo
                               1203                 :          * TO bar GRANTED BY baz" and then "DROP ROLE baz, bar". We want such
                               1204                 :          * an operation to succeed regardless of the order in which the
                               1205                 :          * to-be-dropped roles are passed to DROP ROLE.
                               1206                 :          *
                               1207                 :          * To make that work, we remove all pg_auth_members entries that can
                               1208                 :          * be silently removed in this loop, and then below we'll make a
                               1209                 :          * second pass over the list of roles to be removed and check for any
                               1210                 :          * remaining dependencies.
                               1211                 :          */
 6493 tgl                      1212 GIC         681 :         ScanKeyInit(&scankey,
                               1213                 :                     Anum_pg_auth_members_roleid,
                               1214                 :                     BTEqualStrategyNumber, F_OIDEQ,
                               1215                 :                     ObjectIdGetDatum(roleid));
                               1216                 : 
 6493 tgl                      1217 CBC         681 :         sscan = systable_beginscan(pg_auth_members_rel, AuthMemRoleMemIndexId,
                               1218                 :                                    true, NULL, 1, &scankey);
 8397 bruce                    1219 ECB             : 
 6493 tgl                      1220 GBC         766 :         while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
                               1221                 :         {
                               1222                 :             Form_pg_auth_members authmem_form;
                               1223                 : 
  234 rhaas                    1224 GNC          85 :             authmem_form = (Form_pg_auth_members) GETSTRUCT(tmp_tuple);
                               1225              85 :             deleteSharedDependencyRecordsFor(AuthMemRelationId,
                               1226                 :                                              authmem_form->oid, 0);
 2258 tgl                      1227 GIC          85 :             CatalogTupleDelete(pg_auth_members_rel, &tmp_tuple->t_self);
                               1228                 :         }
                               1229                 : 
 6493                          1230             681 :         systable_endscan(sscan);
                               1231                 : 
                               1232             681 :         ScanKeyInit(&scankey,
 6493 tgl                      1233 ECB             :                     Anum_pg_auth_members_member,
                               1234                 :                     BTEqualStrategyNumber, F_OIDEQ,
                               1235                 :                     ObjectIdGetDatum(roleid));
 6493 tgl                      1236 EUB             : 
 6493 tgl                      1237 GIC         681 :         sscan = systable_beginscan(pg_auth_members_rel, AuthMemMemRoleIndexId,
                               1238                 :                                    true, NULL, 1, &scankey);
                               1239                 : 
                               1240             804 :         while (HeapTupleIsValid(tmp_tuple = systable_getnext(sscan)))
                               1241                 :         {
                               1242                 :             Form_pg_auth_members authmem_form;
                               1243                 : 
  234 rhaas                    1244 GNC         123 :             authmem_form = (Form_pg_auth_members) GETSTRUCT(tmp_tuple);
                               1245             123 :             deleteSharedDependencyRecordsFor(AuthMemRelationId,
                               1246                 :                                              authmem_form->oid, 0);
 2258 tgl                      1247 GIC         123 :             CatalogTupleDelete(pg_auth_members_rel, &tmp_tuple->t_self);
 6494 tgl                      1248 ECB             :         }
                               1249                 : 
 6493 tgl                      1250 GIC         681 :         systable_endscan(sscan);
                               1251                 : 
 6493 tgl                      1252 EUB             :         /*
 6385 bruce                    1253                 :          * Advance command counter so that later iterations of this loop will
                               1254                 :          * see the changes already made.  This is essential if, for example,
                               1255                 :          * we are trying to drop both a role and one of its direct members ---
                               1256                 :          * we'll get an error if we try to delete the linking pg_auth_members
                               1257                 :          * tuple twice.  (We do not need a CCI between the two delete loops
 6385 bruce                    1258 ECB             :          * above, because it's not allowed for a role to directly contain
                               1259                 :          * itself.)
                               1260                 :          */
 6493 tgl                      1261 CBC         681 :         CommandCounterIncrement();
                               1262                 : 
                               1263                 :         /* Looks tentatively OK, add it to the list. */
  234 rhaas                    1264 GNC         681 :         role_address = palloc(sizeof(ObjectAddress));
                               1265             681 :         role_address->classId = AuthIdRelationId;
                               1266             681 :         role_address->objectId = roleid;
                               1267             681 :         role_address->objectSubId = 0;
                               1268             681 :         role_addresses = lappend(role_addresses, role_address);
                               1269                 :     }
                               1270                 : 
                               1271                 :     /*
                               1272                 :      * Second pass over the roles to be removed.
                               1273                 :      */
                               1274            1362 :     foreach(item, role_addresses)
                               1275                 :     {
                               1276             681 :         ObjectAddress *role_address = lfirst(item);
                               1277             681 :         Oid         roleid = role_address->objectId;
                               1278                 :         HeapTuple   tuple;
                               1279                 :         Form_pg_authid roleform;
                               1280                 :         char       *detail;
                               1281                 :         char       *detail_log;
                               1282                 : 
                               1283                 :         /*
                               1284                 :          * Re-find the pg_authid tuple.
                               1285                 :          *
                               1286                 :          * Since we've taken a lock on the role OID, it shouldn't be possible
                               1287                 :          * for the tuple to have been deleted -- or for that matter updated --
                               1288                 :          * unless the user is manually modifying the system catalogs.
                               1289                 :          */
                               1290             681 :         tuple = SearchSysCache1(AUTHOID, ObjectIdGetDatum(roleid));
                               1291             681 :         if (!HeapTupleIsValid(tuple))
  234 rhaas                    1292 UNC           0 :             elog(ERROR, "could not find tuple for role %u", roleid);
  234 rhaas                    1293 GNC         681 :         roleform = (Form_pg_authid) GETSTRUCT(tuple);
                               1294                 : 
                               1295                 :         /*
                               1296                 :          * Check for pg_shdepend entries depending on this role.
                               1297                 :          *
                               1298                 :          * This needs to happen after we've completed removing any
                               1299                 :          * pg_auth_members entries that can be removed silently, in order to
                               1300                 :          * avoid spurious failures. See notes above for more details.
                               1301                 :          */
                               1302             681 :         if (checkSharedDependencies(AuthIdRelationId, roleid,
                               1303                 :                                     &detail, &detail_log))
                               1304              62 :             ereport(ERROR,
                               1305                 :                     (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
                               1306                 :                      errmsg("role \"%s\" cannot be dropped because some objects depend on it",
                               1307                 :                             NameStr(roleform->rolname)),
                               1308                 :                      errdetail_internal("%s", detail),
                               1309                 :                      errdetail_log("%s", detail_log)));
                               1310                 : 
                               1311                 :         /*
                               1312                 :          * Remove the role from the pg_authid table
                               1313                 :          */
                               1314             619 :         CatalogTupleDelete(pg_authid_rel, &tuple->t_self);
                               1315                 : 
                               1316             619 :         ReleaseSysCache(tuple);
                               1317                 : 
                               1318                 :         /*
                               1319                 :          * Remove any comments or security labels on this role.
                               1320                 :          */
                               1321             619 :         DeleteSharedComments(roleid, AuthIdRelationId);
                               1322             619 :         DeleteSharedSecurityLabel(roleid, AuthIdRelationId);
                               1323                 : 
                               1324                 :         /*
                               1325                 :          * Remove settings for this role.
                               1326                 :          */
                               1327             619 :         DropSetting(InvalidOid, roleid);
 8397 bruce                    1328 EUB             :     }
                               1329                 : 
                               1330                 :     /*
                               1331                 :      * Now we can clean up; but keep locks until commit.
                               1332                 :      */
 1539 andres                   1333 GIC         681 :     table_close(pg_auth_members_rel, NoLock);
                               1334             681 :     table_close(pg_authid_rel, NoLock);
 9257 scrappy                  1335 CBC         681 : }
                               1336                 : 
 7226 peter_e                  1337 ECB             : /*
                               1338                 :  * Rename role
                               1339                 :  */
                               1340                 : ObjectAddress
 6494 tgl                      1341 GIC          15 : RenameRole(const char *oldname, const char *newname)
                               1342                 : {
                               1343                 :     HeapTuple   oldtuple,
                               1344                 :                 newtuple;
 6912 bruce                    1345 ECB             :     TupleDesc   dsc;
                               1346                 :     Relation    rel;
                               1347                 :     Datum       datum;
                               1348                 :     bool        isnull;
                               1349                 :     Datum       repl_val[Natts_pg_authid];
 5271 tgl                      1350                 :     bool        repl_null[Natts_pg_authid];
                               1351                 :     bool        repl_repl[Natts_pg_authid];
 6912 bruce                    1352                 :     int         i;
 6494 tgl                      1353 EUB             :     Oid         roleid;
                               1354                 :     ObjectAddress address;
                               1355                 :     Form_pg_authid authform;
                               1356                 : 
 1539 andres                   1357 GIC          15 :     rel = table_open(AuthIdRelationId, RowExclusiveLock);
 6912 bruce                    1358              15 :     dsc = RelationGetDescr(rel);
                               1359                 : 
 4802 rhaas                    1360              15 :     oldtuple = SearchSysCache1(AUTHNAME, CStringGetDatum(oldname));
 6912 bruce                    1361              15 :     if (!HeapTupleIsValid(oldtuple))
 7226 peter_e                  1362 UIC           0 :         ereport(ERROR,
 7205 tgl                      1363 ECB             :                 (errcode(ERRCODE_UNDEFINED_OBJECT),
 6494                          1364                 :                  errmsg("role \"%s\" does not exist", oldname)));
                               1365                 : 
 7226 peter_e                  1366                 :     /*
                               1367                 :      * XXX Client applications probably store the session user somewhere, so
 6385 bruce                    1368                 :      * renaming it could cause confusion.  On the other hand, there may not be
                               1369                 :      * an actual problem besides a little confusion, so think about this and
                               1370                 :      * decide.  Same for SET ROLE ... we don't restrict renaming the current
                               1371                 :      * effective userid, though.
                               1372                 :      */
                               1373                 : 
 2557 sfrost                   1374 GIC          15 :     authform = (Form_pg_authid) GETSTRUCT(oldtuple);
 1601 andres                   1375              15 :     roleid = authform->oid;
                               1376                 : 
 6494 tgl                      1377              15 :     if (roleid == GetSessionUserId())
 7226 peter_e                  1378 LBC           0 :         ereport(ERROR,
 7205 tgl                      1379 EUB             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                               1380                 :                  errmsg("session user cannot be renamed")));
 6467 tgl                      1381 GIC          15 :     if (roleid == GetOuterUserId())
 6467 tgl                      1382 LBC           0 :         ereport(ERROR,
                               1383                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 5911 bruce                    1384 ECB             :                  errmsg("current user cannot be renamed")));
 7226 peter_e                  1385                 : 
                               1386                 :     /*
 2495 rhaas                    1387                 :      * Check that the user is not trying to rename a system role and not
                               1388                 :      * trying to rename a role into the reserved "pg_" namespace.
 2557 sfrost                   1389                 :      */
 2557 sfrost                   1390 GIC          15 :     if (IsReservedName(NameStr(authform->rolname)))
 2557 sfrost                   1391 UIC           0 :         ereport(ERROR,
                               1392                 :                 (errcode(ERRCODE_RESERVED_NAME),
                               1393                 :                  errmsg("role name \"%s\" is reserved",
                               1394                 :                         NameStr(authform->rolname)),
 2118 tgl                      1395 ECB             :                  errdetail("Role names starting with \"pg_\" are reserved.")));
                               1396                 : 
 2557 sfrost                   1397 GIC          15 :     if (IsReservedName(newname))
 2557 sfrost                   1398 UIC           0 :         ereport(ERROR,
                               1399                 :                 (errcode(ERRCODE_RESERVED_NAME),
 2557 sfrost                   1400 ECB             :                  errmsg("role name \"%s\" is reserved",
                               1401                 :                         newname),
                               1402                 :                  errdetail("Role names starting with \"pg_\" are reserved.")));
                               1403                 : 
 1380 tgl                      1404                 :     /*
                               1405                 :      * If built with appropriate switch, whine when regression-testing
                               1406                 :      * conventions for role names are violated.
                               1407                 :      */
                               1408                 : #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
                               1409                 :     if (strncmp(newname, "regress_", 8) != 0)
                               1410                 :         elog(WARNING, "roles created by regression test cases should have names starting with \"regress_\"");
 1380 tgl                      1411 EUB             : #endif
                               1412                 : 
                               1413                 :     /* make sure the new name doesn't exist */
 4802 rhaas                    1414 CBC          15 :     if (SearchSysCacheExists1(AUTHNAME, CStringGetDatum(newname)))
 7226 peter_e                  1415 UBC           0 :         ereport(ERROR,
                               1416                 :                 (errcode(ERRCODE_DUPLICATE_OBJECT),
                               1417                 :                  errmsg("role \"%s\" already exists", newname)));
                               1418                 : 
                               1419                 :     /*
                               1420                 :      * Only superusers can mess with superusers. Otherwise, a user with
                               1421                 :      * CREATEROLE can rename a role for which they have ADMIN OPTION.
                               1422                 :      */
   24 peter                    1423 GNC          15 :     if (authform->rolsuper)
                               1424                 :     {
 6493 tgl                      1425 CBC           3 :         if (!superuser())
 6493 tgl                      1426 LBC           0 :             ereport(ERROR,
                               1427                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               1428                 :                      errmsg("permission denied to rename role"),
                               1429                 :                      errdetail("Only roles with the %s attribute may rename roles with %s.",
                               1430                 :                                "SUPERUSER", "SUPERUSER")));
                               1431                 :     }
                               1432                 :     else
 6493 tgl                      1433 ECB             :     {
   89 rhaas                    1434 GNC          12 :         if (!have_createrole_privilege() ||
                               1435              12 :             !is_admin_of_role(GetUserId(), roleid))
 6493 tgl                      1436 GIC           3 :             ereport(ERROR,
                               1437                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               1438                 :                      errmsg("permission denied to rename role"),
                               1439                 :                      errdetail("Only roles with the %s attribute and the %s option on role \"%s\" may rename this role.",
                               1440                 :                                "CREATEROLE", "ADMIN", NameStr(authform->rolname))));
                               1441                 :     }
                               1442                 : 
                               1443                 :     /* OK, construct the modified tuple */
 6494 tgl                      1444 CBC         156 :     for (i = 0; i < Natts_pg_authid; i++)
 5271 tgl                      1445 GIC         144 :         repl_repl[i] = false;
                               1446                 : 
 5271 tgl                      1447 CBC          12 :     repl_repl[Anum_pg_authid_rolname - 1] = true;
 6494 tgl                      1448 GIC          12 :     repl_val[Anum_pg_authid_rolname - 1] = DirectFunctionCall1(namein,
                               1449                 :                                                                CStringGetDatum(newname));
 5271                          1450              12 :     repl_null[Anum_pg_authid_rolname - 1] = false;
                               1451                 : 
 6494                          1452              12 :     datum = heap_getattr(oldtuple, Anum_pg_authid_rolpassword, dsc, &isnull);
 6912 bruce                    1453 ECB             : 
 2258 heikki.linnakangas       1454 GIC          12 :     if (!isnull && get_password_type(TextDatumGetCString(datum)) == PASSWORD_TYPE_MD5)
                               1455                 :     {
                               1456                 :         /* MD5 uses the username as salt, so just clear it on a rename */
 5271 tgl                      1457               3 :         repl_repl[Anum_pg_authid_rolpassword - 1] = true;
                               1458               3 :         repl_null[Anum_pg_authid_rolpassword - 1] = true;
                               1459                 : 
 6912 bruce                    1460               3 :         ereport(NOTICE,
                               1461                 :                 (errmsg("MD5 password cleared because of role rename")));
                               1462                 :     }
                               1463                 : 
 5271 tgl                      1464              12 :     newtuple = heap_modify_tuple(oldtuple, dsc, repl_val, repl_null, repl_repl);
 2259 alvherre                 1465              12 :     CatalogTupleUpdate(rel, &oldtuple->t_self, newtuple);
                               1466                 : 
 3675 rhaas                    1467              12 :     InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
                               1468                 : 
 2959 alvherre                 1469              12 :     ObjectAddressSet(address, AuthIdRelationId, roleid);
                               1470                 : 
 6912 bruce                    1471              12 :     ReleaseSysCache(oldtuple);
 6184 tgl                      1472 ECB             : 
                               1473                 :     /*
                               1474                 :      * Close pg_authid, but keep lock till commit.
                               1475                 :      */
 1539 andres                   1476 GIC          12 :     table_close(rel, NoLock);
 3759 rhaas                    1477 ECB             : 
 2959 alvherre                 1478 GIC          12 :     return address;
                               1479                 : }
 7226 peter_e                  1480 ECB             : 
                               1481                 : /*
                               1482                 :  * GrantRoleStmt
                               1483                 :  *
 6494 tgl                      1484                 :  * Grant/Revoke roles to/from roles
 8486 peter_e                  1485                 :  */
                               1486                 : void
  227 rhaas                    1487 GNC        1175 : GrantRole(ParseState *pstate, GrantRoleStmt *stmt)
                               1488                 : {
                               1489                 :     Relation    pg_authid_rel;
 6494 tgl                      1490 ECB             :     Oid         grantor;
                               1491                 :     List       *grantee_ids;
 6892 neilc                    1492                 :     ListCell   *item;
                               1493                 :     GrantRoleOptions    popt;
   94 rhaas                    1494 GNC        1175 :     Oid         currentUserId = GetUserId();
                               1495                 : 
                               1496                 :     /* Parse options list. */
  227                          1497            1175 :     InitGrantRoleOptions(&popt);
                               1498            1281 :     foreach(item, stmt->opt)
                               1499                 :     {
                               1500             106 :         DefElem    *opt = (DefElem *) lfirst(item);
                               1501             106 :         char       *optval = defGetString(opt);
                               1502                 : 
                               1503             106 :         if (strcmp(opt->defname, "admin") == 0)
                               1504                 :         {
                               1505              64 :             popt.specified |= GRANT_ROLE_SPECIFIED_ADMIN;
                               1506                 : 
                               1507              64 :             if (parse_bool(optval, &popt.admin))
                               1508              64 :                 continue;
                               1509                 :         }
                               1510              42 :         else if (strcmp(opt->defname, "inherit") == 0)
                               1511                 :         {
                               1512              24 :             popt.specified |= GRANT_ROLE_SPECIFIED_INHERIT;
                               1513              24 :             if (parse_bool(optval, &popt.inherit))
                               1514              24 :                 continue;
                               1515                 :         }
  142                          1516              18 :         else if (strcmp(opt->defname, "set") == 0)
                               1517                 :         {
                               1518              18 :             popt.specified |= GRANT_ROLE_SPECIFIED_SET;
                               1519              18 :             if (parse_bool(optval, &popt.set))
                               1520              18 :                 continue;
                               1521                 :         }
                               1522                 :         else
  227 rhaas                    1523 UNC           0 :             ereport(ERROR,
                               1524                 :                     errcode(ERRCODE_SYNTAX_ERROR),
                               1525                 :                     errmsg("unrecognized role option \"%s\"", opt->defname),
                               1526                 :                     parser_errposition(pstate, opt->location));
                               1527                 : 
                               1528               0 :         ereport(ERROR,
                               1529                 :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                               1530                 :                  errmsg("unrecognized value for role option \"%s\": \"%s\"",
                               1531                 :                         opt->defname, optval),
                               1532                 :                  parser_errposition(pstate, opt->location)));
                               1533                 :     }
                               1534                 : 
                               1535                 :     /* Lookup OID of grantor, if specified. */
 6494 tgl                      1536 GIC        1175 :     if (stmt->grantor)
 2953 alvherre                 1537              39 :         grantor = get_rolespec_oid(stmt->grantor, false);
                               1538                 :     else
  230 rhaas                    1539 GNC        1136 :         grantor = InvalidOid;
                               1540                 : 
 2953 alvherre                 1541 GIC        1172 :     grantee_ids = roleSpecsToIds(stmt->grantee_roles);
 8515 bruce                    1542 ECB             : 
                               1543                 :     /* AccessShareLock is enough since we aren't modifying pg_authid */
 1539 andres                   1544 GIC        1172 :     pg_authid_rel = table_open(AuthIdRelationId, AccessShareLock);
                               1545                 : 
 8515 bruce                    1546 ECB             :     /*
                               1547                 :      * Step through all of the granted roles and add, update, or remove
                               1548                 :      * entries in pg_auth_members as appropriate. If stmt->is_grant is true,
                               1549                 :      * we are adding new grants or, if they already exist, updating options
                               1550                 :      * on those grants. If stmt->is_grant is false, we are revoking grants or
                               1551                 :      * removing options from them.
 7475 tgl                      1552                 :      */
 6494 tgl                      1553 GIC        2285 :     foreach(item, stmt->granted_roles)
                               1554                 :     {
 5190                          1555            1173 :         AccessPriv *priv = (AccessPriv *) lfirst(item);
                               1556            1173 :         char       *rolename = priv->priv_name;
                               1557                 :         Oid         roleid;
                               1558                 : 
                               1559                 :         /* Must reject priv(columns) and ALL PRIVILEGES(columns) */
                               1560            1173 :         if (rolename == NULL || priv->cols != NIL)
 5190 tgl                      1561 UIC           0 :             ereport(ERROR,
                               1562                 :                     (errcode(ERRCODE_INVALID_GRANT_OPERATION),
 2118 tgl                      1563 ECB             :                      errmsg("column names cannot be included in GRANT/REVOKE ROLE")));
                               1564                 : 
 4630 rhaas                    1565 GIC        1173 :         roleid = get_role_oid(rolename, false);
   94 rhaas                    1566 GNC        1173 :         check_role_membership_authorization(currentUserId,
                               1567            1173 :                                             roleid, stmt->is_grant);
 6494 tgl                      1568 CBC        1128 :         if (stmt->is_grant)
   94 rhaas                    1569 GNC        1052 :             AddRoleMems(currentUserId, rolename, roleid,
 6494 tgl                      1570 ECB             :                         stmt->grantee_roles, grantee_ids,
                               1571                 :                         grantor, &popt);
 8397 bruce                    1572                 :         else
   94 rhaas                    1573 GNC          76 :             DelRoleMems(currentUserId, rolename, roleid,
                               1574                 :                         stmt->grantee_roles, grantee_ids,
                               1575                 :                         grantor, &popt, stmt->behavior);
                               1576                 :     }
                               1577                 : 
 6184 tgl                      1578 ECB             :     /*
                               1579                 :      * Close pg_authid, but keep lock till commit.
                               1580                 :      */
 1539 andres                   1581 CBC        1112 :     table_close(pg_authid_rel, NoLock);
 6494 tgl                      1582 GIC        1112 : }
                               1583                 : 
                               1584                 : /*
                               1585                 :  * DropOwnedObjects
                               1586                 :  *
                               1587                 :  * Drop the objects owned by a given list of roles.
                               1588                 :  */
                               1589                 : void
 6031 bruce                    1590              69 : DropOwnedObjects(DropOwnedStmt *stmt)
                               1591                 : {
 2953 alvherre                 1592              69 :     List       *role_ids = roleSpecsToIds(stmt->roles);
                               1593                 :     ListCell   *cell;
 6348 alvherre                 1594 ECB             : 
                               1595                 :     /* Check privileges */
 6347 bruce                    1596 GBC         147 :     foreach(cell, role_ids)
 6348 alvherre                 1597 ECB             :     {
 6347 bruce                    1598 GIC          84 :         Oid         roleid = lfirst_oid(cell);
                               1599                 : 
 6348 alvherre                 1600              84 :         if (!has_privs_of_role(GetUserId(), roleid))
                               1601               6 :             ereport(ERROR,
                               1602                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               1603                 :                      errmsg("permission denied to drop objects"),
                               1604                 :                      errdetail("Only roles with privileges of role \"%s\" may drop objects owned by it.",
                               1605                 :                                GetUserNameFromId(roleid, false))));
                               1606                 :     }
                               1607                 : 
 6348 alvherre                 1608 ECB             :     /* Ok, do it */
 6348 alvherre                 1609 GIC          63 :     shdepDropOwned(role_ids, stmt->behavior);
 6348 alvherre                 1610 CBC          60 : }
                               1611                 : 
                               1612                 : /*
                               1613                 :  * ReassignOwnedObjects
                               1614                 :  *
                               1615                 :  * Give the objects owned by a given list of roles away to another user.
                               1616                 :  */
                               1617                 : void
 6031 bruce                    1618 GIC          19 : ReassignOwnedObjects(ReassignOwnedStmt *stmt)
                               1619                 : {
 2953 alvherre                 1620 CBC          19 :     List       *role_ids = roleSpecsToIds(stmt->roles);
                               1621                 :     ListCell   *cell;
 6348 alvherre                 1622 ECB             :     Oid         newrole;
                               1623                 : 
                               1624                 :     /* Check privileges */
 6347 bruce                    1625 GIC          32 :     foreach(cell, role_ids)
                               1626                 :     {
 6347 bruce                    1627 CBC          19 :         Oid         roleid = lfirst_oid(cell);
 6348 alvherre                 1628 ECB             : 
 6348 alvherre                 1629 GIC          19 :         if (!has_privs_of_role(GetUserId(), roleid))
                               1630               6 :             ereport(ERROR,
                               1631                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               1632                 :                      errmsg("permission denied to reassign objects"),
                               1633                 :                      errdetail("Only roles with privileges of role \"%s\" may reassign objects owned by it.",
                               1634                 :                                GetUserNameFromId(roleid, false))));
 6348 alvherre                 1635 ECB             :     }
                               1636                 : 
                               1637                 :     /* Must have privileges on the receiving side too */
 2953 alvherre                 1638 GIC          13 :     newrole = get_rolespec_oid(stmt->newrole, false);
                               1639                 : 
 6348                          1640              13 :     if (!has_privs_of_role(GetUserId(), newrole))
 6347 bruce                    1641 CBC           3 :         ereport(ERROR,
 6347 bruce                    1642 ECB             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               1643                 :                  errmsg("permission denied to reassign objects"),
                               1644                 :                  errdetail("Only roles with privileges of role \"%s\" may reassign objects to it.",
                               1645                 :                            GetUserNameFromId(newrole, false))));
                               1646                 : 
                               1647                 :     /* Ok, do it */
 6348 alvherre                 1648 GIC          10 :     shdepReassignOwned(role_ids, newrole);
                               1649              10 : }
                               1650                 : 
 6494 tgl                      1651 ECB             : /*
                               1652                 :  * roleSpecsToIds
                               1653                 :  *
                               1654                 :  * Given a list of RoleSpecs, generate a list of role OIDs in the same order.
                               1655                 :  *
                               1656                 :  * ROLESPEC_PUBLIC is not allowed.
                               1657                 :  */
                               1658                 : List *
 2953 alvherre                 1659 GIC        2769 : roleSpecsToIds(List *memberNames)
                               1660                 : {
 6494 tgl                      1661            2769 :     List       *result = NIL;
                               1662                 :     ListCell   *l;
                               1663                 : 
                               1664            4123 :     foreach(l, memberNames)
                               1665                 :     {
 2190                          1666            1354 :         RoleSpec   *rolespec = lfirst_node(RoleSpec, l);
 2878 bruce                    1667 ECB             :         Oid         roleid;
 8397                          1668                 : 
 2953 alvherre                 1669 GIC        1354 :         roleid = get_rolespec_oid(rolespec, false);
 6494 tgl                      1670 CBC        1354 :         result = lappend_oid(result, roleid);
 8397 bruce                    1671 ECB             :     }
 6494 tgl                      1672 GBC        2769 :     return result;
                               1673                 : }
                               1674                 : 
                               1675                 : /*
                               1676                 :  * AddRoleMems -- Add given members to the specified role
                               1677                 :  *
                               1678                 :  * currentUserId: OID of role performing the operation
                               1679                 :  * rolename: name of role to add to (used only for error messages)
                               1680                 :  * roleid: OID of role to add to
                               1681                 :  * memberSpecs: list of RoleSpec of roles to add (used only for error messages)
                               1682                 :  * memberIds: OIDs of roles to add
                               1683                 :  * grantorId: OID that should be recorded as having granted the membership
                               1684                 :  * (InvalidOid if not set explicitly)
                               1685                 :  * popt: information about grant options
 8486 peter_e                  1686 ECB             :  */
 6494 tgl                      1687                 : static void
   94 rhaas                    1688 GNC        2615 : AddRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
 2953 alvherre                 1689 ECB             :             List *memberSpecs, List *memberIds,
                               1690                 :             Oid grantorId, GrantRoleOptions *popt)
                               1691                 : {
                               1692                 :     Relation    pg_authmem_rel;
 6494 tgl                      1693                 :     TupleDesc   pg_authmem_dsc;
 2953 alvherre                 1694 EUB             :     ListCell   *specitem;
                               1695                 :     ListCell   *iditem;
                               1696                 : 
 2953 alvherre                 1697 GIC        2615 :     Assert(list_length(memberSpecs) == list_length(memberIds));
                               1698                 : 
                               1699                 :     /* Validate grantor (and resolve implicit grantor if not specified). */
  230 rhaas                    1700 GNC        2615 :     grantorId = check_role_grantor(currentUserId, roleid, grantorId, true);
                               1701                 : 
 1539 andres                   1702 CBC        2612 :     pg_authmem_rel = table_open(AuthMemRelationId, RowExclusiveLock);
 6494 tgl                      1703            2612 :     pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
 8179 tgl                      1704 ECB             : 
                               1705                 :     /*
                               1706                 :      * Only allow changes to this role by one backend at a time, so that we
                               1707                 :      * can check integrity constraints like the lack of circular ADMIN OPTION
                               1708                 :      * grants without fear of race conditions.
                               1709                 :      */
  230 rhaas                    1710 GNC        2612 :     LockSharedObject(AuthIdRelationId, roleid, 0,
                               1711                 :                      ShareUpdateExclusiveLock);
                               1712                 : 
                               1713                 :     /* Preliminary sanity checks. */
 2953 alvherre                 1714 GIC        3800 :     forboth(specitem, memberSpecs, iditem, memberIds)
                               1715                 :     {
 1079 rhodiumtoad              1716            1197 :         RoleSpec   *memberRole = lfirst_node(RoleSpec, specitem);
 6494 tgl                      1717            1197 :         Oid         memberid = lfirst_oid(iditem);
                               1718                 : 
  744 noah                     1719 ECB             :         /*
                               1720                 :          * pg_database_owner is never a role member.  Lifting this restriction
                               1721                 :          * would require a policy decision about membership loops.  One could
                               1722                 :          * prevent loops, which would include making "ALTER DATABASE x OWNER
                               1723                 :          * TO proposed_datdba" fail if is_member_of_role(pg_database_owner,
                               1724                 :          * proposed_datdba).  Hence, gaining a membership could reduce what a
                               1725                 :          * role could do.  Alternately, one could allow these memberships to
                               1726                 :          * complete loops.  A role could then have actual WITH ADMIN OPTION on
                               1727                 :          * itself, prompting a decision about is_admin_of_role() treatment of
                               1728                 :          * the case.
                               1729                 :          *
                               1730                 :          * Lifting this restriction also has policy implications for ownership
                               1731                 :          * of shared objects (databases and tablespaces).  We allow such
                               1732                 :          * ownership, but we might find cause to ban it in the future.
                               1733                 :          * Designing such a ban would more troublesome if the design had to
                               1734                 :          * address pg_database_owner being a member of role FOO that owns a
                               1735                 :          * shared object.  (The effect of such ownership is that any owner of
                               1736                 :          * another database can act as the owner of affected shared objects.)
                               1737                 :          */
  729 noah                     1738 GIC        1197 :         if (memberid == ROLE_PG_DATABASE_OWNER)
  744 noah                     1739 CBC           3 :             ereport(ERROR,
                               1740                 :                     errmsg("role \"%s\" cannot be a member of any role",
  744 noah                     1741 ECB             :                            get_rolespec_name(memberRole)));
                               1742                 : 
 6493 tgl                      1743                 :         /*
                               1744                 :          * Refuse creation of membership loops, including the trivial case
                               1745                 :          * where a role is made a member of itself.  We do this by checking to
                               1746                 :          * see if the target role is already a member of the proposed member
                               1747                 :          * role.  We have to ignore possible superuserness, however, else we
 6365                          1748                 :          * could never grant membership in a superuser-privileged role.
                               1749                 :          */
 6365 tgl                      1750 CBC        1194 :         if (is_member_of_role_nosuper(roleid, memberid))
 6493 tgl                      1751 GIC           6 :             ereport(ERROR,
                               1752                 :                     (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                               1753                 :                      errmsg("role \"%s\" is a member of role \"%s\"",
                               1754                 :                             rolename, get_rolespec_name(memberRole))));
                               1755                 :     }
                               1756                 : 
                               1757                 :     /*
                               1758                 :      * Disallow attempts to grant ADMIN OPTION back to a user who granted it
                               1759                 :      * to you, similar to what check_circularity does for ACLs. We want the
                               1760                 :      * chains of grants to remain acyclic, so that it's always possible to use
                               1761                 :      * REVOKE .. CASCADE to clean up all grants that depend on the one being
                               1762                 :      * revoked.
                               1763                 :      *
                               1764                 :      * NB: This check might look redundant with the check for membership loops
                               1765                 :      * above, but it isn't. That's checking for role-member loop (e.g. A is a
                               1766                 :      * member of B and B is a member of A) while this is checking for a
                               1767                 :      * member-grantor loop (e.g. A gave ADMIN OPTION on X to B and now B, who
                               1768                 :      * has no other source of ADMIN OPTION on X, tries to give ADMIN OPTION on
                               1769                 :      * X back to A).
                               1770                 :      */
  227 rhaas                    1771 GNC        2603 :     if (popt->admin && grantorId != BOOTSTRAP_SUPERUSERID)
                               1772                 :     {
                               1773                 :         CatCList   *memlist;
                               1774                 :         RevokeRoleGrantAction *actions;
                               1775                 :         int         i;
                               1776                 : 
                               1777                 :         /* Get the list of members for this role. */
  230                          1778              63 :         memlist = SearchSysCacheList1(AUTHMEMROLEMEM,
                               1779                 :                                       ObjectIdGetDatum(roleid));
                               1780                 : 
                               1781                 :         /*
                               1782                 :          * Figure out what would happen if we removed all existing grants to
                               1783                 :          * every role to which we've been asked to make a new grant.
  230 rhaas                    1784 ECB             :          */
  230 rhaas                    1785 GNC          63 :         actions = initialize_revoke_actions(memlist);
                               1786              96 :         foreach(iditem, memberIds)
  230 rhaas                    1787 ECB             :         {
  230 rhaas                    1788 GNC          33 :             Oid         memberid = lfirst_oid(iditem);
                               1789                 : 
                               1790              33 :             if (memberid == BOOTSTRAP_SUPERUSERID)
  230 rhaas                    1791 UNC           0 :                 ereport(ERROR,
                               1792                 :                         (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                               1793                 :                          errmsg("%s option cannot be granted back to your own grantor",
                               1794                 :                                 "ADMIN")));
  230 rhaas                    1795 GNC          33 :             plan_member_revoke(memlist, actions, memberid);
  230 rhaas                    1796 ECB             :         }
                               1797                 : 
                               1798                 :         /*
                               1799                 :          * If the result would be that the grantor role would no longer have
                               1800                 :          * the ability to perform the grant, then the proposed grant would
                               1801                 :          * create a circularity.
                               1802                 :          */
  230 rhaas                    1803 GNC          75 :         for (i = 0; i < memlist->n_members; ++i)
                               1804                 :         {
                               1805                 :             HeapTuple   authmem_tuple;
                               1806                 :             Form_pg_auth_members authmem_form;
                               1807                 : 
                               1808              72 :             authmem_tuple = &memlist->members[i]->tuple;
                               1809              72 :             authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
                               1810                 : 
                               1811              72 :             if (actions[i] == RRG_NOOP &&
                               1812              66 :                 authmem_form->member == grantorId &&
                               1813              60 :                 authmem_form->admin_option)
                               1814              60 :                 break;
                               1815                 :         }
                               1816              63 :         if (i >= memlist->n_members)
                               1817               3 :             ereport(ERROR,
                               1818                 :                     (errcode(ERRCODE_INVALID_GRANT_OPERATION),
                               1819                 :                      errmsg("%s option cannot be granted back to your own grantor",
                               1820                 :                             "ADMIN")));
                               1821                 : 
                               1822              60 :         ReleaseSysCacheList(memlist);
                               1823                 :     }
                               1824                 : 
                               1825                 :     /* Now perform the catalog updates. */
                               1826            3785 :     forboth(specitem, memberSpecs, iditem, memberIds)
                               1827                 :     {
                               1828            1185 :         RoleSpec   *memberRole = lfirst_node(RoleSpec, specitem);
                               1829            1185 :         Oid         memberid = lfirst_oid(iditem);
                               1830                 :         HeapTuple   authmem_tuple;
                               1831                 :         HeapTuple   tuple;
                               1832            1185 :         Datum       new_record[Natts_pg_auth_members] = {0};
                               1833            1185 :         bool        new_record_nulls[Natts_pg_auth_members] = {0};
                               1834            1185 :         bool        new_record_repl[Natts_pg_auth_members] = {0};
                               1835                 : 
                               1836                 :         /* Common initialization for possible insert or update */
  227                          1837            1185 :         new_record[Anum_pg_auth_members_roleid - 1] =
                               1838            1185 :             ObjectIdGetDatum(roleid);
                               1839            1185 :         new_record[Anum_pg_auth_members_member - 1] =
                               1840            1185 :             ObjectIdGetDatum(memberid);
                               1841            1185 :         new_record[Anum_pg_auth_members_grantor - 1] =
                               1842            1185 :             ObjectIdGetDatum(grantorId);
                               1843                 : 
                               1844                 :         /* Find any existing tuple */
  230                          1845            1185 :         authmem_tuple = SearchSysCache3(AUTHMEMROLEMEM,
                               1846                 :                                         ObjectIdGetDatum(roleid),
                               1847                 :                                         ObjectIdGetDatum(memberid),
                               1848                 :                                         ObjectIdGetDatum(grantorId));
                               1849                 : 
                               1850                 :         /*
                               1851                 :          * If we found a tuple, update it with new option values, unless
                               1852                 :          * there are no changes, in which case issue a WARNING.
                               1853                 :          *
                               1854                 :          * If we didn't find a tuple, just insert one.
                               1855                 :          */
  227 rhaas                    1856 CBC        1185 :         if (HeapTupleIsValid(authmem_tuple))
  234 rhaas                    1857 ECB             :         {
                               1858                 :             Form_pg_auth_members authmem_form;
  227 rhaas                    1859 GNC          16 :             bool        at_least_one_change = false;
                               1860                 : 
  234                          1861              16 :             authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
                               1862                 : 
  227                          1863              16 :             if ((popt->specified & GRANT_ROLE_SPECIFIED_ADMIN) != 0
  227 rhaas                    1864 UNC           0 :                 && authmem_form->admin_option != popt->admin)
                               1865                 :             {
                               1866               0 :                 new_record[Anum_pg_auth_members_admin_option - 1] =
                               1867               0 :                     BoolGetDatum(popt->admin);
                               1868               0 :                 new_record_repl[Anum_pg_auth_members_admin_option - 1] =
                               1869                 :                     true;
                               1870               0 :                 at_least_one_change = true;
                               1871                 :             }
                               1872                 : 
  227 rhaas                    1873 GNC          16 :             if ((popt->specified & GRANT_ROLE_SPECIFIED_INHERIT) != 0
                               1874               7 :                 && authmem_form->inherit_option != popt->inherit)
                               1875                 :             {
                               1876               7 :                 new_record[Anum_pg_auth_members_inherit_option - 1] =
                               1877               7 :                     BoolGetDatum(popt->inherit);
                               1878               7 :                 new_record_repl[Anum_pg_auth_members_inherit_option - 1] =
                               1879                 :                     true;
                               1880               7 :                 at_least_one_change = true;
                               1881                 :             }
                               1882                 : 
  142                          1883              16 :             if ((popt->specified & GRANT_ROLE_SPECIFIED_SET) != 0
                               1884               4 :                 && authmem_form->set_option != popt->set)
                               1885                 :             {
                               1886               4 :                 new_record[Anum_pg_auth_members_set_option - 1] =
                               1887               4 :                     BoolGetDatum(popt->set);
                               1888               4 :                 new_record_repl[Anum_pg_auth_members_set_option - 1] =
                               1889                 :                     true;
                               1890               4 :                 at_least_one_change = true;
                               1891                 :             }
                               1892                 : 
  227                          1893              16 :             if (!at_least_one_change)
                               1894                 :             {
  234                          1895               9 :                 ereport(NOTICE,
                               1896                 :                         (errmsg("role \"%s\" has already been granted membership in role \"%s\" by role \"%s\"",
                               1897                 :                                 get_rolespec_name(memberRole), rolename,
                               1898                 :                                 GetUserNameFromId(grantorId, false))));
                               1899               9 :                 ReleaseSysCache(authmem_tuple);
                               1900               9 :                 continue;
                               1901                 :             }
                               1902                 : 
 5271 tgl                      1903 CBC           7 :             tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
                               1904                 :                                       new_record,
 5050 bruce                    1905 ECB             :                                       new_record_nulls, new_record_repl);
 2259 alvherre                 1906 CBC           7 :             CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple);
                               1907                 : 
 6494 tgl                      1908               7 :             ReleaseSysCache(authmem_tuple);
                               1909                 :         }
                               1910                 :         else
 8397 bruce                    1911 EUB             :         {
                               1912                 :             Oid         objectId;
  234 rhaas                    1913 GNC        1169 :             Oid        *newmembers = palloc(sizeof(Oid));
                               1914                 : 
                               1915                 :             /*
                               1916                 :              * The values for these options can be taken directly from 'popt'.
                               1917                 :              * Either they were specified, or the defaults as set by
                               1918                 :              * InitGrantRoleOptions are correct.
                               1919                 :              */
  227                          1920            1169 :             new_record[Anum_pg_auth_members_admin_option - 1] =
                               1921            1169 :                 BoolGetDatum(popt->admin);
  142                          1922            1169 :             new_record[Anum_pg_auth_members_set_option - 1] =
                               1923            1169 :                 BoolGetDatum(popt->set);
                               1924                 : 
                               1925                 :             /*
                               1926                 :              * If the user specified a value for the inherit option, use
                               1927                 :              * whatever was specified. Otherwise, set the default value based
                               1928                 :              * on the role-level property.
                               1929                 :              */
  227                          1930            1169 :             if ((popt->specified & GRANT_ROLE_SPECIFIED_INHERIT) != 0)
                               1931              75 :                 new_record[Anum_pg_auth_members_inherit_option - 1] =
                               1932              75 :                     popt->inherit;
                               1933                 :             else
                               1934                 :             {
                               1935                 :                 HeapTuple       mrtup;
                               1936                 :                 Form_pg_authid  mrform;
                               1937                 : 
                               1938            1094 :                 mrtup = SearchSysCache1(AUTHOID, memberid);
                               1939            1094 :                 if (!HeapTupleIsValid(mrtup))
  227 rhaas                    1940 UNC           0 :                     elog(ERROR, "cache lookup failed for role %u", memberid);
  227 rhaas                    1941 GNC        1094 :                 mrform = (Form_pg_authid) GETSTRUCT(mrtup);
                               1942            1094 :                 new_record[Anum_pg_auth_members_inherit_option - 1] =
                               1943            1094 :                     mrform->rolinherit;
                               1944            1094 :                 ReleaseSysCache(mrtup);
                               1945                 :             }
                               1946                 : 
                               1947                 :             /* get an OID for the new row and insert it */
  118 michael                  1948            1169 :             objectId = GetNewOidWithIndex(pg_authmem_rel, AuthMemOidIndexId,
                               1949                 :                                           Anum_pg_auth_members_oid);
  234 rhaas                    1950            1169 :             new_record[Anum_pg_auth_members_oid - 1] = objectId;
 5271 tgl                      1951 GIC        1169 :             tuple = heap_form_tuple(pg_authmem_dsc,
                               1952                 :                                     new_record, new_record_nulls);
 2259 alvherre                 1953            1169 :             CatalogTupleInsert(pg_authmem_rel, tuple);
                               1954                 : 
                               1955                 :             /* updateAclDependencies wants to pfree array inputs */
  234 rhaas                    1956 GNC        1169 :             newmembers[0] = grantorId;
                               1957            1169 :             updateAclDependencies(AuthMemRelationId, objectId,
                               1958                 :                                   0, InvalidOid,
                               1959                 :                                   0, NULL,
                               1960                 :                                   1, newmembers);
                               1961                 :         }
 6493 tgl                      1962 EUB             : 
                               1963                 :         /* CCI after each change, in case there are duplicates in list */
 6493 tgl                      1964 GIC        1176 :         CommandCounterIncrement();
                               1965                 :     }
                               1966                 : 
                               1967                 :     /*
                               1968                 :      * Close pg_authmem, but keep lock till commit.
                               1969                 :      */
 1539 andres                   1970 CBC        2600 :     table_close(pg_authmem_rel, NoLock);
 8515 bruce                    1971            2600 : }
                               1972                 : 
 7652 tgl                      1973 ECB             : /*
                               1974                 :  * DelRoleMems -- Remove given members from the specified role
 6494                          1975                 :  *
                               1976                 :  * rolename: name of role to del from (used only for error messages)
                               1977                 :  * roleid: OID of role to del from
 2953 alvherre                 1978                 :  * memberSpecs: list of RoleSpec of roles to del (used only for error messages)
                               1979                 :  * memberIds: OIDs of roles to del
                               1980                 :  * grantorId: who is revoking the membership
                               1981                 :  * popt: information about grant options
                               1982                 :  * behavior: RESTRICT or CASCADE behavior for recursive removal
                               1983                 :  */
                               1984                 : static void
   94 rhaas                    1985 GNC          82 : DelRoleMems(Oid currentUserId, const char *rolename, Oid roleid,
                               1986                 :             List *memberSpecs, List *memberIds,
                               1987                 :             Oid grantorId, GrantRoleOptions *popt, DropBehavior behavior)
                               1988                 : {
 6494 tgl                      1989 ECB             :     Relation    pg_authmem_rel;
                               1990                 :     TupleDesc   pg_authmem_dsc;
 2953 alvherre                 1991                 :     ListCell   *specitem;
 6385 bruce                    1992                 :     ListCell   *iditem;
                               1993                 :     CatCList   *memlist;
                               1994                 :     RevokeRoleGrantAction *actions;
                               1995                 :     int         i;
                               1996                 : 
 2953 alvherre                 1997 GIC          82 :     Assert(list_length(memberSpecs) == list_length(memberIds));
                               1998                 : 
                               1999                 :     /* Validate grantor (and resolve implicit grantor if not specified). */
  230 rhaas                    2000 GNC          82 :     grantorId = check_role_grantor(currentUserId, roleid, grantorId, false);
                               2001                 : 
 1539 andres                   2002 GIC          82 :     pg_authmem_rel = table_open(AuthMemRelationId, RowExclusiveLock);
 6494 tgl                      2003              82 :     pg_authmem_dsc = RelationGetDescr(pg_authmem_rel);
                               2004                 : 
                               2005                 :     /*
                               2006                 :      * Only allow changes to this role by one backend at a time, so that we
                               2007                 :      * can check for things like dependent privileges without fear of race
                               2008                 :      * conditions.
                               2009                 :      */
  230 rhaas                    2010 GNC          82 :     LockSharedObject(AuthIdRelationId, roleid, 0,
                               2011                 :                      ShareUpdateExclusiveLock);
                               2012                 : 
                               2013              82 :     memlist = SearchSysCacheList1(AUTHMEMROLEMEM, ObjectIdGetDatum(roleid));
                               2014              82 :     actions = initialize_revoke_actions(memlist);
                               2015                 : 
                               2016                 :     /*
                               2017                 :      * We may need to recurse to dependent privileges if DROP_CASCADE was
                               2018                 :      * specified, or refuse to perform the operation if dependent privileges
                               2019                 :      * exist and DROP_RESTRICT was specified. plan_single_revoke() will figure
                               2020                 :      * out what to do with each catalog tuple.
                               2021                 :      */
 2953 alvherre                 2022 GIC         158 :     forboth(specitem, memberSpecs, iditem, memberIds)
                               2023                 :     {
 2953 alvherre                 2024 CBC          82 :         RoleSpec   *memberRole = lfirst(specitem);
 6494 tgl                      2025 GIC          82 :         Oid         memberid = lfirst_oid(iditem);
                               2026                 : 
  230 rhaas                    2027 GNC          82 :         if (!plan_single_revoke(memlist, actions, memberid, grantorId,
                               2028                 :                                 popt, behavior))
 6494 tgl                      2029 ECB             :         {
 6494 tgl                      2030 GIC           3 :             ereport(WARNING,
                               2031                 :                     (errmsg("role \"%s\" has not been granted membership in role \"%s\" by role \"%s\"",
                               2032                 :                             get_rolespec_name(memberRole), rolename,
                               2033                 :                             GetUserNameFromId(grantorId, false))));
                               2034               3 :             continue;
                               2035                 :         }
                               2036                 :     }
                               2037                 : 
                               2038                 :     /*
                               2039                 :      * We now know what to do with each catalog tuple: it should either be
                               2040                 :      * left alone, deleted, or just have the admin_option flag cleared.
                               2041                 :      * Perform the appropriate action in each case.
                               2042                 :      */
  230 rhaas                    2043 GNC         221 :     for (i = 0; i < memlist->n_members; ++i)
                               2044                 :     {
                               2045                 :         HeapTuple   authmem_tuple;
                               2046                 :         Form_pg_auth_members authmem_form;
                               2047                 : 
                               2048             145 :         if (actions[i] == RRG_NOOP)
                               2049              63 :             continue;
                               2050                 : 
                               2051              82 :         authmem_tuple = &memlist->members[i]->tuple;
  234                          2052              82 :         authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
                               2053                 : 
  230                          2054              82 :         if (actions[i] == RRG_DELETE_GRANT)
 6494 tgl                      2055 ECB             :         {
                               2056                 :             /*
                               2057                 :              * Remove the entry altogether, after first removing its
                               2058                 :              * dependencies
                               2059                 :              */
  234 rhaas                    2060 GNC          58 :             deleteSharedDependencyRecordsFor(AuthMemRelationId,
                               2061                 :                                              authmem_form->oid, 0);
 2258 tgl                      2062 GIC          58 :             CatalogTupleDelete(pg_authmem_rel, &authmem_tuple->t_self);
                               2063                 :         }
                               2064                 :         else
                               2065                 :         {
                               2066                 :             /* Just turn off the specified option */
                               2067                 :             HeapTuple   tuple;
  267 peter                    2068 GNC          24 :             Datum       new_record[Natts_pg_auth_members] = {0};
                               2069              24 :             bool        new_record_nulls[Natts_pg_auth_members] = {0};
                               2070              24 :             bool        new_record_repl[Natts_pg_auth_members] = {0};
 6494 tgl                      2071 ECB             : 
                               2072                 :             /* Build a tuple to update with */
  227 rhaas                    2073 GNC          24 :             if (actions[i] == RRG_REMOVE_ADMIN_OPTION)
                               2074                 :             {
                               2075              15 :                 new_record[Anum_pg_auth_members_admin_option - 1] =
                               2076              15 :                     BoolGetDatum(false);
                               2077              15 :                 new_record_repl[Anum_pg_auth_members_admin_option - 1] =
                               2078                 :                     true;
                               2079                 :             }
                               2080               9 :             else if (actions[i] == RRG_REMOVE_INHERIT_OPTION)
                               2081                 :             {
                               2082               6 :                 new_record[Anum_pg_auth_members_inherit_option - 1] =
                               2083               6 :                     BoolGetDatum(false);
                               2084               6 :                 new_record_repl[Anum_pg_auth_members_inherit_option - 1] =
                               2085                 :                     true;
                               2086                 :             }
  142                          2087               3 :             else if (actions[i] == RRG_REMOVE_SET_OPTION)
                               2088                 :             {
                               2089               3 :                 new_record[Anum_pg_auth_members_set_option - 1] =
                               2090               3 :                     BoolGetDatum(false);
                               2091               3 :                 new_record_repl[Anum_pg_auth_members_set_option - 1] =
                               2092                 :                     true;
                               2093                 :             }
                               2094                 :             else
  227 rhaas                    2095 UNC           0 :                 elog(ERROR, "unknown role revoke action");
                               2096                 : 
 5271 tgl                      2097 CBC          24 :             tuple = heap_modify_tuple(authmem_tuple, pg_authmem_dsc,
 5050 bruce                    2098 ECB             :                                       new_record,
                               2099                 :                                       new_record_nulls, new_record_repl);
 2259 alvherre                 2100 GIC          24 :             CatalogTupleUpdate(pg_authmem_rel, &tuple->t_self, tuple);
                               2101                 :         }
                               2102                 :     }
 7652 tgl                      2103 ECB             : 
  230 rhaas                    2104 GNC          76 :     ReleaseSysCacheList(memlist);
                               2105                 : 
 7475 tgl                      2106 ECB             :     /*
                               2107                 :      * Close pg_authmem, but keep lock till commit.
                               2108                 :      */
 1539 andres                   2109 GIC          76 :     table_close(pg_authmem_rel, NoLock);
 7226 peter_e                  2110              76 : }
                               2111                 : 
                               2112                 : /*
                               2113                 :  * Check that currentUserId has permission to modify the membership list for
                               2114                 :  * roleid. Throw an error if not.
                               2115                 :  */
                               2116                 : static void
   94 rhaas                    2117 GNC        1221 : check_role_membership_authorization(Oid currentUserId, Oid roleid,
                               2118                 :                                     bool is_grant)
                               2119                 : {
                               2120                 :     /*
                               2121                 :      * The charter of pg_database_owner is to have exactly one, implicit,
                               2122                 :      * situation-dependent member.  There's no technical need for this
                               2123                 :      * restriction.  (One could lift it and take the further step of making
                               2124                 :      * object_ownercheck(DatabaseRelationId, ...) equivalent to
                               2125                 :      * has_privs_of_role(roleid, ROLE_PG_DATABASE_OWNER), in which case
                               2126                 :      * explicit, situation-independent members could act as the owner of any
                               2127                 :      * database.)
                               2128                 :      */
                               2129            1221 :     if (is_grant && roleid == ROLE_PG_DATABASE_OWNER)
                               2130               6 :         ereport(ERROR,
                               2131                 :                 errmsg("role \"%s\" cannot have explicit members",
                               2132                 :                        GetUserNameFromId(roleid, false)));
                               2133                 : 
                               2134                 :     /* To mess with a superuser role, you gotta be superuser. */
                               2135            1215 :     if (superuser_arg(roleid))
                               2136                 :     {
                               2137               8 :         if (!superuser_arg(currentUserId))
                               2138                 :         {
   23 peter                    2139               3 :             if (is_grant)
                               2140               3 :                 ereport(ERROR,
                               2141                 :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               2142                 :                          errmsg("permission denied to grant role \"%s\"",
                               2143                 :                                 GetUserNameFromId(roleid, false)),
                               2144                 :                          errdetail("Only roles with the %s attribute may grant roles with %s.",
                               2145                 :                                    "SUPERUSER", "SUPERUSER")));
                               2146                 :             else
   23 peter                    2147 UNC           0 :                 ereport(ERROR,
                               2148                 :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               2149                 :                          errmsg("permission denied to revoke role \"%s\"",
                               2150                 :                                 GetUserNameFromId(roleid, false)),
                               2151                 :                          errdetail("Only roles with the %s attribute may revoke roles with %s.",
                               2152                 :                                    "SUPERUSER", "SUPERUSER")));
                               2153                 :         }
                               2154                 :     }
                               2155                 :     else
                               2156                 :     {
                               2157                 :         /*
                               2158                 :          * Otherwise, must have admin option on the role to be changed.
                               2159                 :          */
   89 rhaas                    2160 GNC        1207 :         if (!is_admin_of_role(currentUserId, roleid))
                               2161                 :         {
   23 peter                    2162              72 :             if (is_grant)
                               2163              72 :                 ereport(ERROR,
                               2164                 :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               2165                 :                          errmsg("permission denied to grant role \"%s\"",
                               2166                 :                                 GetUserNameFromId(roleid, false)),
                               2167                 :                          errdetail("Only roles with the %s option on role \"%s\" may grant this role.",
                               2168                 :                                    "ADMIN", GetUserNameFromId(roleid, false))));
                               2169                 :             else
   23 peter                    2170 UNC           0 :                 ereport(ERROR,
                               2171                 :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               2172                 :                          errmsg("permission denied to revoke role \"%s\"",
                               2173                 :                                 GetUserNameFromId(roleid, false)),
                               2174                 :                          errdetail("Only roles with the %s option on role \"%s\" may revoke this role.",
                               2175                 :                                    "ADMIN", GetUserNameFromId(roleid, false))));
                               2176                 :         }
                               2177                 :     }
   94 rhaas                    2178 GNC        1140 : }
                               2179                 : 
                               2180                 : /*
                               2181                 :  * Sanity-check, or infer, the grantor for a GRANT or REVOKE statement
                               2182                 :  * targeting a role.
                               2183                 :  *
                               2184                 :  * The grantor must always be either a role with ADMIN OPTION on the role in
                               2185                 :  * which membership is being granted, or the bootstrap superuser. This is
                               2186                 :  * similar to the restriction enforced by select_best_grantor, except that
                               2187                 :  * roles don't have owners, so we regard the bootstrap superuser as the
                               2188                 :  * implicit owner.
                               2189                 :  *
                               2190                 :  * If the grantor was not explicitly specified by the user, grantorId should
                               2191                 :  * be passed as InvalidOid, and this function will infer the user to be
                               2192                 :  * recorded as the grantor. In many cases, this will be the current user, but
                               2193                 :  * things get more complicated when the current user doesn't possess ADMIN
                               2194                 :  * OPTION on the role but rather relies on having SUPERUSER privileges, or
                               2195                 :  * on inheriting the privileges of a role which does have ADMIN OPTION. See
                               2196                 :  * below for details.
                               2197                 :  *
                               2198                 :  * If the grantor was specified by the user, then it must be a user that
                               2199                 :  * can legally be recorded as the grantor, as per the rule stated above.
                               2200                 :  * This is an integrity constraint, not a permissions check, and thus even
                               2201                 :  * superusers are subject to this restriction. However, there is also a
                               2202                 :  * permissions check: to specify a role as the grantor, the current user
                               2203                 :  * must possess the privileges of that role. Superusers will always pass
                               2204                 :  * this check, but for non-superusers it may lead to an error.
                               2205                 :  *
                               2206                 :  * The return value is the OID to be regarded as the grantor when executing
                               2207                 :  * the operation.
                               2208                 :  */
                               2209                 : static Oid
  230                          2210            2697 : check_role_grantor(Oid currentUserId, Oid roleid, Oid grantorId, bool is_grant)
                               2211                 : {
                               2212                 :     /* If the grantor ID was not specified, pick one to use. */
                               2213            2697 :     if (!OidIsValid(grantorId))
                               2214                 :     {
                               2215                 :         /*
                               2216                 :          * Grants where the grantor is recorded as the bootstrap superuser do
                               2217                 :          * not depend on any other existing grants, so always default to this
                               2218                 :          * interpretation when possible.
                               2219                 :          */
   89                          2220            2598 :         if (superuser_arg(currentUserId))
  230                          2221            2430 :             return BOOTSTRAP_SUPERUSERID;
                               2222                 : 
                               2223                 :         /*
                               2224                 :          * Otherwise, the grantor must either have ADMIN OPTION on the role or
                               2225                 :          * inherit the privileges of a role which does. In the former case,
                               2226                 :          * record the grantor as the current user; in the latter, pick one of
                               2227                 :          * the roles that is "most directly" inherited by the current role
                               2228                 :          * (i.e. fewest "hops").
                               2229                 :          *
                               2230                 :          * (We shouldn't fail to find a best grantor, because we've already
                               2231                 :          * established that the current user has permission to perform the
                               2232                 :          * operation.)
                               2233                 :          */
                               2234             168 :         grantorId = select_best_admin(currentUserId, roleid);
                               2235             168 :         if (!OidIsValid(grantorId))
  230 rhaas                    2236 UNC           0 :             elog(ERROR, "no possible grantors");
  230 rhaas                    2237 GNC         168 :         return grantorId;
                               2238                 :     }
                               2239                 : 
                               2240                 :     /*
                               2241                 :      * If an explicit grantor is specified, it must be a role whose privileges
                               2242                 :      * the current user possesses.
                               2243                 :      *
                               2244                 :      * It should also be a role that has ADMIN OPTION on the target role, but
                               2245                 :      * we check this condition only in case of GRANT. For REVOKE, no matching
                               2246                 :      * grant should exist anyway, but if it somehow does, let the user get rid
                               2247                 :      * of it.
                               2248                 :      */
                               2249              99 :     if (is_grant)
                               2250                 :     {
                               2251              87 :         if (!has_privs_of_role(currentUserId, grantorId))
  230 rhaas                    2252 UNC           0 :             ereport(ERROR,
                               2253                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               2254                 :                      errmsg("permission denied to grant privileges as role \"%s\"",
                               2255                 :                             GetUserNameFromId(grantorId, false)),
                               2256                 :                      errdetail("Only roles with privileges of role \"%s\" may grant privileges as this role.",
                               2257                 :                                GetUserNameFromId(grantorId, false))));
                               2258                 : 
  230 rhaas                    2259 GNC         111 :         if (grantorId != BOOTSTRAP_SUPERUSERID &&
                               2260              24 :             select_best_admin(grantorId, roleid) != grantorId)
                               2261               3 :             ereport(ERROR,
                               2262                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               2263                 :                      errmsg("permission denied to grant privileges as role \"%s\"",
                               2264                 :                             GetUserNameFromId(grantorId, false)),
                               2265                 :                      errdetail("The grantor must have the %s option on role \"%s\".",
                               2266                 :                                "ADMIN", GetUserNameFromId(roleid, false))));
                               2267                 :     }
                               2268                 :     else
                               2269                 :     {
                               2270              12 :         if (!has_privs_of_role(currentUserId, grantorId))
  230 rhaas                    2271 UNC           0 :             ereport(ERROR,
                               2272                 :                     (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                               2273                 :                      errmsg("permission denied to revoke privileges granted by role \"%s\"",
                               2274                 :                             GetUserNameFromId(grantorId, false)),
                               2275                 :                      errdetail("Only roles with privileges of role \"%s\" may revoke privileges granted by this role.",
                               2276                 :                                GetUserNameFromId(grantorId, false))));
                               2277                 :     }
                               2278                 : 
                               2279                 :     /*
                               2280                 :      * If a grantor was specified explicitly, always attribute the grant to
                               2281                 :      * that role (unless we error out above).
                               2282                 :      */
  230 rhaas                    2283 GNC          96 :     return grantorId;
                               2284                 : }
                               2285                 : 
                               2286                 : /*
                               2287                 :  * Initialize an array of RevokeRoleGrantAction objects.
                               2288                 :  *
                               2289                 :  * 'memlist' should be a list of all grants for the target role.
                               2290                 :  *
                               2291                 :  * This constructs an array indicating that no actions are to be performed;
                               2292                 :  * that is, every element is initially RRG_NOOP.
                               2293                 :  */
                               2294                 : static RevokeRoleGrantAction *
                               2295             145 : initialize_revoke_actions(CatCList *memlist)
                               2296                 : {
                               2297                 :     RevokeRoleGrantAction *result;
                               2298                 :     int         i;
                               2299                 : 
                               2300             145 :     if (memlist->n_members == 0)
  230 rhaas                    2301 UNC           0 :         return NULL;
                               2302                 : 
  230 rhaas                    2303 GNC         145 :     result = palloc(sizeof(RevokeRoleGrantAction) * memlist->n_members);
                               2304             398 :     for (i = 0; i < memlist->n_members; i++)
                               2305             253 :         result[i] = RRG_NOOP;
                               2306             145 :     return result;
                               2307                 : }
                               2308                 : 
                               2309                 : /*
                               2310                 :  * Figure out what we would need to do in order to revoke a grant, or just the
                               2311                 :  * admin option on a grant, given that there might be dependent privileges.
                               2312                 :  *
                               2313                 :  * 'memlist' should be a list of all grants for the target role.
                               2314                 :  *
                               2315                 :  * Whatever actions prove to be necessary will be signalled by updating
                               2316                 :  * 'actions'.
                               2317                 :  *
                               2318                 :  * If behavior is DROP_RESTRICT, an error will occur if there are dependent
                               2319                 :  * role membership grants; if DROP_CASCADE, those grants will be scheduled
                               2320                 :  * for deletion.
                               2321                 :  *
                               2322                 :  * The return value is true if the matching grant was found in the list,
                               2323                 :  * and false if not.
                               2324                 :  */
                               2325                 : static bool
                               2326              82 : plan_single_revoke(CatCList *memlist, RevokeRoleGrantAction *actions,
                               2327                 :                    Oid member, Oid grantor, GrantRoleOptions *popt,
                               2328                 :                    DropBehavior behavior)
                               2329                 : {
                               2330                 :     int         i;
                               2331                 : 
                               2332                 :     /*
                               2333                 :      * If popt.specified == 0, we're revoking the grant entirely; otherwise,
                               2334                 :      * we expect just one bit to be set, and we're revoking the corresponding
                               2335                 :      * option. As of this writing, there's no syntax that would allow for
                               2336                 :      * an attempt to revoke multiple options at once, and the logic below
                               2337                 :      * wouldn't work properly if such syntax were added, so assert that our
                               2338                 :      * caller isn't trying to do that.
                               2339                 :      */
  227                          2340              82 :     Assert(pg_popcount32(popt->specified) <= 1);
                               2341                 : 
  230                          2342             142 :     for (i = 0; i < memlist->n_members; ++i)
                               2343                 :     {
                               2344                 :         HeapTuple   authmem_tuple;
                               2345                 :         Form_pg_auth_members authmem_form;
                               2346                 : 
                               2347             139 :         authmem_tuple = &memlist->members[i]->tuple;
                               2348             139 :         authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
                               2349                 : 
                               2350             139 :         if (authmem_form->member == member &&
                               2351              88 :             authmem_form->grantor == grantor)
                               2352                 :         {
  227                          2353              79 :             if ((popt->specified & GRANT_ROLE_SPECIFIED_INHERIT) != 0)
                               2354                 :             {
                               2355                 :                 /*
                               2356                 :                  * Revoking the INHERIT option doesn't change anything for
                               2357                 :                  * dependent privileges, so we don't need to recurse.
                               2358                 :                  */
                               2359               6 :                 actions[i] = RRG_REMOVE_INHERIT_OPTION;
                               2360                 :             }
  142                          2361              73 :             else if ((popt->specified & GRANT_ROLE_SPECIFIED_SET) != 0)
                               2362                 :             {
                               2363                 :                 /* Here too, no need to recurse. */
                               2364               3 :                 actions[i] = RRG_REMOVE_SET_OPTION;
                               2365                 :             }
                               2366                 :             else
                               2367                 :             {
                               2368                 :                 bool    revoke_admin_option_only;
                               2369                 : 
                               2370                 :                 /*
                               2371                 :                  * Revoking the grant entirely, or ADMIN option on a grant,
                               2372                 :                  * implicates dependent privileges, so we may need to recurse.
                               2373                 :                  */
  227                          2374              70 :                 revoke_admin_option_only =
                               2375              70 :                     (popt->specified & GRANT_ROLE_SPECIFIED_ADMIN) != 0;
                               2376              70 :                 plan_recursive_revoke(memlist, actions, i,
                               2377                 :                                       revoke_admin_option_only, behavior);
                               2378                 :             }
  230                          2379              73 :             return true;
                               2380                 :         }
                               2381                 :     }
                               2382                 : 
                               2383               3 :     return false;
                               2384                 : }
                               2385                 : 
                               2386                 : /*
                               2387                 :  * Figure out what we would need to do in order to revoke all grants to
                               2388                 :  * a given member, given that there might be dependent privileges.
                               2389                 :  *
                               2390                 :  * 'memlist' should be a list of all grants for the target role.
                               2391                 :  *
                               2392                 :  * Whatever actions prove to be necessary will be signalled by updating
                               2393                 :  * 'actions'.
                               2394                 :  */
                               2395                 : static void
                               2396              33 : plan_member_revoke(CatCList *memlist, RevokeRoleGrantAction *actions,
                               2397                 :                    Oid member)
                               2398                 : {
                               2399                 :     int         i;
                               2400                 : 
                               2401              72 :     for (i = 0; i < memlist->n_members; ++i)
                               2402                 :     {
                               2403                 :         HeapTuple   authmem_tuple;
                               2404                 :         Form_pg_auth_members authmem_form;
                               2405                 : 
                               2406              39 :         authmem_tuple = &memlist->members[i]->tuple;
                               2407              39 :         authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
                               2408                 : 
                               2409              39 :         if (authmem_form->member == member)
                               2410               3 :             plan_recursive_revoke(memlist, actions, i, false, DROP_CASCADE);
                               2411                 :     }
                               2412              33 : }
                               2413                 : 
                               2414                 : /*
                               2415                 :  * Workhorse for figuring out recursive revocation of role grants.
                               2416                 :  *
                               2417                 :  * This is similar to what recursive_revoke() does for ACLs.
                               2418                 :  */
                               2419                 : static void
                               2420              85 : plan_recursive_revoke(CatCList *memlist, RevokeRoleGrantAction *actions,
                               2421                 :                       int index,
                               2422                 :                       bool revoke_admin_option_only, DropBehavior behavior)
                               2423                 : {
                               2424              85 :     bool        would_still_have_admin_option = false;
                               2425                 :     HeapTuple   authmem_tuple;
                               2426                 :     Form_pg_auth_members authmem_form;
                               2427                 :     int         i;
                               2428                 : 
                               2429                 :     /* If it's already been done, we can just return. */
                               2430              85 :     if (actions[index] == RRG_DELETE_GRANT)
  230 rhaas                    2431 UNC           0 :         return;
  230 rhaas                    2432 GNC          85 :     if (actions[index] == RRG_REMOVE_ADMIN_OPTION &&
                               2433                 :         revoke_admin_option_only)
  230 rhaas                    2434 UNC           0 :         return;
                               2435                 : 
                               2436                 :     /* Locate tuple data. */
  230 rhaas                    2437 GNC          85 :     authmem_tuple = &memlist->members[index]->tuple;
                               2438              85 :     authmem_form = (Form_pg_auth_members) GETSTRUCT(authmem_tuple);
                               2439                 : 
                               2440                 :     /*
                               2441                 :      * If the existing tuple does not have admin_option set, then we do not
                               2442                 :      * need to recurse. If we're just supposed to clear that bit we don't need
                               2443                 :      * to do anything at all; if we're supposed to remove the grant, we need
                               2444                 :      * to do something, but only to the tuple, and not any others.
                               2445                 :      */
                               2446              85 :     if (!revoke_admin_option_only)
                               2447                 :     {
                               2448              67 :         actions[index] = RRG_DELETE_GRANT;
                               2449              67 :         if (!authmem_form->admin_option)
                               2450              46 :             return;
                               2451                 :     }
                               2452                 :     else
                               2453                 :     {
                               2454              18 :         if (!authmem_form->admin_option)
  230 rhaas                    2455 UNC           0 :             return;
  230 rhaas                    2456 GNC          18 :         actions[index] = RRG_REMOVE_ADMIN_OPTION;
                               2457                 :     }
                               2458                 : 
                               2459                 :     /* Determine whether the member would still have ADMIN OPTION. */
                               2460             114 :     for (i = 0; i < memlist->n_members; ++i)
                               2461                 :     {
                               2462                 :         HeapTuple   am_cascade_tuple;
                               2463                 :         Form_pg_auth_members am_cascade_form;
                               2464                 : 
                               2465              75 :         am_cascade_tuple = &memlist->members[i]->tuple;
                               2466              75 :         am_cascade_form = (Form_pg_auth_members) GETSTRUCT(am_cascade_tuple);
                               2467                 : 
                               2468              75 :         if (am_cascade_form->member == authmem_form->member &&
                               2469              39 :             am_cascade_form->admin_option && actions[i] == RRG_NOOP)
                               2470                 :         {
  230 rhaas                    2471 UNC           0 :             would_still_have_admin_option = true;
                               2472               0 :             break;
                               2473                 :         }
                               2474                 :     }
                               2475                 : 
                               2476                 :     /* If the member would still have ADMIN OPTION, we need not recurse. */
  230 rhaas                    2477 GNC          39 :     if (would_still_have_admin_option)
  230 rhaas                    2478 UNC           0 :         return;
                               2479                 : 
                               2480                 :     /*
                               2481                 :      * Recurse to grants that are not yet slated for deletion which have this
                               2482                 :      * member as the grantor.
                               2483                 :      */
  230 rhaas                    2484 GNC         108 :     for (i = 0; i < memlist->n_members; ++i)
                               2485                 :     {
                               2486                 :         HeapTuple   am_cascade_tuple;
                               2487                 :         Form_pg_auth_members am_cascade_form;
                               2488                 : 
                               2489              75 :         am_cascade_tuple = &memlist->members[i]->tuple;
                               2490              75 :         am_cascade_form = (Form_pg_auth_members) GETSTRUCT(am_cascade_tuple);
                               2491                 : 
                               2492              75 :         if (am_cascade_form->grantor == authmem_form->member &&
                               2493              18 :             actions[i] != RRG_DELETE_GRANT)
                               2494                 :         {
                               2495              18 :             if (behavior == DROP_RESTRICT)
                               2496               6 :                 ereport(ERROR,
                               2497                 :                         (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
                               2498                 :                          errmsg("dependent privileges exist"),
                               2499                 :                          errhint("Use CASCADE to revoke them too.")));
                               2500                 : 
                               2501              12 :             plan_recursive_revoke(memlist, actions, i, false, behavior);
                               2502                 :         }
                               2503                 :     }
                               2504                 : }
                               2505                 : 
                               2506                 : /*
                               2507                 :  * Initialize a GrantRoleOptions object with default values.
                               2508                 :  */
                               2509                 : static void
  227                          2510            2113 : InitGrantRoleOptions(GrantRoleOptions *popt)
                               2511                 : {
                               2512            2113 :     popt->specified = 0;
                               2513            2113 :     popt->admin = false;
                               2514            2113 :     popt->inherit = false;
  142                          2515            2113 :     popt->set = true;
  227                          2516            2113 : }
                               2517                 : 
                               2518                 : /*
                               2519                 :  * GUC check_hook for createrole_self_grant
                               2520                 :  */
                               2521                 : bool
   89                          2522            1860 : check_createrole_self_grant(char **newval, void **extra, GucSource source)
                               2523                 : {
                               2524                 :     char       *rawstring;
                               2525                 :     List       *elemlist;
                               2526                 :     ListCell   *l;
                               2527            1860 :     unsigned    options = 0;
                               2528                 :     unsigned   *result;
                               2529                 : 
                               2530                 :     /* Need a modifiable copy of string */
                               2531            1860 :     rawstring = pstrdup(*newval);
                               2532                 : 
                               2533            1860 :     if (!SplitIdentifierString(rawstring, ',', &elemlist))
                               2534                 :     {
                               2535                 :         /* syntax error in list */
   89 rhaas                    2536 UNC           0 :         GUC_check_errdetail("List syntax is invalid.");
                               2537               0 :         pfree(rawstring);
                               2538               0 :         list_free(elemlist);
                               2539               0 :         return false;
                               2540                 :     }
                               2541                 : 
   89 rhaas                    2542 GNC        1866 :     foreach(l, elemlist)
                               2543                 :     {
                               2544               6 :         char       *tok = (char *) lfirst(l);
                               2545                 : 
                               2546               6 :         if (pg_strcasecmp(tok, "SET") == 0)
                               2547               3 :             options |= GRANT_ROLE_SPECIFIED_SET;
                               2548               3 :         else if (pg_strcasecmp(tok, "INHERIT") == 0)
                               2549               3 :             options |= GRANT_ROLE_SPECIFIED_INHERIT;
                               2550                 :         else
                               2551                 :         {
   89 rhaas                    2552 UNC           0 :             GUC_check_errdetail("Unrecognized key word: \"%s\".", tok);
                               2553               0 :             pfree(rawstring);
                               2554               0 :             list_free(elemlist);
                               2555               0 :             return false;
                               2556                 :         }
                               2557                 :     }
                               2558                 : 
   89 rhaas                    2559 GNC        1860 :     pfree(rawstring);
                               2560            1860 :     list_free(elemlist);
                               2561                 : 
                               2562            1860 :     result = (unsigned *) guc_malloc(LOG, sizeof(unsigned));
                               2563            1860 :     *result = options;
                               2564            1860 :     *extra = result;
                               2565                 : 
                               2566            1860 :     return true;
                               2567                 : }
                               2568                 : 
                               2569                 : /*
                               2570                 :  * GUC assign_hook for createrole_self_grant
                               2571                 :  */
                               2572                 : void
                               2573            1860 : assign_createrole_self_grant(const char *newval, void *extra)
                               2574                 : {
                               2575            1860 :     unsigned    options = * (unsigned *) extra;
                               2576                 : 
                               2577            1860 :     createrole_self_grant_enabled = (options != 0);
                               2578            1860 :     createrole_self_grant_options.specified = GRANT_ROLE_SPECIFIED_ADMIN
                               2579                 :         | GRANT_ROLE_SPECIFIED_INHERIT
                               2580                 :         | GRANT_ROLE_SPECIFIED_SET;
                               2581            1860 :     createrole_self_grant_options.admin = false;
                               2582            1860 :     createrole_self_grant_options.inherit =
                               2583            1860 :         (options & GRANT_ROLE_SPECIFIED_INHERIT) != 0;
                               2584            1860 :     createrole_self_grant_options.set =
                               2585            1860 :         (options & GRANT_ROLE_SPECIFIED_SET) != 0;
                               2586            1860 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a