#include "postgres_fe.h"
#include "pg_upgrade.h"
+#include "common/restricted_token.h"
#ifdef HAVE_LANGINFO_H
#include <langinfo.h>
parseCommandLine(argc, argv);
+ get_restricted_token(os_info.progname);
+
adjust_data_dir(&old_cluster);
adjust_data_dir(&new_cluster);
#endif
#include "catalog/catalog.h"
+#include "common/restricted_token.h"
#include "common/username.h"
#include "mb/pg_wchar.h"
#include "getaddrinfo.h"
static const char *boot_options = "-F";
static const char *backend_options = "--single -F -O -c search_path=pg_catalog -c exit_on_error=true";
-#ifdef WIN32
-char *restrict_env;
-#endif
static const char *subdirs[] = {
"global",
"pg_xlog",
static bool check_locale_encoding(const char *locale, int encoding);
static void setlocales(void);
static void usage(const char *progname);
-void get_restricted_token(void);
void setup_pgdata(void);
void setup_bin_paths(const char *argv0);
void setup_data_file_paths(void);
void warn_on_mount_point(int error);
void initialize_data_directory(void);
-
-#ifdef WIN32
-static int CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo);
-#endif
-
-
/*
* macros for running pipes to postgres
*/
#endif
}
-#ifdef WIN32
-typedef BOOL (WINAPI * __CreateRestrictedToken) (HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
-
-/* Windows API define missing from some versions of MingW headers */
-#ifndef DISABLE_MAX_PRIVILEGE
-#define DISABLE_MAX_PRIVILEGE 0x1
-#endif
-
-/*
- * 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 required 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, _("%s: WARNING: cannot create restricted tokens on this platform\n"), progname);
- 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, _("%s: could not open process token: error code %lu\n"), progname, 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, _("%s: could not allocate SIDs: error code %lu\n"),
- progname, 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, _("%s: could not create restricted token: error code %lu\n"), progname, GetLastError());
- return 0;
- }
-
-#ifndef __CYGWIN__
- AddUserToTokenDacl(restrictedToken);
-#endif
-
- if (!CreateProcessAsUser(restrictedToken,
- NULL,
- cmd,
- NULL,
- NULL,
- TRUE,
- CREATE_SUSPENDED,
- NULL,
- NULL,
- &si,
- processInfo))
-
- {
- fprintf(stderr, _("%s: could not start process for command \"%s\": error code %lu\n"), progname, cmd, GetLastError());
- return 0;
- }
-
- return ResumeThread(processInfo->hThread);
-}
-#endif
-
/*
* print help text
*/
}
}
-void
-get_restricted_token(void)
-{
-#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 ((restrict_env = getenv("PG_RESTRICT_EXEC")) == NULL
- || strcmp(restrict_env, "1") != 0)
- {
- PROCESS_INFORMATION pi;
- char *cmdline;
-
- ZeroMemory(&pi, sizeof(pi));
-
- cmdline = pg_strdup(GetCommandLine());
-
- putenv("PG_RESTRICT_EXEC=1");
-
- if (!CreateRestrictedProcess(cmdline, &pi))
- {
- fprintf(stderr, _("%s: could not re-execute with restricted token: error code %lu\n"), progname, 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, _("%s: could not get exit code from subprocess: error code %lu\n"), progname, GetLastError());
- exit(1);
- }
- exit(x);
- }
- }
-#endif
-}
void
setup_pgdata(void)
check_need_password(authmethodlocal, authmethodhost);
- get_restricted_token();
+ get_restricted_token(progname);
setup_pgdata();
#include "catalog/catversion.h"
#include "catalog/pg_control.h"
#include "common/fe_memutils.h"
+#include "common/restricted_token.h"
#include "storage/large_object.h"
#include "pg_getopt.h"
}
#endif
+ get_restricted_token(progname);
+
if (chdir(DataDir) < 0)
{
fprintf(stderr, _("%s: could not change directory to \"%s\": %s\n"),
OBJS_COMMON = exec.o pg_crc.o pg_lzcompress.o pgfnames.o psprintf.o relpath.o \
rmtree.o string.o username.o wait_error.o
-OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o
+OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o restricted_token.o
OBJS_SRV = $(OBJS_COMMON:%.o=%_srv.o)
--- /dev/null
+/*-------------------------------------------------------------------------
+ *
+ * restricted_token.c
+ * helper routine to ensure restricted token on Windows
+ *
+ *
+ * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/restricted_token.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#error "This file is not expected to be compiled for backend code"
+#endif
+
+#include "postgres_fe.h"
+
+#include "common/restricted_token.h"
+
+#ifdef WIN32
+
+/* internal vars */
+char *restrict_env;
+
+typedef BOOL (WINAPI * __CreateRestrictedToken) (HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
+
+/* Windows API define missing from some versions of MingW headers */
+#ifndef DISABLE_MAX_PRIVILEGE
+#define DISABLE_MAX_PRIVILEGE 0x1
+#endif
+
+/*
+ * Create a restricted token and execute the specified process with it.
+ *
+ * Returns restricted token on success and 0 on failure.
+ *
+ * On NT4, or any other system not containing the required functions, will
+ * NOT execute anything.
+ */
+HANDLE
+CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, const char *progname)
+{
+ 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, _("%s: WARNING: cannot create restricted tokens on this platform\n"), progname);
+ 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, _("%s: could not open process token: error code %lu\n"), progname, 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, _("%s: could not allocate SIDs: error code %lu\n"),
+ progname, 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, _("%s: could not create restricted token: error code %lu\n"),
+ progname, GetLastError());
+ return 0;
+ }
+
+#ifndef __CYGWIN__
+ AddUserToTokenDacl(restrictedToken);
+#endif
+
+ if (!CreateProcessAsUser(restrictedToken,
+ NULL,
+ cmd,
+ NULL,
+ NULL,
+ TRUE,
+ CREATE_SUSPENDED,
+ NULL,
+ NULL,
+ &si,
+ processInfo))
+
+ {
+ fprintf(stderr, _("%s: could not start process for command \"%s\": error code %lu\n"), progname, cmd, GetLastError());
+ return 0;
+ }
+
+ ResumeThread(processInfo->hThread);
+ return restrictedToken;
+}
+#endif
+
+/*
+ * On Windows make sure that we are running with a restricted token,
+ * On other platforms do nothing.
+ */
+void
+get_restricted_token(const char *progname)
+{
+#ifdef WIN32
+ HANDLE restrictedToken;
+
+ /*
+ * Before we execute another program, make sure that we are running with a
+ * restricted token. If not, re-execute ourselves with one.
+ */
+
+ if ((restrict_env = getenv("PG_RESTRICT_EXEC")) == NULL
+ || strcmp(restrict_env, "1") != 0)
+ {
+ PROCESS_INFORMATION pi;
+ char *cmdline;
+
+ ZeroMemory(&pi, sizeof(pi));
+
+ cmdline = pg_strdup(GetCommandLine());
+
+ putenv("PG_RESTRICT_EXEC=1");
+
+ if ((restrictedToken = CreateRestrictedProcess(cmdline, &pi, progname)) == 0)
+ {
+ fprintf(stderr, _("%s: could not re-execute with restricted token: error code %lu\n"), progname, GetLastError());
+ }
+ else
+ {
+ /*
+ * Successfully re-execed. Now wait for child process to capture
+ * exitcode.
+ */
+ DWORD x;
+
+ CloseHandle(restrictedToken);
+ CloseHandle(pi.hThread);
+ WaitForSingleObject(pi.hProcess, INFINITE);
+
+ if (!GetExitCodeProcess(pi.hProcess, &x))
+ {
+ fprintf(stderr, _("%s: could not get exit code from subprocess: error code %lu\n"), progname, GetLastError());
+ exit(1);
+ }
+ exit(x);
+ }
+ }
+#endif
+}
--- /dev/null
+/*
+ * restricted_token.h
+ * helper routine to ensure restricted token on Windows
+ *
+ * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/restricted_token.h
+ */
+#ifndef COMMON_RESTRICTED_TOKEN_H
+#define COMMON_RESTRICTED_TOKEN_H
+
+/*
+ * On Windows make sure that we are running with a restricted token,
+ * On other platforms do nothing.
+ */
+void get_restricted_token(const char *progname);
+
+#ifdef WIN32
+/* Create a restricted token and execute the specified process with it. */
+HANDLE CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo, const char *progname);
+#endif
+
+#endif /* COMMON_RESTRICTED_TOKEN_H */
#include <sys/resource.h>
#endif
+#include "common/restricted_token.h"
#include "common/username.h"
#include "getopt_long.h"
#include "libpq/pqcomm.h" /* needed for UNIXSOCK_PATH() */
static void status(const char *fmt,...) pg_attribute_printf(1, 2);
static void psql_command(const char *database, const char *query,...) pg_attribute_printf(2, 3);
-#ifdef WIN32
-typedef BOOL (WINAPI * __CreateRestrictedToken) (HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
-
-/* Windows API define missing from some versions of MingW headers */
-#ifndef DISABLE_MAX_PRIVILEGE
-#define DISABLE_MAX_PRIVILEGE 0x1
-#endif
-#endif
-
/*
* allow core files if possible.
*/
/* in parent */
return pid;
#else
- char *cmdline2;
- BOOL b;
- STARTUPINFO si;
- PROCESS_INFORMATION pi;
- 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)
- {
- if (Advapi32Handle != NULL)
- FreeLibrary(Advapi32Handle);
- fprintf(stderr, _("%s: cannot create restricted tokens on this platform\n"),
- progname);
- exit(2);
- }
-
- /* Open the current token to use as base for the restricted one */
- if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken))
- {
- fprintf(stderr, _("could not open process token: error code %lu\n"),
- GetLastError());
- exit(2);
- }
-
- /* 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, _("could not allocate SIDs: error code %lu\n"), GetLastError());
- exit(2);
- }
-
- 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, _("could not create restricted token: error code %lu\n"),
- GetLastError());
- exit(2);
- }
+ PROCESS_INFORMATION pi;
+ char *cmdline2;
+ HANDLE restrictedToken;
+ memset(&pi, 0, sizeof(pi));
cmdline2 = psprintf("cmd /c \"%s\"", cmdline);
-#ifndef __CYGWIN__
- AddUserToTokenDacl(restrictedToken);
-#endif
-
- if (!CreateProcessAsUser(restrictedToken,
- NULL,
- cmdline2,
- NULL,
- NULL,
- TRUE,
- CREATE_SUSPENDED,
- NULL,
- NULL,
- &si,
- &pi))
- {
- fprintf(stderr, _("could not start process for \"%s\": error code %lu\n"),
- cmdline2, GetLastError());
+ if((restrictedToken =
+ CreateRestrictedProcess(cmdline2, &pi, progname)) == 0)
exit(2);
- }
-
- free(cmdline2);
- ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
return pi.hProcess;
#endif
exec.c pg_crc.c pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c
string.c username.c wait_error.c);
- our @pgcommonfrontendfiles = (@pgcommonallfiles, qw(fe_memutils.c));
+ our @pgcommonfrontendfiles = (@pgcommonallfiles, qw(fe_memutils.c
+ restricted_token.c));
our @pgcommonbkndfiles = @pgcommonallfiles;