|
42 | 42 | * Portions Copyright (c) 1994, Regents of the University of California
|
43 | 43 | * Portions taken from FreeBSD.
|
44 | 44 | *
|
45 |
| - * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.107 2006/01/27 19:01:15 tgl Exp $ |
| 45 | + * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.108 2006/02/10 22:05:42 tgl Exp $ |
46 | 46 | *
|
47 | 47 | *-------------------------------------------------------------------------
|
48 | 48 | */
|
@@ -95,6 +95,9 @@ static char *authmethod = "";
|
95 | 95 | static bool debug = false;
|
96 | 96 | static bool noclean = false;
|
97 | 97 | static bool show_setting = false;
|
| 98 | +#ifdef WIN32 |
| 99 | +static bool restricted_exec = false; |
| 100 | +#endif |
98 | 101 |
|
99 | 102 |
|
100 | 103 | /* internal vars */
|
@@ -192,6 +195,9 @@ static int locale_date_order(const char *locale);
|
192 | 195 | static bool chklocale(const char *locale);
|
193 | 196 | static void setlocales(void);
|
194 | 197 | static void usage(const char *progname);
|
| 198 | +#ifdef WIN32 |
| 199 | +static int CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo); |
| 200 | +#endif |
195 | 201 |
|
196 | 202 |
|
197 | 203 | /*
|
@@ -2239,6 +2245,91 @@ setlocales(void)
|
2239 | 2245 |
|
2240 | 2246 | }
|
2241 | 2247 |
|
| 2248 | +#ifdef WIN32 |
| 2249 | +/* MingW headers are incomplete */ |
| 2250 | +typedef WINAPI BOOL (*__CreateRestrictedToken)(HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE); |
| 2251 | +#define DISABLE_MAX_PRIVILEGE 0x1 |
| 2252 | + |
| 2253 | +/* |
| 2254 | + * Create a restricted token and execute the specified process with it. |
| 2255 | + * |
| 2256 | + * Returns 0 on failure, non-zero on success, same as CreateProcess(). |
| 2257 | + * |
| 2258 | + * On NT4, or any other system not containing the required functions, will |
| 2259 | + * NOT execute anything. |
| 2260 | + */ |
| 2261 | +static int |
| 2262 | +CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo) |
| 2263 | +{ |
| 2264 | + BOOL b; |
| 2265 | + STARTUPINFO si; |
| 2266 | + HANDLE origToken; |
| 2267 | + HANDLE restrictedToken; |
| 2268 | + SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; |
| 2269 | + SID_AND_ATTRIBUTES dropSids[2]; |
| 2270 | + __CreateRestrictedToken _CreateRestrictedToken = NULL; |
| 2271 | + HANDLE Advapi32Handle; |
| 2272 | + |
| 2273 | + ZeroMemory(&si, sizeof(si)); |
| 2274 | + si.cb = sizeof(si); |
| 2275 | + |
| 2276 | + Advapi32Handle = LoadLibrary("ADVAPI32.DLL"); |
| 2277 | + if (Advapi32Handle != NULL) |
| 2278 | + { |
| 2279 | + _CreateRestrictedToken = (__CreateRestrictedToken) GetProcAddress(Advapi32Handle, "CreateRestrictedToken"); |
| 2280 | + } |
| 2281 | + |
| 2282 | + if (_CreateRestrictedToken == NULL) |
| 2283 | + { |
| 2284 | + fprintf(stderr,"WARNING: Unable to create restricted tokens on this platform\n"); |
| 2285 | + if (Advapi32Handle != NULL) |
| 2286 | + FreeLibrary(Advapi32Handle); |
| 2287 | + return 0; |
| 2288 | + } |
| 2289 | + |
| 2290 | + /* Open the current token to use as a base for the restricted one */ |
| 2291 | + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken)) |
| 2292 | + { |
| 2293 | + fprintf(stderr, "Failed to open process token: %lu\n", GetLastError()); |
| 2294 | + return 0; |
| 2295 | + } |
| 2296 | + |
| 2297 | + /* Allocate list of SIDs to remove */ |
| 2298 | + ZeroMemory(&dropSids, sizeof(dropSids)); |
| 2299 | + if (!AllocateAndInitializeSid(&NtAuthority, 2, |
| 2300 | + SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0,0,0,0,0, |
| 2301 | + 0, &dropSids[0].Sid) || |
| 2302 | + !AllocateAndInitializeSid(&NtAuthority, 2, |
| 2303 | + SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0,0,0,0,0, |
| 2304 | + 0, &dropSids[1].Sid)) |
| 2305 | + { |
| 2306 | + fprintf(stderr,"Failed to allocate SIDs: %lu\n", GetLastError()); |
| 2307 | + return 0; |
| 2308 | + } |
| 2309 | + |
| 2310 | + b = _CreateRestrictedToken(origToken, |
| 2311 | + DISABLE_MAX_PRIVILEGE, |
| 2312 | + sizeof(dropSids)/sizeof(dropSids[0]), |
| 2313 | + dropSids, |
| 2314 | + 0, NULL, |
| 2315 | + 0, NULL, |
| 2316 | + &restrictedToken); |
| 2317 | + |
| 2318 | + FreeSid(dropSids[1].Sid); |
| 2319 | + FreeSid(dropSids[0].Sid); |
| 2320 | + CloseHandle(origToken); |
| 2321 | + FreeLibrary(Advapi32Handle); |
| 2322 | + |
| 2323 | + if (!b) |
| 2324 | + { |
| 2325 | + fprintf(stderr,"Failed to create restricted token: %lu\n", GetLastError()); |
| 2326 | + return 0; |
| 2327 | + } |
| 2328 | + |
| 2329 | + return CreateProcessAsUser(restrictedToken, NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, processInfo); |
| 2330 | +} |
| 2331 | +#endif |
| 2332 | + |
2242 | 2333 | /*
|
2243 | 2334 | * print help text
|
2244 | 2335 | */
|
@@ -2295,6 +2386,9 @@ main(int argc, char *argv[])
|
2295 | 2386 | {"auth", required_argument, NULL, 'A'},
|
2296 | 2387 | {"pwprompt", no_argument, NULL, 'W'},
|
2297 | 2388 | {"pwfile", required_argument, NULL, 9},
|
| 2389 | +#ifdef WIN32 |
| 2390 | + {"restrictedexec", no_argument, NULL, 10}, |
| 2391 | +#endif |
2298 | 2392 | {"username", required_argument, NULL, 'U'},
|
2299 | 2393 | {"help", no_argument, NULL, '?'},
|
2300 | 2394 | {"version", no_argument, NULL, 'V'},
|
@@ -2403,6 +2497,11 @@ main(int argc, char *argv[])
|
2403 | 2497 | case 9:
|
2404 | 2498 | pwfilename = xstrdup(optarg);
|
2405 | 2499 | break;
|
| 2500 | +#ifdef WIN32 |
| 2501 | + case 10: |
| 2502 | + restricted_exec = true; |
| 2503 | + break; |
| 2504 | +#endif |
2406 | 2505 | case 's':
|
2407 | 2506 | show_setting = true;
|
2408 | 2507 | break;
|
@@ -2497,6 +2596,44 @@ main(int argc, char *argv[])
|
2497 | 2596 | pg_data_native = pg_data;
|
2498 | 2597 | canonicalize_path(pg_data);
|
2499 | 2598 |
|
| 2599 | +#ifdef WIN32 |
| 2600 | + /* |
| 2601 | + * Before we execute another program, make sure that we are running with a |
| 2602 | + * restricted token. If not, re-execute ourselves with one. |
| 2603 | + */ |
| 2604 | + if (!restricted_exec) |
| 2605 | + { |
| 2606 | + PROCESS_INFORMATION pi; |
| 2607 | + char *cmdline; |
| 2608 | + |
| 2609 | + ZeroMemory(&pi, sizeof(pi)); |
| 2610 | + |
| 2611 | + cmdline = pg_malloc(strlen(GetCommandLine()) + 19); |
| 2612 | + strcpy(cmdline, GetCommandLine()); |
| 2613 | + strcat(cmdline, " --restrictedexec"); |
| 2614 | + |
| 2615 | + if (!CreateRestrictedProcess(cmdline, &pi)) |
| 2616 | + { |
| 2617 | + fprintf(stderr,"Failed to re-exec with restricted token: %lu.\n", GetLastError()); |
| 2618 | + } |
| 2619 | + else |
| 2620 | + { |
| 2621 | + /* Successfully re-execed. Now wait for child process to capture exitcode. */ |
| 2622 | + DWORD x; |
| 2623 | + |
| 2624 | + CloseHandle(pi.hThread); |
| 2625 | + WaitForSingleObject(pi.hProcess, INFINITE); |
| 2626 | + |
| 2627 | + if (!GetExitCodeProcess(pi.hProcess, &x)) |
| 2628 | + { |
| 2629 | + fprintf(stderr,"Failed to get exit code from subprocess: %lu\n", GetLastError()); |
| 2630 | + exit(1); |
| 2631 | + } |
| 2632 | + exit(x); |
| 2633 | + } |
| 2634 | + } |
| 2635 | +#endif |
| 2636 | + |
2500 | 2637 | /*
|
2501 | 2638 | * we have to set PGDATA for postgres rather than pass it on the command
|
2502 | 2639 | * line to avoid dumb quoting problems on Windows, and we would especially
|
|
0 commit comments