defect_pg_ctl_admin_win32.patch
text/plain
Filename: defect_pg_ctl_admin_win32.patch
Type: text/plain
Part: 0
Message:
Re: 9.2RC1 wraps this Thursday ...
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/bin/pg_ctl/pg_ctl.c | 156 | 0 |
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index af8d8b2..ff5d373 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -258,6 +258,121 @@ xstrdup(const char *s)
}
/*
+ * Call GetTokenInformation() on a token and return a dynamically sized
+ * buffer with the information in it. This buffer must be free():d by
+ * the calling function!
+ */
+static BOOL
+pgwin32_get_dynamic_tokeninfo(HANDLE token, TOKEN_INFORMATION_CLASS class,
+ char **InfoBuffer, char *errbuf, int errsize)
+{
+ DWORD InfoBufferSize;
+
+ if (GetTokenInformation(token, class, NULL, 0, &InfoBufferSize))
+ {
+ snprintf(errbuf, errsize, "could not get token information: got zero size\n");
+ return FALSE;
+ }
+
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ {
+ snprintf(errbuf, errsize, "could not get token information: error code %lu\n",
+ GetLastError());
+ return FALSE;
+ }
+
+ *InfoBuffer = malloc(InfoBufferSize);
+ if (*InfoBuffer == NULL)
+ {
+ snprintf(errbuf, errsize, "could not allocate %d bytes for token information\n",
+ (int) InfoBufferSize);
+ return FALSE;
+ }
+
+ if (!GetTokenInformation(token, class, *InfoBuffer,
+ InfoBufferSize, &InfoBufferSize))
+ {
+ snprintf(errbuf, errsize, "could not get token information: error code %lu\n",
+ GetLastError());
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/*
+ * Returns nonzero if the current user has administrative privileges,
+ * or zero if not.
+ */
+static int
+pgwin32_is_admin(void)
+{
+ HANDLE AccessToken;
+ char *InfoBuffer = NULL;
+ char errbuf[256];
+ PTOKEN_GROUPS Groups;
+ PSID AdministratorsSid;
+ PSID PowerUsersSid;
+ SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
+ UINT x;
+ BOOL success;
+
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &AccessToken))
+ {
+ write_stderr("could not open process token: error code %lu\n",
+ GetLastError());
+ exit(1);
+ }
+
+ if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenGroups,
+ &InfoBuffer, errbuf, sizeof(errbuf)))
+ {
+ write_stderr("%s", errbuf);
+ exit(1);
+ }
+
+ Groups = (PTOKEN_GROUPS) InfoBuffer;
+
+ CloseHandle(AccessToken);
+
+ if (!AllocateAndInitializeSid(&NtAuthority, 2,
+ SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
+ 0, &AdministratorsSid))
+ {
+ write_stderr("could not get SID for Administrators group: error code %lu\n",
+ GetLastError());
+ exit(1);
+ }
+
+ if (!AllocateAndInitializeSid(&NtAuthority, 2,
+ SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
+ 0, &PowerUsersSid))
+ {
+ write_stderr("could not get SID for PowerUsers group: error code %lu\n",
+ GetLastError());
+ exit(1);
+ }
+
+ success = FALSE;
+
+ for (x = 0; x < Groups->GroupCount; x++)
+ {
+ if ((EqualSid(AdministratorsSid, Groups->Groups[x].Sid) && (Groups->Groups[x].Attributes & SE_GROUP_ENABLED)) ||
+ (EqualSid(PowerUsersSid, Groups->Groups[x].Sid) && (Groups->Groups[x].Attributes & SE_GROUP_ENABLED)))
+ {
+ success = TRUE;
+ break;
+ }
+ }
+
+ free(InfoBuffer);
+ FreeSid(AdministratorsSid);
+ FreeSid(PowerUsersSid);
+ return success;
+}
+
+/*
* Given an already-localized string, print it to stdout unless the
* user has specified that no messages should be printed.
*/
@@ -2015,6 +2130,47 @@ main(int argc, char **argv)
progname);
exit(1);
}
+#else
+
+ /*
+ * Before we execute another program, make sure that we are running with a
+ * restricted token. If not, re-execute ourselves with one.
+ */
+ if (pgwin32_is_admin())
+ {
+ PROCESS_INFORMATION pi;
+ char *cmdline;
+
+ ZeroMemory(&pi, sizeof(pi));
+
+ cmdline = xstrdup(GetCommandLine());
+
+ putenv("PG_RESTRICT_EXEC=1");
+
+ if (!CreateRestrictedProcess(cmdline, &pi, false))
+ {
+ write_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))
+ {
+ write_stderr(_("%s: could not get exit code from subprocess: error code %lu\n"), progname, GetLastError());
+ exit(1);
+ }
+
+ exit(x);
+ }
+ }
#endif
/*