diff options
Diffstat (limited to 'src/backend/port/win32/security.c')
-rw-r--r-- | src/backend/port/win32/security.c | 184 |
1 files changed, 184 insertions, 0 deletions
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; +} |