mirror of https://github.com/postgres/postgres
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 HaganderREL8_0_STABLE
parent
b5b9e33564
commit
b15f9b08ef
@ -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; |
||||
} |
Loading…
Reference in new issue