Index: bin/initdb/initdb.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/initdb/initdb.c,v
retrieving revision 1.106
diff -c -r1.106 initdb.c
*** bin/initdb/initdb.c	5 Jan 2006 10:07:46 -0000	1.106
--- bin/initdb/initdb.c	5 Feb 2006 15:02:23 -0000
***************
*** 95,100 ****
--- 95,103 ----
  static bool debug = false;
  static bool noclean = false;
  static bool show_setting = false;
+ #ifdef WIN32
+ static bool restricted_exec = false;
+ #endif
  
  
  /* internal vars */
***************
*** 192,197 ****
--- 195,203 ----
  static bool chklocale(const char *locale);
  static void setlocales(void);
  static void usage(const char *progname);
+ #ifdef WIN32
+ static int CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo);
+ #endif
  
  
  /*
***************
*** 2239,2244 ****
--- 2245,2335 ----
  
  }
  
+ #ifdef WIN32
+ /* MingW headers are incomplete */
+ typedef WINAPI BOOL (*__CreateRestrictedToken)(HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
+ #define DISABLE_MAX_PRIVILEGE   0x1 
+ 
+ /*
+  * Create a restricted token and execute the specified process with it.
+  *
+  * Returns 0 on failure, non-zero on success, same as CreateProcess().
+  *
+  * On NT4, or any other system not containing the require functions, will
+  * NOT execute anything.
+  */
+ static int 
+ CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo)
+ {
+     BOOL b;
+     STARTUPINFO si;
+     HANDLE origToken;
+     HANDLE restrictedToken;
+     SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
+     SID_AND_ATTRIBUTES dropSids[2];
+     __CreateRestrictedToken _CreateRestrictedToken = NULL;
+     HANDLE Advapi32Handle;
+     
+     ZeroMemory(&si, sizeof(si));
+     si.cb = sizeof(si);
+ 
+     Advapi32Handle = LoadLibrary("ADVAPI32.DLL");
+     if (Advapi32Handle != NULL)
+     {
+         _CreateRestrictedToken = (__CreateRestrictedToken) GetProcAddress(Advapi32Handle, "CreateRestrictedToken");
+     }
+ 
+     if (_CreateRestrictedToken == NULL)
+     {
+         fprintf(stderr,"WARNING: Unable to create restricted tokens on this platform\n");
+         if (Advapi32Handle != NULL)
+             FreeLibrary(Advapi32Handle);
+         return 0;
+     }
+ 
+     /* Open the current token to use as a base for the restricted one */
+     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken))
+     {
+         fprintf(stderr, "Failed to open process token: %lu\n", GetLastError());
+         return 0;
+     }
+ 
+     /* Allocate list of SIDs to remove */
+     ZeroMemory(&dropSids, sizeof(dropSids));
+     if (!AllocateAndInitializeSid(&NtAuthority, 2,
+             SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0,0,0,0,0,
+             0, &dropSids[0].Sid) ||
+         !AllocateAndInitializeSid(&NtAuthority, 2, 
+             SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0,0,0,0,0,
+             0, &dropSids[1].Sid))
+     {
+         fprintf(stderr,"Failed to allocate SIDs: %lu\n", GetLastError());
+         return 0;
+     }
+ 
+     b = _CreateRestrictedToken(origToken,
+             DISABLE_MAX_PRIVILEGE,
+             sizeof(dropSids)/sizeof(dropSids[0]),
+             dropSids,
+             0, NULL,
+             0, NULL,
+             &restrictedToken);
+     
+     FreeSid(dropSids[1].Sid);
+     FreeSid(dropSids[0].Sid);
+     CloseHandle(origToken);
+     FreeLibrary(Advapi32Handle);
+ 
+     if (!b)
+     {
+         fprintf(stderr,"Failed to create restricted token: %lu\n", GetLastError());
+         return 0;
+     }
+ 
+     return CreateProcessAsUser(restrictedToken, NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, processInfo);
+ }
+ #endif
+ 
  /*
   * print help text
   */
***************
*** 2295,2300 ****
--- 2386,2394 ----
  		{"auth", required_argument, NULL, 'A'},
  		{"pwprompt", no_argument, NULL, 'W'},
  		{"pwfile", required_argument, NULL, 9},
+ #ifdef WIN32
+         {"restrictedexec", no_argument, NULL, 10},
+ #endif
  		{"username", required_argument, NULL, 'U'},
  		{"help", no_argument, NULL, '?'},
  		{"version", no_argument, NULL, 'V'},
***************
*** 2403,2408 ****
--- 2497,2507 ----
  			case 9:
  				pwfilename = xstrdup(optarg);
  				break;
+ #ifdef WIN32
+             case 10:
+                 restricted_exec = true;
+                 break;
+ #endif
  			case 's':
  				show_setting = true;
  				break;
***************
*** 2497,2502 ****
--- 2596,2639 ----
  	pg_data_native = pg_data;
  	canonicalize_path(pg_data);
  
+ #ifdef WIN32
+     /* 
+      * Before we execute another program, make sure that we are running with a 
+      * restricted token. If not, re-execute ourselves with one.
+      */
+     if (!restricted_exec)
+     {
+         PROCESS_INFORMATION pi;
+         char *cmdline;
+         
+         ZeroMemory(&pi, sizeof(pi));
+ 
+         cmdline = pg_malloc(strlen(GetCommandLine()) + 19);
+         strcpy(cmdline, GetCommandLine());
+         strcat(cmdline, " --restrictedexec");
+         
+         if (!CreateRestrictedProcess(cmdline, &pi))
+         {
+             fprintf(stderr,"Failed to re-exec with restricted token: %lu.\n", GetLastError());
+         }
+         else
+         {
+             /* Successfully re-execed. Now wait for child process to capture exitcode. */
+             DWORD x;
+             
+             CloseHandle(pi.hThread);
+             WaitForSingleObject(pi.hProcess, INFINITE);
+ 
+             if (!GetExitCodeProcess(pi.hProcess, &x))
+             {
+                 fprintf(stderr,"Failed to get exit code from subprocess: %lu\n", GetLastError());
+                 exit(1);
+             }
+             exit(x);
+         }
+     }
+ #endif
+ 
  	/*
  	 * we have to set PGDATA for postgres rather than pass it on the command
  	 * line to avoid dumb quoting problems on Windows, and we would especially
