Skip to content

Commit 4ae0805

Browse files
committed
Revert Windows service check refactoring, and replace with a different fix.
This reverts commit 38bdba5, "Fix and simplify check for whether we're running as Windows service". It turns out that older versions of MinGW - like that on buildfarm member narwhal - do not support the CheckTokenMembership() function. This replaces the refactoring with a much smaller fix, to add a check for SE_GROUP_ENABLED to pgwin32_is_service(). Only apply to back-branches, and keep the refactoring in HEAD. It's unlikely that anyone is still really using such an old version of MinGW - aside from narwhal - but let's not change the minimum requirements in minor releases. Discussion: https://www.postgresql.org/message-id/16609.1489773427@sss.pgh.pa.us Patch: https://www.postgresql.org/message-id/CAB7nPqSvfu%3DKpJ%3DNX%2BYAHmgAmQdzA7N5h31BjzXeMgczhGCC%2BQ%40mail.gmail.com
1 parent a4d07d2 commit 4ae0805

File tree

1 file changed

+143
-38
lines changed

1 file changed

+143
-38
lines changed

src/port/win32security.c

Lines changed: 143 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
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+
2126
/*
2227
* Utility wrapper for frontend and backend when reporting an error
2328
* message.
@@ -48,11 +53,33 @@ log_error(const char *fmt,...)
4853
int
4954
pgwin32_is_admin(void)
5055
{
56+
HANDLE AccessToken;
57+
char *InfoBuffer = NULL;
58+
char errbuf[256];
59+
PTOKEN_GROUPS Groups;
5160
PSID AdministratorsSid;
5261
PSID PowerUsersSid;
5362
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
54-
BOOL IsAdministrators;
55-
BOOL IsPowerUsers;
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);
5683

5784
if (!AllocateAndInitializeSid(&NtAuthority, 2,
5885
SECURITY_BUILTIN_DOMAIN_RID,
@@ -74,35 +101,34 @@ pgwin32_is_admin(void)
74101
exit(1);
75102
}
76103

77-
if (!CheckTokenMembership(NULL, AdministratorsSid, &IsAdministrators) ||
78-
!CheckTokenMembership(NULL, PowerUsersSid, &IsPowerUsers))
104+
success = FALSE;
105+
106+
for (x = 0; x < Groups->GroupCount; x++)
79107
{
80-
log_error(_("could not check access token membership: error code %lu\n"),
81-
GetLastError());
82-
exit(1);
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+
}
83116
}
84117

118+
free(InfoBuffer);
85119
FreeSid(AdministratorsSid);
86120
FreeSid(PowerUsersSid);
87-
88-
if (IsAdministrators || IsPowerUsers)
89-
return 1;
90-
else
91-
return 0;
121+
return success;
92122
}
93123

94124
/*
95125
* We consider ourselves running as a service if one of the following is
96126
* true:
97127
*
98-
* 1) We are running as LocalSystem (only used by services)
128+
* 1) We are running as Local System (only used by services)
99129
* 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
100130
* process token by the SCM when starting a service)
101131
*
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-
*
106132
* Return values:
107133
* 0 = Not service
108134
* 1 = Service
@@ -117,62 +143,141 @@ int
117143
pgwin32_is_service(void)
118144
{
119145
static int _is_service = -1;
120-
BOOL IsMember;
146+
HANDLE AccessToken;
147+
char *InfoBuffer = NULL;
148+
char errbuf[256];
149+
PTOKEN_GROUPS Groups;
150+
PTOKEN_USER User;
121151
PSID ServiceSid;
122152
PSID LocalSystemSid;
123153
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
154+
UINT x;
124155

125156
/* Only check the first time */
126157
if (_is_service != -1)
127158
return _is_service;
128159

129-
/* First check for LocalSystem */
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+
130177
if (!AllocateAndInitializeSid(&NtAuthority, 1,
131178
SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0,
132179
&LocalSystemSid))
133180
{
134181
fprintf(stderr, "could not get SID for local system account\n");
182+
CloseHandle(AccessToken);
135183
return -1;
136184
}
137185

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

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

153-
/* Check for service group membership */
206+
Groups = (PTOKEN_GROUPS) InfoBuffer;
207+
154208
if (!AllocateAndInitializeSid(&NtAuthority, 1,
155209
SECURITY_SERVICE_RID, 0, 0, 0, 0, 0, 0, 0,
156210
&ServiceSid))
157211
{
158-
fprintf(stderr, "could not get SID for service group: error code %lu\n",
159-
GetLastError());
212+
fprintf(stderr, "could not get SID for service group\n");
213+
free(InfoBuffer);
214+
CloseHandle(AccessToken);
160215
return -1;
161216
}
162217

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

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

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

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy