Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3ebcc24

Browse files
committed
Fix and simplify check for whether we're running as Windows service.
If the process token contains SECURITY_SERVICE_RID, but it has been disabled by the SE_GROUP_USE_FOR_DENY_ONLY attribute, win32_is_service() would incorrectly report that we're running as a service. That situation arises, e.g. if postmaster is launched with a restricted security token, with the "Log in as Service" privilege explicitly removed. Replace the broken code with CheckProcessTokenMembership(), which does this correctly. Also replace similar code in win32_is_admin(), even though it got this right, for simplicity and consistency. Per bug #13755, reported by Breen Hagan. Back-patch to all supported versions. Patch by Takayuki Tsunakawa, reviewed by Michael Paquier. Discussion: https://www.postgresql.org/message-id/20151104062315.2745.67143%40wrigleys.postgresql.org
1 parent 8f8a5ae commit 3ebcc24

File tree

1 file changed

+38
-135
lines changed

1 file changed

+38
-135
lines changed

src/backend/port/win32/security.c

Lines changed: 38 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@
1414
#include "postgres.h"
1515

1616

17-
static BOOL pgwin32_get_dynamic_tokeninfo(HANDLE token,
18-
TOKEN_INFORMATION_CLASS class, char **InfoBuffer,
19-
char *errbuf, int errsize);
20-
2117
/*
2218
* Returns nonzero if the current user has administrative privileges,
2319
* or zero if not.
@@ -28,33 +24,11 @@ static BOOL pgwin32_get_dynamic_tokeninfo(HANDLE token,
2824
int
2925
pgwin32_is_admin(void)
3026
{
31-
HANDLE AccessToken;
32-
char *InfoBuffer = NULL;
33-
char errbuf[256];
34-
PTOKEN_GROUPS Groups;
3527
PSID AdministratorsSid;
3628
PSID PowerUsersSid;
3729
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
38-
UINT x;
39-
BOOL success;
40-
41-
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &AccessToken))
42-
{
43-
write_stderr("could not open process token: error code %lu\n",
44-
GetLastError());
45-
exit(1);
46-
}
47-
48-
if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenGroups,
49-
&InfoBuffer, errbuf, sizeof(errbuf)))
50-
{
51-
write_stderr("%s", errbuf);
52-
exit(1);
53-
}
54-
55-
Groups = (PTOKEN_GROUPS) InfoBuffer;
56-
57-
CloseHandle(AccessToken);
30+
BOOL IsAdministrators;
31+
BOOL IsPowerUsers;
5832

5933
if (!AllocateAndInitializeSid(&NtAuthority, 2,
6034
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
@@ -74,32 +48,35 @@ pgwin32_is_admin(void)
7448
exit(1);
7549
}
7650

77-
success = FALSE;
78-
79-
for (x = 0; x < Groups->GroupCount; x++)
51+
if (!CheckTokenMembership(NULL, AdministratorsSid, &IsAdministrators) ||
52+
!CheckTokenMembership(NULL, PowerUsersSid, &IsPowerUsers))
8053
{
81-
if ((EqualSid(AdministratorsSid, Groups->Groups[x].Sid) && (Groups->Groups[x].Attributes & SE_GROUP_ENABLED)) ||
82-
(EqualSid(PowerUsersSid, Groups->Groups[x].Sid) && (Groups->Groups[x].Attributes & SE_GROUP_ENABLED)))
83-
{
84-
success = TRUE;
85-
break;
86-
}
54+
write_stderr("could not check access token membership: error code %lu\n",
55+
GetLastError());
56+
exit(1);
8757
}
8858

89-
free(InfoBuffer);
9059
FreeSid(AdministratorsSid);
9160
FreeSid(PowerUsersSid);
92-
return success;
61+
62+
if (IsAdministrators || IsPowerUsers)
63+
return 1;
64+
else
65+
return 0;
9366
}
9467

9568
/*
9669
* We consider ourselves running as a service if one of the following is
9770
* true:
9871
*
99-
* 1) We are running as Local System (only used by services)
72+
* 1) We are running as LocalSystem (only used by services)
10073
* 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
10174
* process token by the SCM when starting a service)
10275
*
76+
* The check for LocalSystem is needed, because surprisingly, if a service
77+
* is running as LocalSystem, it does not have SECURITY_SERVICE_RID in its
78+
* process token.
79+
*
10380
* Return values:
10481
* 0 = Not service
10582
* 1 = Service
@@ -113,136 +90,62 @@ int
11390
pgwin32_is_service(void)
11491
{
11592
static int _is_service = -1;
116-
HANDLE AccessToken;
117-
char *InfoBuffer = NULL;
118-
char errbuf[256];
119-
PTOKEN_GROUPS Groups;
120-
PTOKEN_USER User;
93+
BOOL IsMember;
12194
PSID ServiceSid;
12295
PSID LocalSystemSid;
12396
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
124-
UINT x;
12597

12698
/* Only check the first time */
12799
if (_is_service != -1)
128100
return _is_service;
129101

