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

Skip to content

Commit ff30aec

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 b4ff860 commit ff30aec

File tree

1 file changed

+38
-142
lines changed

1 file changed

+38
-142
lines changed

src/port/win32security.c

Lines changed: 38 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@
1818
#endif
1919

2020

21-
static BOOL pgwin32_get_dynamic_tokeninfo(HANDLE token,
22-
TOKEN_INFORMATION_CLASS class,
23-
char **InfoBuffer, char *errbuf, int errsize);
24-
25-
2621
/*
2722
* Utility wrapper for frontend and backend when reporting an error
2823
* message.
@@ -53,33 +48,11 @@ log_error(const char *fmt,...)
5348
int
5449
pgwin32_is_admin(void)
5550
{
56-
HANDLE AccessToken;
57-
char *InfoBuffer = NULL;
58-
char errbuf[256];
59-
PTOKEN_GROUPS Groups;
6051
PSID AdministratorsSid;
6152
PSID PowerUsersSid;
6253
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
63-
UINT x;
64-
BOOL success;
65-
66-
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &AccessToken))
67-
{
68-
log_error(_("could not open process token: error code %lu\n"),
69-
GetLastError());
70-
exit(1);
71-
}
72-
73-
if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenGroups,
74-
&InfoBuffer, errbuf, sizeof(errbuf)))
75-
{
76-
log_error("%s", errbuf);
77-
exit(1);
78-
}
79-
80-
Groups = (PTOKEN_GROUPS) InfoBuffer;
81-
82-
CloseHandle(AccessToken);
54+
BOOL IsAdministrators;
55+
BOOL IsPowerUsers;
8356

8457
if (!AllocateAndInitializeSid(&NtAuthority, 2,
8558
SECURITY_BUILTIN_DOMAIN_RID,
@@ -101,34 +74,35 @@ pgwin32_is_admin(void)
10174
exit(1);
10275
}
10376

104-
success = FALSE;
105-
106-
for (x = 0; x < Groups->GroupCount; x++)
77+
if (!CheckTokenMembership(NULL, AdministratorsSid, &IsAdministrators) ||
78+
!CheckTokenMembership(NULL, PowerUsersSid, &IsPowerUsers))
10779
{
108-
if ((EqualSid(AdministratorsSid, Groups->Groups[x].Sid) &&
109-
(Groups->Groups[x].Attributes & SE_GROUP_ENABLED)) ||
110-
(EqualSid(PowerUsersSid, Groups->Groups[x].Sid) &&
111-
(Groups->Groups[x].Attributes & SE_GROUP_ENABLED)))
112-
{
113-
success = TRUE;
114-
break;
115-
}
80+
log_error(_("could not check access token membership: error code %lu\n"),
81+
GetLastError());
82+
exit(1);
11683
}
11784

118-
free(InfoBuffer);
11985
FreeSid(AdministratorsSid);
12086
FreeSid(PowerUsersSid);
121-
return success;
87+
88+
if (IsAdministrators || IsPowerUsers)
89+
return 1;
90+
else
91+
return 0;
12292
}
12393

12494
/*
12595
* We consider ourselves running as a service if one of the following is
12696
* true:
12797
*
128-
* 1) We are running as Local System (only used by services)
98+
* 1) We are running as LocalSystem (only used by services)
12999
* 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
130100
* process token by the SCM when starting a service)
131101
*
102+
* The check for LocalSystem is needed, because surprisingly, if a service
103+
* is running as LocalSystem, it does not have SECURITY_SERVICE_RID in its
104+
* process token.
105+
*
132106
* Return values:
133107
* 0 = Not service
134108
* 1 = Service
@@ -143,140 +117,62 @@ int
143117
pgwin32_is_service(void)
144118
{
145119
static int _is_service = -1;
146-
HANDLE AccessToken;
147-
char *InfoBuffer = NULL;
148-
char errbuf[256];
149-
PTOKEN_GROUPS Groups;
150-
PTOKEN_USER User;
120+
BOOL IsMember;
151121
PSID ServiceSid;
152122
PSID LocalSystemSid;
153123
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
154-
UINT x;
155124

156125
/* Only check the first time */
157126
if (_is_service != -1)
158127
return _is_service;
159128

