18
18
#endif
19
19
20
20
21
+ static BOOL pgwin32_get_dynamic_tokeninfo (HANDLE token ,
22
+ TOKEN_INFORMATION_CLASS class ,
23
+ char * * InfoBuffer , char * errbuf , int errsize );
24
+
25
+
21
26
/*
22
27
* Utility wrapper for frontend and backend when reporting an error
23
28
* message.
@@ -48,11 +53,33 @@ log_error(const char *fmt,...)
48
53
int
49
54
pgwin32_is_admin (void )
50
55
{
56
+ HANDLE AccessToken ;
57
+ char * InfoBuffer = NULL ;
58
+ char errbuf [256 ];
59
+ PTOKEN_GROUPS Groups ;
51
60
PSID AdministratorsSid ;
52
61
PSID PowerUsersSid ;
53
62
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 );
56
83
57
84
if (!AllocateAndInitializeSid (& NtAuthority , 2 ,
58
85
SECURITY_BUILTIN_DOMAIN_RID ,
@@ -74,35 +101,34 @@ pgwin32_is_admin(void)
74
101
exit (1 );
75
102
}
76
103
77
- if (!CheckTokenMembership (NULL , AdministratorsSid , & IsAdministrators ) ||
78
- !CheckTokenMembership (NULL , PowerUsersSid , & IsPowerUsers ))
104
+ success = FALSE;
105
+
106
+ for (x = 0 ; x < Groups -> GroupCount ; x ++ )
79
107
{
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
+ }
83
116
}
84
117
118
+ free (InfoBuffer );
85
119
FreeSid (AdministratorsSid );
86
120
FreeSid (PowerUsersSid );
87
-
88
- if (IsAdministrators || IsPowerUsers )
89
- return 1 ;
90
- else
91
- return 0 ;
121
+ return success ;
92
122
}
93
123
94
124
/*
95
125
* We consider ourselves running as a service if one of the following is
96
126
* true:
97
127
*
98
- * 1) We are running as LocalSystem (only used by services)
128
+ * 1) We are running as Local System (only used by services)
99
129
* 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
100
130
* process token by the SCM when starting a service)
101
131
*
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
- *
106
132
* Return values:
107
133
* 0 = Not service
108
134
* 1 = Service
@@ -117,62 +143,141 @@ int
117
143
pgwin32_is_service (void )
118
144
{
119
145
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 ;
121
151
PSID ServiceSid ;
122
152
PSID LocalSystemSid ;
123
153
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY };
154
+ UINT x ;
124
155
125
156
/* Only check the first time */
126
157
if (_is_service != -1 )
127
158
return _is_service ;
128
159
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
+
130
177
if (!AllocateAndInitializeSid (& NtAuthority , 1 ,
131
178
SECURITY_LOCAL_SYSTEM_RID , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
132
179
& LocalSystemSid ))
133
180
{
134
181
fprintf (stderr , "could not get SID for local system account\n" );
182
+ CloseHandle (AccessToken );
135
183
return -1 ;
136
184
}
137
185
138
- if (! CheckTokenMembership ( NULL , LocalSystemSid , & IsMember ))
186
+ if (EqualSid ( LocalSystemSid , User -> User . Sid ))
139
187
{
140
- fprintf (stderr , "could not check access token membership: error code %lu\n" ,
141
- GetLastError ());
142
188
FreeSid (LocalSystemSid );
143
- return -1 ;
189
+ free (InfoBuffer );
190
+ CloseHandle (AccessToken );
191
+ _is_service = 1 ;
192
+ return _is_service ;
144
193
}
194
+
145
195
FreeSid (LocalSystemSid );
196
+ free (InfoBuffer );
146
197
147
- if (IsMember )
198
+ /* Now check for group SID */
199
+ if (!pgwin32_get_dynamic_tokeninfo (AccessToken , TokenGroups , & InfoBuffer ,
200
+ errbuf , sizeof (errbuf )))
148
201
{
149
- _is_service = 1 ;
150
- return _is_service ;
202
+ fprintf ( stderr , "%s" , errbuf ) ;
203
+ return -1 ;
151
204
}
152
205
153
- /* Check for service group membership */
206
+ Groups = (PTOKEN_GROUPS ) InfoBuffer ;
207
+
154
208
if (!AllocateAndInitializeSid (& NtAuthority , 1 ,
155
209
SECURITY_SERVICE_RID , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
156
210
& ServiceSid ))
157
211
{
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 );
160
215
return -1 ;
161
216
}
162
217
163
- if (!CheckTokenMembership (NULL , ServiceSid , & IsMember ))
218
+ _is_service = 0 ;
219
+ for (x = 0 ; x < Groups -> GroupCount ; x ++ )
164
220
{
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
+ }
169
227
}
228
+
229
+ free (InfoBuffer );
170
230
FreeSid (ServiceSid );
171
231
172
- if (IsMember )
173
- _is_service = 1 ;
174
- else
175
- _is_service = 0 ;
232
+ CloseHandle (AccessToken );
176
233
177
234
return _is_service ;
178
235
}
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