14
14
#include "postgres.h"
15
15
16
16
17
- static BOOL pgwin32_get_dynamic_tokeninfo (HANDLE token ,
18
- TOKEN_INFORMATION_CLASS class , char * * InfoBuffer ,
19
- char * errbuf , int errsize );
20
-
21
17
/*
22
18
* Returns nonzero if the current user has administrative privileges,
23
19
* or zero if not.
@@ -28,33 +24,11 @@ static BOOL pgwin32_get_dynamic_tokeninfo(HANDLE token,
28
24
int
29
25
pgwin32_is_admin (void )
30
26
{
31
- HANDLE AccessToken ;
32
- char * InfoBuffer = NULL ;
33
- char errbuf [256 ];
34
- PTOKEN_GROUPS Groups ;
35
27
PSID AdministratorsSid ;
36
28
PSID PowerUsersSid ;
37
29
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 ;
58
32
59
33
if (!AllocateAndInitializeSid (& NtAuthority , 2 ,
60
34
SECURITY_BUILTIN_DOMAIN_RID , DOMAIN_ALIAS_RID_ADMINS , 0 , 0 , 0 , 0 , 0 ,
@@ -74,32 +48,35 @@ pgwin32_is_admin(void)
74
48
exit (1 );
75
49
}
76
50
77
- success = FALSE;
78
-
79
- for (x = 0 ; x < Groups -> GroupCount ; x ++ )
51
+ if (!CheckTokenMembership (NULL , AdministratorsSid , & IsAdministrators ) ||
52
+ !CheckTokenMembership (NULL , PowerUsersSid , & IsPowerUsers ))
80
53
{
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 );
87
57
}
88
58
89
- free (InfoBuffer );
90
59
FreeSid (AdministratorsSid );
91
60
FreeSid (PowerUsersSid );
92
- return success ;
61
+
62
+ if (IsAdministrators || IsPowerUsers )
63
+ return 1 ;
64
+ else
65
+ return 0 ;
93
66
}
94
67
95
68
/*
96
69
* We consider ourselves running as a service if one of the following is
97
70
* true:
98
71
*
99
- * 1) We are running as Local System (only used by services)
72
+ * 1) We are running as LocalSystem (only used by services)
100
73
* 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
101
74
* process token by the SCM when starting a service)
102
75
*
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
+ *
103
80
* Return values:
104
81
* 0 = Not service
105
82
* 1 = Service
@@ -113,136 +90,62 @@ int
113
90
pgwin32_is_service (void )
114
91
{
115
92
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 ;
121
94
PSID ServiceSid ;
122
95
PSID LocalSystemSid ;
123
96
SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY };
124
- UINT x ;
125
97
126
98
/* Only check the first time */
127
99
if (_is_service != -1 )
128
100
return _is_service ;
129
101
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 */
147
103
if (!AllocateAndInitializeSid (& NtAuthority , 1 ,
148
104
SECURITY_LOCAL_SYSTEM_RID , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
149
105
& LocalSystemSid ))
150
106
{
151
107
fprintf (stderr , "could not get SID for local system account\n" );
152
- CloseHandle (AccessToken );
153
108
return -1 ;
154
109
}
155
110
156
- if (EqualSid ( LocalSystemSid , User -> User . Sid ))
111
+ if (! CheckTokenMembership ( NULL , LocalSystemSid , & IsMember ))
157
112
{
113
+ fprintf (stderr , "could not check access token membership: error code %lu\n" ,
114
+ GetLastError ());
158
115
FreeSid (LocalSystemSid );
159
- free (InfoBuffer );
160
- CloseHandle (AccessToken );
161
- _is_service = 1 ;
162
- return _is_service ;
116
+ return -1 ;
163
117
}
164
-
165
118
FreeSid (LocalSystemSid );
166
- free (InfoBuffer );
167
119
168
- /* Now check for group SID */
169
- if (!pgwin32_get_dynamic_tokeninfo (AccessToken , TokenGroups , & InfoBuffer ,
170
- errbuf , sizeof (errbuf )))
120
+ if (IsMember )
171
121
{
172
- fprintf ( stderr , "%s" , errbuf ) ;
173
- return -1 ;
122
+ _is_service = 1 ;
123
+ return _is_service ;
174
124
}
175
125
176
- Groups = (PTOKEN_GROUPS ) InfoBuffer ;
177
-
126
+ /* Check for service group membership */
178
127
if (!AllocateAndInitializeSid (& NtAuthority , 1 ,
179
128
SECURITY_SERVICE_RID , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
180
129
& ServiceSid ))
181
130
{
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 ());
185
133
return -1 ;
186
134
}
187
135
188
- _is_service = 0 ;
189
- for (x = 0 ; x < Groups -> GroupCount ; x ++ )
136
+ if (!CheckTokenMembership (NULL , ServiceSid , & IsMember ))
190
137
{
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 ;
196
142
}
197
-
198
- free (InfoBuffer );
199
143
FreeSid (ServiceSid );
200
144
201
- CloseHandle (AccessToken );
145
+ if (IsMember )
146
+ _is_service = 1 ;
147
+ else
148
+ _is_service = 0 ;
202
149
203
150
return _is_service ;
204
151
}
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