160-
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &AccessToken))
161-
{
162-
fprintf(stderr, "could not open process token: error code %lu\n",
163-
GetLastError());
164-
return -1;
165-
}
166-
167-
/* First check for local system */
168-
if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenUser, &InfoBuffer,
169-
errbuf, sizeof(errbuf)))
170-
{
171-
fprintf(stderr, "%s", errbuf);
172-
return -1;
173-
}
174-
175-
User = (PTOKEN_USER) InfoBuffer;
176-
129+
/* First check for LocalSystem */
177130
if (!AllocateAndInitializeSid(&NtAuthority, 1,
178131
SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0,
179132
&LocalSystemSid))
180133
{
181134
fprintf(stderr, "could not get SID for local system account\n");
182-
CloseHandle(AccessToken);
183135
return -1;
184136
}
185137

186-
if (EqualSid(LocalSystemSid, User->User.Sid))
138+
if (!CheckTokenMembership(NULL, LocalSystemSid, &IsMember))
187139
{
140+
fprintf(stderr, "could not check access token membership: error code %lu\n",
141+
GetLastError());
188142
FreeSid(LocalSystemSid);
189-
free(InfoBuffer);
190-
CloseHandle(AccessToken);
191-
_is_service = 1;
192-
return _is_service;
143+
return -1;
193144
}
194-
195145
FreeSid(LocalSystemSid);
196-
free(InfoBuffer);
197146

198-
/* Now check for group SID */
199-
if (!pgwin32_get_dynamic_tokeninfo(AccessToken, TokenGroups, &InfoBuffer,
200-
errbuf, sizeof(errbuf)))
147+
if (IsMember)
201148
{
202-
fprintf(stderr, "%s", errbuf);
203-
return -1;
149+
_is_service = 1;
150+
return _is_service;
204151
}
205152

206-
Groups = (PTOKEN_GROUPS) InfoBuffer;
207-
153+
/* Check for service group membership */
208154
if (!AllocateAndInitializeSid(&NtAuthority, 1,
209155
SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0,
210156
&ServiceSid))
211157
{
212-
fprintf(stderr, "could not get SID for service group\n");
213-
free(InfoBuffer);
214-
CloseHandle(AccessToken);
158+
fprintf(stderr, "could not get SID for service group: error code %lu\n",
159+
GetLastError());
215160
return -1;
216161
}
217162

218-
_is_service = 0;
219-
for (x = 0; x < Groups->GroupCount; x++)
163+
if (!CheckTokenMembership(NULL, ServiceSid, &IsMember))
220164
{
221-
if (EqualSid(ServiceSid, Groups->Groups[x].Sid))
222-
{
223-
_is_service = 1;
224-
break;
225-
}
165+
fprintf(stderr, "could not check access token membership: error code %lu\n",
166+
GetLastError());
167+
FreeSid(ServiceSid);
168+
return -1;
226169
}
227-
228-
free(InfoBuffer);
229170
FreeSid(ServiceSid);
230171

231-
CloseHandle(AccessToken);
172+
if (IsMember)
173+
_is_service = 1;
174+
else
175+
_is_service = 0;
232176

233177
return _is_service;
234178
}
235-
236-
237-
/*
238-
* Call GetTokenInformation() on a token and return a dynamically sized
239-
* buffer with the information in it. This buffer must be free():d by
240-
* the calling function!
241-
*/
242-
static BOOL
243-
pgwin32_get_dynamic_tokeninfo(HANDLE token, TOKEN_INFORMATION_CLASS class,
244-
char **InfoBuffer, char *errbuf, int errsize)
245-
{
246-
DWORD InfoBufferSize;
247-
248-
if (GetTokenInformation(token, class, NULL, 0, &InfoBufferSize))
249-
{
250-
snprintf(errbuf, errsize,
251-
"could not get token information buffer size: got zero size\n");
252-
return FALSE;
253-
}
254-
255-
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
256-
{
257-
snprintf(errbuf, errsize,
258-
"could not get token information buffer size: error code %lu\n",
259-
GetLastError());
260-
return FALSE;
261-
}
262-
263-
*InfoBuffer = malloc(InfoBufferSize);
264-
if (*InfoBuffer == NULL)
265-
{
266-
snprintf(errbuf, errsize,
267-
"could not allocate %d bytes for token information\n",
268-
(int) InfoBufferSize);
269-
return FALSE;
270-
}
271-
272-
if (!GetTokenInformation(token, class, *InfoBuffer,
273-
InfoBufferSize, &InfoBufferSize))
274-
{
275-
snprintf(errbuf, errsize,
276-
"could not get token information: error code %lu\n",
277-
GetLastError());
278-
return FALSE;
279-
}
280-
281-
return TRUE;
282-
}

0 commit comments

Comments
 (0)