mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Replace direct fprintf(stderr) calls by write_stderr(), and cause this
routine to do something appropriate on Win32. Also, add a security check on Win32 that parallels the can't-run-as-root check on Unix. Magnus Hagander
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
# Makefile for port/win32
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# $PostgreSQL: pgsql/src/backend/port/win32/Makefile,v 1.4 2004/04/12 16:19:18 momjian Exp $
|
||||
# $PostgreSQL: pgsql/src/backend/port/win32/Makefile,v 1.5 2004/06/24 21:02:42 tgl Exp $
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
@@ -12,7 +12,7 @@ subdir = src/backend/port/win32
|
||||
top_builddir = ../../../..
|
||||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
OBJS = sema.o shmem.o timer.o socket.o signal.o
|
||||
OBJS = sema.o shmem.o timer.o socket.o signal.o security.o
|
||||
|
||||
all: SUBSYS.o
|
||||
|
||||
|
||||
184
src/backend/port/win32/security.c
Normal file
184
src/backend/port/win32/security.c
Normal file
@@ -0,0 +1,184 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* security.c
|
||||
* Microsoft Windows Win32 Security Support Functions
|
||||
*
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/port/win32/security.c,v 1.1 2004/06/24 21:02:42 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
|
||||
/*
|
||||
* Returns nonzero if the current user has administrative privileges,
|
||||
* or zero if not.
|
||||
*
|
||||
* Note: this cannot use ereport() because it's called too early during
|
||||
* startup.
|
||||
*/
|
||||
int
|
||||
pgwin32_is_admin(void)
|
||||
{
|
||||
HANDLE AccessToken;
|
||||
UCHAR InfoBuffer[1024];
|
||||
PTOKEN_GROUPS Groups = (PTOKEN_GROUPS)InfoBuffer;
|
||||
DWORD InfoBufferSize;
|
||||
PSID AdministratorsSid;
|
||||
PSID PowerUsersSid;
|
||||
SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY };
|
||||
UINT x;
|
||||
BOOL success;
|
||||
|
||||
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&AccessToken))
|
||||
{
|
||||
write_stderr("failed to open process token: %d\n",
|
||||
(int)GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!GetTokenInformation(AccessToken,TokenGroups,InfoBuffer,
|
||||
1024, &InfoBufferSize))
|
||||
{
|
||||
write_stderr("failed to get token information: %d\n",
|
||||
(int)GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
CloseHandle(AccessToken);
|
||||
|
||||
if(!AllocateAndInitializeSid(&NtAuthority, 2,
|
||||
SECURITY_BUILTIN_DOMAIN_RID,DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
|
||||
0,&AdministratorsSid))
|
||||
{
|
||||
write_stderr("failed to get SID for Administrators group: %d\n",
|
||||
(int)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("failed to get SID for PowerUsers group: %d\n",
|
||||
(int)GetLastError());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
success = FALSE;
|
||||
|
||||
for (x=0; x<Groups->GroupCount; x++)
|
||||
{
|
||||
if (EqualSid(AdministratorsSid, Groups->Groups[x].Sid) ||
|
||||
EqualSid(PowerUsersSid, Groups->Groups[x].Sid))
|
||||
{
|
||||
success = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FreeSid(AdministratorsSid);
|
||||
FreeSid(PowerUsersSid);
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
* We consider ourselves running as a service if one of the following is
|
||||
* true:
|
||||
*
|
||||
* 1) We are running as Local System (only used by services)
|
||||
* 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
|
||||
* process token by the SCM when starting a service)
|
||||
*
|
||||
* Return values:
|
||||
* 0 = Not service
|
||||
* 1 = Service
|
||||
* -1 = Error
|
||||
*
|
||||
* Note: we can't report errors via either ereport (we're called too early)
|
||||
* or write_stderr (because that calls this). We are therefore reduced to
|
||||
* writing directly on stderr, which sucks, but we have few alternatives.
|
||||
*/
|
||||
int
|
||||
pgwin32_is_service(void)
|
||||
{
|
||||
static int _is_service = -1;
|
||||
HANDLE AccessToken;
|
||||
UCHAR InfoBuffer[1024];
|
||||
PTOKEN_GROUPS Groups = (PTOKEN_GROUPS)InfoBuffer;
|
||||
PTOKEN_USER User = (PTOKEN_USER)InfoBuffer;
|
||||
DWORD InfoBufferSize;
|
||||
PSID ServiceSid;
|
||||
PSID LocalSystemSid;
|
||||
SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY };
|
||||
UINT x;
|
||||
|
||||
/* Only check the first time */
|
||||
if (_is_service != -1)
|
||||
return _is_service;
|
||||
|
||||
if (!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&AccessToken)) {
|
||||
fprintf(stderr,"failed to open process token: %d\n",
|
||||
(int)GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* First check for local system */
|
||||
if (!GetTokenInformation(AccessToken,TokenUser,InfoBuffer,1024,&InfoBufferSize)) {
|
||||
fprintf(stderr,"failed to get token information: %d\n",
|
||||
(int)GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!AllocateAndInitializeSid(&NtAuthority,1,
|
||||
SECURITY_LOCAL_SYSTEM_RID,0,0,0,0,0,0,0,
|
||||
&LocalSystemSid)) {
|
||||
fprintf(stderr,"failed to get SID for local system account\n");
|
||||
CloseHandle(AccessToken);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (EqualSid(LocalSystemSid, User->User.Sid)) {
|
||||
FreeSid(LocalSystemSid);
|
||||
CloseHandle(AccessToken);
|
||||
_is_service = 1;
|
||||
return _is_service;
|
||||
}
|
||||
|
||||
FreeSid(LocalSystemSid);
|
||||
|
||||
/* Now check for group SID */
|
||||
if (!GetTokenInformation(AccessToken,TokenGroups,InfoBuffer,1024,&InfoBufferSize)) {
|
||||
fprintf(stderr,"failed to get token information: %d\n",
|
||||
(int)GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!AllocateAndInitializeSid(&NtAuthority,1,
|
||||
SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0,
|
||||
&ServiceSid)) {
|
||||
fprintf(stderr,"failed to get SID for service group\n");
|
||||
CloseHandle(AccessToken);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_is_service = 0;
|
||||
for (x = 0; x < Groups->GroupCount; x++)
|
||||
{
|
||||
if (EqualSid(ServiceSid, Groups->Groups[x].Sid))
|
||||
{
|
||||
_is_service = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FreeSid(ServiceSid);
|
||||
|
||||
CloseHandle(AccessToken);
|
||||
|
||||
return _is_service;
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/port/win32/signal.c,v 1.3 2004/05/27 14:39:29 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/port/win32/signal.c,v 1.4 2004/06/24 21:02:42 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -63,18 +63,18 @@ pgwin32_signal_initialize(void)
|
||||
pgwin32_signal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (pgwin32_signal_event == NULL)
|
||||
ereport(FATAL,
|
||||
(errmsg_internal("Failed to create signal event: %i!",(int)GetLastError())));
|
||||
(errmsg_internal("failed to create signal event: %d", (int)GetLastError())));
|
||||
|
||||
/* Create thread for handling signals */
|
||||
signal_thread_handle = CreateThread(NULL, 0, pg_signal_thread, NULL, 0, NULL);
|
||||
if (signal_thread_handle == NULL)
|
||||
ereport(FATAL,
|
||||
(errmsg_internal("Failed to create signal handler thread!")));
|
||||
(errmsg_internal("failed to create signal handler thread")));
|
||||
|
||||
/* Create console control handle to pick up Ctrl-C etc */
|
||||
if (!SetConsoleCtrlHandler(pg_console_handler, TRUE))
|
||||
ereport(FATAL,
|
||||
(errmsg_internal("Failed to set console control handler!")));
|
||||
(errmsg_internal("failed to set console control handler")));
|
||||
}
|
||||
|
||||
|
||||
@@ -209,7 +209,7 @@ pg_signal_thread(LPVOID param)
|
||||
char pipename[128];
|
||||
HANDLE pipe = INVALID_HANDLE_VALUE;
|
||||
|
||||
wsprintf(pipename, "\\\\.\\pipe\\pgsignal_%i", GetCurrentProcessId());
|
||||
wsprintf(pipename, "\\\\.\\pipe\\pgsignal_%d", GetCurrentProcessId());
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@@ -221,7 +221,7 @@ pg_signal_thread(LPVOID param)
|
||||
PIPE_UNLIMITED_INSTANCES, 16, 16, 1000, NULL);
|
||||
if (pipe == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
fprintf(stderr, gettext("Failed to create signal listener pipe: %i. Retrying.\n"), (int) GetLastError());
|
||||
write_stderr("failed to create signal listener pipe: %d. Retrying.\n", (int) GetLastError());
|
||||
SleepEx(500, FALSE);
|
||||
continue;
|
||||
}
|
||||
@@ -233,7 +233,8 @@ pg_signal_thread(LPVOID param)
|
||||
(LPTHREAD_START_ROUTINE) pg_signal_dispatch_thread,
|
||||
(LPVOID) pipe, 0, NULL);
|
||||
if (hThread == INVALID_HANDLE_VALUE)
|
||||
fprintf(stderr, gettext("Failed to create signal dispatch thread: %i\n"), (int) GetLastError());
|
||||
write_stderr("failed to create signal dispatch thread: %d\n",
|
||||
(int) GetLastError());
|
||||
else
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user