130-
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &AccessToken))
131-
{
132-
fprintf(stderr, "could not open process token: error code %lu\n",
133-
GetLastError());
134-
return -1;
135-
}
136-
137-
/* First check for local system */
138-
if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenUser, &InfoBuffer,
139-
errbuf, sizeof(errbuf)))
140-
{
141-
fprintf(stderr, "%s", errbuf);
142-
return -1;
143-
}
144-
145-
User = (PTOKEN_USER) InfoBuffer;
146-
102+
/* First check for LocalSystem */
147103
if (!AllocateAndInitializeSid(&NtAuthority, 1,
148104
SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0,
149105
&LocalSystemSid))
150106
{
151107
fprintf(stderr, "could not get SID for local system account\n");
152-
CloseHandle(AccessToken);
153108
return -1;
154109
}
155110

156-
if (EqualSid(LocalSystemSid, User->User.Sid))
111+
if (!CheckTokenMembership(NULL, LocalSystemSid, &IsMember))
157112
{
113+
fprintf(stderr, "could not check access token membership: error code %lu\n",
114+
GetLastError());
158115
FreeSid(LocalSystemSid);
159-
free(InfoBuffer);
160-
CloseHandle(AccessToken);
161-
_is_service = 1;
162-
return _is_service;
116+
return -1;
163117
}
164-
165118
FreeSid(LocalSystemSid);
166-
free(InfoBuffer);
167119

168-
/* Now check for group SID */
169-
if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenGroups, &InfoBuffer,
170-
errbuf, sizeof(errbuf)))
120+
if (IsMember)
171121
{
172-
fprintf(stderr, "%s", errbuf);
173-
return -1;
122+
_is_service = 1;
123+
return _is_service;
174124
}
175125

176-
Groups = (PTOKEN_GROUPS) InfoBuffer;
177-
126+
/* Check for service group membership */
178127
if (!AllocateAndInitializeSid(&NtAuthority, 1,
179128
SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0,
180129
&ServiceSid))
181130
{
182-
fprintf(stderr, "could not get SID for service group\n");
183-
free(InfoBuffer);
184-
CloseHandle(AccessToken);
131+
fprintf(stderr, "could not get SID for service group: error code %lu\n",
132+
GetLastError());
185133
return -1;
186134
}
187135

188-
_is_service = 0;
189-
for (x = 0; x < Groups->GroupCount; x++)
136+
if (!CheckTokenMembership(NULL, ServiceSid, &IsMember))
190137
{
191-
if (EqualSid(ServiceSid, Groups->Groups[x].Sid))
192-
{
193-
_is_service = 1;
194-
break;
195-
}
138+
fprintf(stderr, "could not check access token membership: error code %lu\n",
139+
GetLastError());
140+
FreeSid(ServiceSid);
141+
return -1;
196142
}
197-
198-
free(InfoBuffer);
199143
FreeSid(ServiceSid);
200144

201-
CloseHandle(AccessToken);
145+
if (IsMember)
146+
_is_service = 1;
147+
else
148+
_is_service = 0;
202149

203150
return _is_service;
204151
}
205-
206-
207-
/*
208-
* Call GetTokenInformation() on a token and return a dynamically sized
209-
* buffer with the information in it. This buffer must be free():d by
210-
* the calling function!
211-
*/
212-
static BOOL
213-
pgwin32_get_dynamic_tokeninfo(HANDLE token, TOKEN_INFORMATION_CLASS class,
214-
char **InfoBuffer, char *errbuf, int errsize)
215-
{
216-
DWORD InfoBufferSize;
217-
218-
if (GetTokenInformation(token, class, NULL, 0, &InfoBufferSize))
219-
{
220-
snprintf(errbuf, errsize, "could not get token information: got zero size\n");
221-
return FALSE;
222-
}
223-
224-
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
225-
{
226-
snprintf(errbuf, errsize, "could not get token information: error code %lu\n",
227-
GetLastError());
228-
return FALSE;
229-
}
230-
231-
*InfoBuffer = malloc(InfoBufferSize);
232-
if (*InfoBuffer == NULL)
233-
{
234-
snprintf(errbuf, errsize, "could not allocate %d bytes for token information\n",
235-
(int) InfoBufferSize);
236-
return FALSE;
237-
}
238-
239-
if (!GetTokenInformation(token, class, *InfoBuffer,
240-
InfoBufferSize, &InfoBufferSize))
241-
{
242-
snprintf(errbuf, errsize, "could not get token information: error code %lu\n",
243-
GetLastError());
244-
return FALSE;
245-
}
246-
247-
return TRUE;
248-
}

0 commit comments

Comments
 (0)