diff options
Diffstat (limited to 'src/backend/port/win32')
-rw-r--r-- | src/backend/port/win32/Makefile | 4 | ||||
-rw-r--r-- | src/backend/port/win32/security.c | 184 | ||||
-rw-r--r-- | src/backend/port/win32/signal.c | 15 |
3 files changed, 194 insertions, 9 deletions
diff --git a/src/backend/port/win32/Makefile b/src/backend/port/win32/Makefile index 0d5b64ce364..8069d590fd4 100644 --- a/src/backend/port/win32/Makefile +++ b/src/backend/port/win32/Makefile @@ -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 diff --git a/src/backend/port/win32/security.c b/src/backend/port/win32/security.c new file mode 100644 index 00000000000..acc2f41343c --- /dev/null +++ b/src/backend/port/win32/security.c @@ -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; +} diff --git a/src/backend/port/win32/signal.c b/src/backend/port/win32/signal.c index fc0652a5b01..a5cc2561123 100644 --- a/src/backend/port/win32/signal.c +++ b/src/backend/port/win32/signal.c @@ -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); } |