|
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 | staticbooldebug= false;
|
96 | 96 | staticboolnoclean= false;
|
97 | 97 | staticboolshow_setting= false;
|
| 98 | +#ifdefWIN32 |
| 99 | +staticboolrestricted_exec= false; |
| 100 | +#endif |
98 | 101 |
|
99 | 102 |
|
100 | 103 | /* internal vars */
|
@@ -192,6 +195,9 @@ static intlocale_date_order(const char *locale);
|
192 | 195 | staticboolchklocale(constchar*locale);
|
193 | 196 | staticvoidsetlocales(void);
|
194 | 197 | staticvoidusage(constchar*progname);
|
| 198 | +#ifdefWIN32 |
| 199 | +staticintCreateRestrictedProcess(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 | +#ifdefWIN32 |
| 2249 | +/* MingW headers are incomplete */ |
| 2250 | +typedefWINAPIBOOL (*__CreateRestrictedToken)(HANDLE,DWORD,DWORD,PSID_AND_ATTRIBUTES,DWORD,PLUID_AND_ATTRIBUTES,DWORD,PSID_AND_ATTRIBUTES,PHANDLE); |
| 2251 | +#defineDISABLE_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 | +staticint |
| 2262 | +CreateRestrictedProcess(char*cmd,PROCESS_INFORMATION*processInfo) |
| 2263 | +{ |
| 2264 | +BOOLb; |
| 2265 | +STARTUPINFOsi; |
| 2266 | +HANDLEorigToken; |
| 2267 | +HANDLErestrictedToken; |
| 2268 | +SID_IDENTIFIER_AUTHORITYNtAuthority= {SECURITY_NT_AUTHORITY}; |
| 2269 | +SID_AND_ATTRIBUTESdropSids[2]; |
| 2270 | +__CreateRestrictedToken_CreateRestrictedToken=NULL; |
| 2271 | +HANDLEAdvapi32Handle; |
| 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 | +return0; |
| 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 | +return0; |
| 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 | +return0; |
| 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 | +return0; |
| 2327 | + } |
| 2328 | + |
| 2329 | +returnCreateProcessAsUser(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 | +#ifdefWIN32 |
| 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 | case9:
|
2404 | 2498 | pwfilename=xstrdup(optarg);
|
2405 | 2499 | break;
|
| 2500 | +#ifdefWIN32 |
| 2501 | +case10: |
| 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 | +#ifdefWIN32 |
| 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_INFORMATIONpi; |
| 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 | +DWORDx; |
| 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
|
|