Use dynamically-sized buffers in pgwin32_is_service().

Magnus Hagander
This commit is contained in:
Tom Lane 2004-11-16 19:52:22 +00:00
parent 7efa8411cc
commit 6beb6fa495
1 changed files with 71 additions and 36 deletions

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/port/win32/security.c,v 1.6 2004/11/09 13:01:25 petere Exp $ * $PostgreSQL: pgsql/src/backend/port/win32/security.c,v 1.7 2004/11/16 19:52:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -14,6 +14,10 @@
#include "postgres.h" #include "postgres.h"
static BOOL pgwin32_get_dynamic_tokeninfo(HANDLE token,
TOKEN_INFORMATION_CLASS class, char **InfoBuffer,
char *errbuf, int errsize);
/* /*
* Returns nonzero if the current user has administrative privileges, * Returns nonzero if the current user has administrative privileges,
* or zero if not. * or zero if not.
@ -26,8 +30,8 @@ pgwin32_is_admin(void)
{ {
HANDLE AccessToken; HANDLE AccessToken;
char *InfoBuffer = NULL; char *InfoBuffer = NULL;
char errbuf[256];
PTOKEN_GROUPS Groups; PTOKEN_GROUPS Groups;
DWORD InfoBufferSize;
PSID AdministratorsSid; PSID AdministratorsSid;
PSID PowerUsersSid; PSID PowerUsersSid;
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
@ -41,36 +45,15 @@ pgwin32_is_admin(void)
exit(1); exit(1);
} }
if (GetTokenInformation(AccessToken, TokenGroups, NULL, 0, &InfoBufferSize)) if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenGroups,
&InfoBuffer, errbuf, sizeof(errbuf)))
{ {
write_stderr("could not get token information: got zero size\n"); write_stderr(errbuf);
exit(1); exit(1);
} }
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
write_stderr("could not get token information: error code %d\n",
(int) GetLastError());
exit(1);
}
InfoBuffer = malloc(InfoBufferSize);
if (!InfoBuffer)
{
write_stderr("could not allocate %i bytes for token information\n",
(int) InfoBufferSize);
exit(1);
}
Groups = (PTOKEN_GROUPS) InfoBuffer; Groups = (PTOKEN_GROUPS) InfoBuffer;
if (!GetTokenInformation(AccessToken, TokenGroups, InfoBuffer,
InfoBufferSize, &InfoBufferSize))
{
write_stderr("could not get token information: error code %d\n",
(int) GetLastError());
exit(1);
}
CloseHandle(AccessToken); CloseHandle(AccessToken);
if (!AllocateAndInitializeSid(&NtAuthority, 2, if (!AllocateAndInitializeSid(&NtAuthority, 2,
@ -131,10 +114,10 @@ pgwin32_is_service(void)
{ {
static int _is_service = -1; static int _is_service = -1;
HANDLE AccessToken; HANDLE AccessToken;
UCHAR InfoBuffer[1024]; char *InfoBuffer = NULL;
PTOKEN_GROUPS Groups = (PTOKEN_GROUPS) InfoBuffer; char errbuf[256];
PTOKEN_USER User = (PTOKEN_USER) InfoBuffer; PTOKEN_GROUPS Groups;
DWORD InfoBufferSize; PTOKEN_USER User;
PSID ServiceSid; PSID ServiceSid;
PSID LocalSystemSid; PSID LocalSystemSid;
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY}; SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
@ -152,13 +135,15 @@ pgwin32_is_service(void)
} }
/* First check for local system */ /* First check for local system */
if (!GetTokenInformation(AccessToken, TokenUser, InfoBuffer, 1024, &InfoBufferSize)) if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenUser, &InfoBuffer,
errbuf, sizeof(errbuf)))
{ {
fprintf(stderr, "could not get token information: error code %d\n", fprintf(stderr,errbuf);
(int) GetLastError());
return -1; return -1;
} }
User = (PTOKEN_USER) InfoBuffer;
if (!AllocateAndInitializeSid(&NtAuthority, 1, if (!AllocateAndInitializeSid(&NtAuthority, 1,
SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0,
&LocalSystemSid)) &LocalSystemSid))
@ -171,26 +156,31 @@ pgwin32_is_service(void)
if (EqualSid(LocalSystemSid, User->User.Sid)) if (EqualSid(LocalSystemSid, User->User.Sid))
{ {
FreeSid(LocalSystemSid); FreeSid(LocalSystemSid);
free(InfoBuffer);
CloseHandle(AccessToken); CloseHandle(AccessToken);
_is_service = 1; _is_service = 1;
return _is_service; return _is_service;
} }
FreeSid(LocalSystemSid); FreeSid(LocalSystemSid);
free(InfoBuffer);
/* Now check for group SID */ /* Now check for group SID */
if (!GetTokenInformation(AccessToken, TokenGroups, InfoBuffer, 1024, &InfoBufferSize)) if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenGroups, &InfoBuffer,
errbuf, sizeof(errbuf)))
{ {
fprintf(stderr, "could not get token information: error code %d\n", fprintf(stderr,errbuf);
(int) GetLastError());
return -1; return -1;
} }
Groups = (PTOKEN_GROUPS) InfoBuffer;
if (!AllocateAndInitializeSid(&NtAuthority, 1, if (!AllocateAndInitializeSid(&NtAuthority, 1,
SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0, SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0,
&ServiceSid)) &ServiceSid))
{ {
fprintf(stderr, "could not get SID for service group\n"); fprintf(stderr, "could not get SID for service group\n");
free(InfoBuffer);
CloseHandle(AccessToken); CloseHandle(AccessToken);
return -1; return -1;
} }
@ -205,9 +195,54 @@ pgwin32_is_service(void)
} }
} }
free(InfoBuffer);
FreeSid(ServiceSid); FreeSid(ServiceSid);
CloseHandle(AccessToken); CloseHandle(AccessToken);
return _is_service; return _is_service;
} }
/*
* 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 %d\n",
(int) 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 %d\n",
(int) GetLastError());
return FALSE;
}
return TRUE;
}