@@ -50,6 +50,11 @@ static void copy_clog_xlog_xid(void);
50
50
static void set_frozenxids (void );
51
51
static void setup (char * argv0 ,bool live_check );
52
52
static void cleanup (void );
53
+ static void get_restricted_token (const char * progname );
54
+
55
+ #ifdef WIN32
56
+ static int CreateRestrictedProcess (char * cmd ,PROCESS_INFORMATION * processInfo ,const char * progname );
57
+ #endif
53
58
54
59
ClusterInfo old_cluster ,
55
60
new_cluster ;
@@ -67,6 +72,9 @@ char *output_files[] = {
67
72
NULL
68
73
};
69
74
75
+ #ifdef WIN32
76
+ static char * restrict_env ;
77
+ #endif
70
78
71
79
int
72
80
main (int argc ,char * * argv )
@@ -78,6 +86,8 @@ main(int argc, char **argv)
78
86
79
87
parseCommandLine (argc ,argv );
80
88
89
+ get_restricted_token (os_info .progname );
90
+
81
91
adjust_data_dir (& old_cluster );
82
92
adjust_data_dir (& new_cluster );
83
93
@@ -170,6 +180,162 @@ main(int argc, char **argv)
170
180
return 0 ;
171
181
}
172
182
183
+ #ifdef WIN32
184
+ typedef BOOL (WINAPI * __CreateRestrictedToken ) (HANDLE ,DWORD ,DWORD ,PSID_AND_ATTRIBUTES ,DWORD ,PLUID_AND_ATTRIBUTES ,DWORD ,PSID_AND_ATTRIBUTES ,PHANDLE );
185
+
186
+ /* Windows API define missing from some versions of MingW headers */
187
+ #ifndef DISABLE_MAX_PRIVILEGE
188
+ #define DISABLE_MAX_PRIVILEGE 0x1
189
+ #endif
190
+
191
+ /*
192
+ * Create a restricted token and execute the specified process with it.
193
+ *
194
+ * Returns 0 on failure, non-zero on success, same as CreateProcess().
195
+ *
196
+ * On NT4, or any other system not containing the required functions, will
197
+ * NOT execute anything.
198
+ */
199
+ static int
200
+ CreateRestrictedProcess (char * cmd ,PROCESS_INFORMATION * processInfo ,const char * progname )
201
+ {
202
+ BOOL b ;
203
+ STARTUPINFO si ;
204
+ HANDLE origToken ;
205
+ HANDLE restrictedToken ;
206
+ SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY };
207
+ SID_AND_ATTRIBUTES dropSids [2 ];
208
+ __CreateRestrictedToken _CreateRestrictedToken = NULL ;
209
+ HANDLE Advapi32Handle ;
210
+
211
+ ZeroMemory (& si ,sizeof (si ));
212
+ si .cb = sizeof (si );
213
+
214
+ Advapi32Handle = LoadLibrary ("ADVAPI32.DLL" );
215
+ if (Advapi32Handle != NULL )
216
+ {
217
+ _CreateRestrictedToken = (__CreateRestrictedToken )GetProcAddress (Advapi32Handle ,"CreateRestrictedToken" );
218
+ }
219
+
220
+ if (_CreateRestrictedToken == NULL )
221
+ {
222
+ fprintf (stderr ,_ ("%s: WARNING: cannot create restricted tokens on this platform\n" ),progname );
223
+ if (Advapi32Handle != NULL )
224
+ FreeLibrary (Advapi32Handle );
225
+ return 0 ;
226
+ }
227
+
228
+ /* Open the current token to use as a base for the restricted one */
229
+ if (!OpenProcessToken (GetCurrentProcess (),TOKEN_ALL_ACCESS ,& origToken ))
230
+ {
231
+ fprintf (stderr ,_ ("%s: could not open process token: error code %lu\n" ),progname ,GetLastError ());
232
+ return 0 ;
233
+ }
234
+
235
+ /* Allocate list of SIDs to remove */
236
+ ZeroMemory (& dropSids ,sizeof (dropSids ));
237
+ if (!AllocateAndInitializeSid (& NtAuthority ,2 ,
238
+ SECURITY_BUILTIN_DOMAIN_RID ,DOMAIN_ALIAS_RID_ADMINS ,0 ,0 ,0 ,0 ,0 ,
239
+ 0 ,& dropSids [0 ].Sid )||
240
+ !AllocateAndInitializeSid (& NtAuthority ,2 ,
241
+ SECURITY_BUILTIN_DOMAIN_RID ,DOMAIN_ALIAS_RID_POWER_USERS ,0 ,0 ,0 ,0 ,0 ,
242
+ 0 ,& dropSids [1 ].Sid ))
243
+ {
244
+ fprintf (stderr ,_ ("%s: could not to allocate SIDs: error code %lu\n" ),progname ,GetLastError ());
245
+ return 0 ;
246
+ }
247
+
248
+ b = _CreateRestrictedToken (origToken ,
249
+ DISABLE_MAX_PRIVILEGE ,
250
+ sizeof (dropSids ) /sizeof (dropSids [0 ]),
251
+ dropSids ,
252
+ 0 ,NULL ,
253
+ 0 ,NULL ,
254
+ & restrictedToken );
255
+
256
+ FreeSid (dropSids [1 ].Sid );
257
+ FreeSid (dropSids [0 ].Sid );
258
+ CloseHandle (origToken );
259
+ FreeLibrary (Advapi32Handle );
260
+
261
+ if (!b )
262
+ {
263
+ fprintf (stderr ,_ ("%s: could not create restricted token: error code %lu\n" ),progname ,GetLastError ());
264
+ return 0 ;
265
+ }
266
+
267
+ #ifndef __CYGWIN__
268
+ AddUserToTokenDacl (restrictedToken );
269
+ #endif
270
+
271
+ if (!CreateProcessAsUser (restrictedToken ,
272
+ NULL ,
273
+ cmd ,
274
+ NULL ,
275
+ NULL ,
276
+ TRUE,
277
+ CREATE_SUSPENDED ,
278
+ NULL ,
279
+ NULL ,
280
+ & si ,
281
+ processInfo ))
282
+
283
+ {
284
+ fprintf (stderr ,_ ("%s: could not start process for command \"%s\": error code %lu\n" ),progname ,cmd ,GetLastError ());
285
+ return 0 ;
286
+ }
287
+
288
+ return ResumeThread (processInfo -> hThread );
289
+ }
290
+ #endif
291
+
292
+ void
293
+ get_restricted_token (const char * progname )
294
+ {
295
+ #ifdef WIN32
296
+
297
+ /*
298
+ * Before we execute another program, make sure that we are running with a
299
+ * restricted token. If not, re-execute ourselves with one.
300
+ */
301
+
302
+ if ((restrict_env = getenv ("PG_RESTRICT_EXEC" ))== NULL
303
+ || strcmp (restrict_env ,"1" )!= 0 )
304
+ {
305
+ PROCESS_INFORMATION pi ;
306
+ char * cmdline ;
307
+
308
+ ZeroMemory (& pi ,sizeof (pi ));
309
+
310
+ cmdline = pg_strdup (GetCommandLine ());
311
+
312
+ putenv ("PG_RESTRICT_EXEC=1" );
313
+
314
+ if (!CreateRestrictedProcess (cmdline ,& pi ,progname ))
315
+ {
316
+ fprintf (stderr ,_ ("%s: could not re-execute with restricted token: error code %lu\n" ),progname ,GetLastError ());
317
+ }
318
+ else
319
+ {
320
+ /*
321
+ * Successfully re-execed. Now wait for child process to capture
322
+ * exitcode.
323
+ */
324
+ DWORD x ;
325
+
326
+ CloseHandle (pi .hThread );
327
+ WaitForSingleObject (pi .hProcess ,INFINITE );
328
+
329
+ if (!GetExitCodeProcess (pi .hProcess ,& x ))
330
+ {
331
+ fprintf (stderr ,_ ("%s: could not get exit code from subprocess: error code %lu\n" ),progname ,GetLastError ());
332
+ exit (1 );
333
+ }
334
+ exit (x );
335
+ }
336
+ }
337
+ #endif
338
+ }
173
339
174
340
static void
175
341
setup (char * argv0 ,bool live_check )