Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)