@@ -69,7 +69,6 @@ typedef struct MtmGucEntry
69
69
{
70
70
char key [GUC_KEY_MAXLEN ];
71
71
dlist_node list_node ;
72
- char * value ;
73
72
} MtmGucEntry ;
74
73
75
74
typedef struct {
@@ -83,8 +82,6 @@ bool MtmMonotonicSequences;
83
82
char * MtmRemoteFunctionsList ;
84
83
bool MtmIgnoreTablesWithoutPk ;
85
84
86
- fmgr_hook_type prev_fmgr_hook = NULL ;
87
-
88
85
static char MtmTempSchema [NAMEDATALEN ];
89
86
static bool TempDropRegistered ;
90
87
@@ -127,7 +124,7 @@ static void MtmProcessUtilitySender(PlannedStmt *pstmt,
127
124
QueryEnvironment * queryEnv , DestReceiver * dest ,
128
125
char * completionTag );
129
126
130
- static void MtmGucUpdate (const char * key , char * value );
127
+ static void MtmGucUpdate (const char * key );
131
128
static void MtmInitializeRemoteFunctionsMap (void );
132
129
static char * MtmGucSerialize (void );
133
130
static void MtmMakeRelationLocal (Oid relid , bool locked );
@@ -325,31 +322,24 @@ MtmGucInit(void)
325
322
oldcontext = MemoryContextSwitchTo (TopMemoryContext );
326
323
current_role = GetConfigOptionByName ("session_authorization" , NULL , false);
327
324
// XXX if (current_role && *current_role && strcmp(MtmDatabaseUser, current_role) != 0)
328
- MtmGucUpdate ("session_authorization" , current_role );
325
+ MtmGucUpdate ("session_authorization" );
329
326
MemoryContextSwitchTo (oldcontext );
330
327
}
331
328
332
329
static void
333
330
MtmGucDiscard ()
334
331
{
335
- dlist_iter iter ;
336
-
337
332
if (dlist_is_empty (& MtmGucList ))
338
333
return ;
339
334
340
- dlist_foreach (iter , & MtmGucList )
341
- {
342
- MtmGucEntry * cur_entry = dlist_container (MtmGucEntry , list_node , iter .cur );
343
- pfree (cur_entry -> value );
344
- }
345
335
dlist_init (& MtmGucList );
346
336
347
337
hash_destroy (MtmGucHash );
348
338
MtmGucHash = NULL ;
349
339
}
350
340
351
341
static inline void
352
- MtmGucUpdate (const char * key , char * value )
342
+ MtmGucUpdate (const char * key )
353
343
{
354
344
MtmGucEntry * hentry ;
355
345
bool found ;
@@ -359,11 +349,8 @@ MtmGucUpdate(const char *key, char *value)
359
349
360
350
hentry = (MtmGucEntry * )hash_search (MtmGucHash , key , HASH_ENTER , & found );
361
351
if (found )
362
- {
363
- pfree (hentry -> value );
364
352
dlist_delete (& hentry -> list_node );
365
- }
366
- hentry -> value = value ;
353
+
367
354
dlist_push_tail (& MtmGucList , & hentry -> list_node );
368
355
}
369
356
@@ -379,7 +366,6 @@ MtmGucRemove(const char *key)
379
366
hentry = (MtmGucEntry * )hash_search (MtmGucHash , key , HASH_FIND , & found );
380
367
if (found )
381
368
{
382
- pfree (hentry -> value );
383
369
dlist_delete (& hentry -> list_node );
384
370
hash_search (MtmGucHash , key , HASH_REMOVE , NULL );
385
371
}
@@ -398,7 +384,7 @@ MtmGucSet(VariableSetStmt *stmt, const char *queryStr)
398
384
switch (stmt -> kind )
399
385
{
400
386
case VAR_SET_VALUE :
401
- MtmGucUpdate (stmt -> name , ExtractSetVariableArgs ( stmt ) );
387
+ MtmGucUpdate (stmt -> name );
402
388
break ;
403
389
404
390
case VAR_SET_DEFAULT :
@@ -488,6 +474,10 @@ MtmGucSerialize(void)
488
474
StringInfo serialized_gucs = makeStringInfo ();
489
475
dlist_iter iter ;
490
476
const char * search_path ;
477
+ bool found ;
478
+ Oid ceUserId = GetUserId ();
479
+ Oid csUserId = GetSessionUserId ();
480
+ bool useRole = is_member_of_role (csUserId , ceUserId );
491
481
492
482
if (!MtmGucHash )
493
483
MtmGucInit ();
@@ -496,10 +486,34 @@ MtmGucSerialize(void)
496
486
appendStringInfoString (serialized_gucs , "RESET session_authorization; " );
497
487
appendStringInfo (serialized_gucs , "select mtm.set_temp_schema('%s'); " , MtmTempSchema );
498
488
489
+ hash_search (MtmGucHash , "session_authorization" , HASH_FIND , & found );
490
+ if (found )
491
+ {
492
+ MemoryContext oldcontext ;
493
+
494
+ oldcontext = MemoryContextSwitchTo (TopMemoryContext );
495
+ hash_search (MtmGucHash , "role" , HASH_FIND , & found );
496
+ if ((found ) && (ceUserId == csUserId ))
497
+ /*
498
+ * We need to do this because SET LOCAL return only WARNING if is used
499
+ * out of transaction block. DDL will be passed to another nodes and
500
+ * will set "role" variable at current node.
501
+ */
502
+ MtmGucRemove ("role" );
503
+ else if ((!found ) && (ceUserId != csUserId ) && useRole )
504
+ /*
505
+ * We need to do this because SECURITY DEFINER changed current user
506
+ * value quietly.
507
+ */
508
+ MtmGucUpdate ("role" );
509
+ MemoryContextSwitchTo (oldcontext );
510
+ }
511
+
499
512
dlist_foreach (iter , & MtmGucList )
500
513
{
501
514
MtmGucEntry * cur_entry = dlist_container (MtmGucEntry , list_node , iter .cur );
502
515
struct config_generic * gconf ;
516
+ const char * gucValue ;
503
517
504
518
if (strcmp (cur_entry -> key , "search_path" ) == 0 )
505
519
continue ;
@@ -508,19 +522,27 @@ MtmGucSerialize(void)
508
522
appendStringInfoString (serialized_gucs , cur_entry -> key );
509
523
appendStringInfoString (serialized_gucs , " TO " );
510
524
525
+ /* Current effective user can have more privileges than session user
526
+ * (increase in rights by SECURITY DEFINER, for example). In this case
527
+ * we need to set session authorization role in the current user value.
528
+ */
529
+ if (strcmp (cur_entry -> key , "session_authorization" ) == 0 )
530
+ gucValue = GetUserNameFromId (useRole ? csUserId : ceUserId , false);
531
+ else
532
+ gucValue = GetConfigOption (cur_entry -> key , false, true);
533
+
511
534
gconf = fing_guc_conf (cur_entry -> key );
512
535
if (gconf && (gconf -> vartype == PGC_STRING ||
513
536
gconf -> vartype == PGC_ENUM ||
514
537
(gconf -> flags & (GUC_UNIT_MEMORY | GUC_UNIT_TIME ))))
515
538
{
516
539
appendStringInfoString (serialized_gucs , "'" );
517
- appendStringInfoString (serialized_gucs , cur_entry -> value );
540
+ appendStringInfoString (serialized_gucs , gucValue );
518
541
appendStringInfoString (serialized_gucs , "'" );
519
542
}
520
543
else
521
- {
522
- appendStringInfoString (serialized_gucs , cur_entry -> value );
523
- }
544
+ appendStringInfoString (serialized_gucs , gucValue );
545
+
524
546
appendStringInfoString (serialized_gucs , "; " );
525
547
}
526
548
@@ -1499,37 +1521,3 @@ MtmToggleDML(void)
1499
1521
{
1500
1522
MtmTx .contains_dml = true;
1501
1523
}
1502
-
1503
- /*
1504
- * Multimaster need to adjust its preferences with authorization parameters,
1505
- * provided by SECURITY DEFINER.
1506
- */
1507
- void
1508
- multimaster_fmgr_hook (FmgrHookEventType event ,
1509
- FmgrInfo * flinfo , Datum * private )
1510
- {
1511
- Oid roleid ;
1512
- int sec_context ;
1513
- char * current_role ;
1514
- MemoryContext oldcontext ;
1515
-
1516
- if (prev_fmgr_hook )
1517
- (* prev_fmgr_hook ) (event , flinfo , private );
1518
-
1519
- switch (event )
1520
- {
1521
- case FHET_START :
1522
- case FHET_END :
1523
- case FHET_ABORT :
1524
- oldcontext = MemoryContextSwitchTo (TopMemoryContext );
1525
- GetUserIdAndSecContext (& roleid , & sec_context );
1526
- current_role = GetUserNameFromId (roleid , false);
1527
- MtmGucUpdate ("session_authorization" , current_role );
1528
- MemoryContextSwitchTo (oldcontext );
1529
- break ;
1530
-
1531
- default :
1532
- elog (ERROR , "unexpected event type: %d" , (int ) event );
1533
- break ;
1534
- }
1535
- }
0 commit comments