39
39
#include "utils/fmgroids.h"
40
40
#include "utils/syscache.h"
41
41
#include "utils/timestamp.h"
42
+ #include "utils/varlena.h"
42
43
43
44
/*
44
45
* Removing a role grant - or the admin option on it - might recurse to
@@ -81,8 +82,11 @@ typedef struct
81
82
#define GRANT_ROLE_SPECIFIED_INHERIT 0x0002
82
83
#define GRANT_ROLE_SPECIFIED_SET 0x0004
83
84
84
- /* GUC parameter */
85
+ /* GUC parameters */
85
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 ;
86
90
87
91
/* Hook to check passwords in CreateRole() and AlterRole() */
88
92
check_password_hook_type check_password_hook = NULL ;
@@ -532,10 +536,13 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
532
536
if (!superuser ())
533
537
{
534
538
RoleSpec * current_role = makeNode (RoleSpec );
535
- GrantRoleOptions poptself ;
539
+ GrantRoleOptions poptself ;
540
+ List * memberSpecs ;
541
+ List * memberIds = list_make1_oid (currentUserId );
536
542
537
543
current_role -> roletype = ROLESPEC_CURRENT_ROLE ;
538
544
current_role -> location = -1 ;
545
+ memberSpecs = list_make1 (current_role );
539
546
540
547
poptself .specified = GRANT_ROLE_SPECIFIED_ADMIN
541
548
| GRANT_ROLE_SPECIFIED_INHERIT
@@ -545,14 +552,28 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
545
552
poptself .set = false;
546
553
547
554
AddRoleMems (BOOTSTRAP_SUPERUSERID , stmt -> role , roleid ,
548
- list_make1 ( current_role ), list_make1_oid ( GetUserId ()) ,
555
+ memberSpecs , memberIds ,
549
556
BOOTSTRAP_SUPERUSERID , & poptself );
550
557
551
558
/*
552
559
* We must make the implicit grant visible to the code below, else
553
560
* the additional grants will fail.
554
561
*/
555
562
CommandCounterIncrement ();
563
+
564
+ /*
565
+ * Because of the implicit grant above, a CREATEROLE user who creates
566
+ * a role has the ability to grant that role back to themselves with
567
+ * the INHERIT or SET options, if they wish to inherit the role's
568
+ * privileges or be able to SET ROLE to it. The createrole_self_grant
569
+ * GUC can be used to make this happen automatically. This has no
570
+ * security implications since the same user is able to make the same
571
+ * grant using an explicit GRANT statement; it's just convenient.
572
+ */
573
+ if (createrole_self_grant_enabled )
574
+ AddRoleMems (currentUserId , stmt -> role , roleid ,
575
+ memberSpecs , memberIds ,
576
+ currentUserId , & createrole_self_grant_options );
556
577
}
557
578
558
579
/*
@@ -2414,3 +2435,73 @@ InitGrantRoleOptions(GrantRoleOptions *popt)
2414
2435
popt -> inherit = false;
2415
2436
popt -> set = true;
2416
2437
}
2438
+
2439
+ /*
2440
+ * GUC check_hook for createrole_self_grant
2441
+ */
2442
+ bool
2443
+ check_createrole_self_grant (char * * newval , void * * extra , GucSource source )
2444
+ {
2445
+ char * rawstring ;
2446
+ List * elemlist ;
2447
+ ListCell * l ;
2448
+ unsigned options = 0 ;
2449
+ unsigned * result ;
2450
+
2451
+ /* Need a modifiable copy of string */
2452
+ rawstring = pstrdup (* newval );
2453
+
2454
+ if (!SplitIdentifierString (rawstring , ',' , & elemlist ))
2455
+ {
2456
+ /* syntax error in list */
2457
+ GUC_check_errdetail ("List syntax is invalid." );
2458
+ pfree (rawstring );
2459
+ list_free (elemlist );
2460
+ return false;
2461
+ }
2462
+
2463
+ foreach (l , elemlist )
2464
+ {
2465
+ char * tok = (char * ) lfirst (l );
2466
+
2467
+ if (pg_strcasecmp (tok , "SET" ) == 0 )
2468
+ options |= GRANT_ROLE_SPECIFIED_SET ;
2469
+ else if (pg_strcasecmp (tok , "INHERIT" ) == 0 )
2470
+ options |= GRANT_ROLE_SPECIFIED_INHERIT ;
2471
+ else
2472
+ {
2473
+ GUC_check_errdetail ("Unrecognized key word: \"%s\"." , tok );
2474
+ pfree (rawstring );
2475
+ list_free (elemlist );
2476
+ return false;
2477
+ }
2478
+ }
2479
+
2480
+ pfree (rawstring );
2481
+ list_free (elemlist );
2482
+
2483
+ result = (unsigned * ) guc_malloc (LOG , sizeof (unsigned ));
2484
+ * result = options ;
2485
+ * extra = result ;
2486
+
2487
+ return true;
2488
+ }
2489
+
2490
+ /*
2491
+ * GUC assign_hook for createrole_self_grant
2492
+ */
2493
+ void
2494
+ assign_createrole_self_grant (const char * newval , void * extra )
2495
+ {
2496
+ unsigned options = * (unsigned * ) extra ;
2497
+
2498
+ createrole_self_grant_enabled = (options != 0 );
2499
+ createrole_self_grant_options .specified = GRANT_ROLE_SPECIFIED_ADMIN
2500
+ | GRANT_ROLE_SPECIFIED_INHERIT
2501
+ | GRANT_ROLE_SPECIFIED_SET ;
2502
+ createrole_self_grant_options .admin = false;
2503
+ createrole_self_grant_options .inherit =
2504
+ (options & GRANT_ROLE_SPECIFIED_INHERIT ) != 0 ;
2505
+ createrole_self_grant_options .set =
2506
+ (options & GRANT_ROLE_SPECIFIED_SET ) != 0 ;
2507
+ }
0 commit comments