1414#include "postgres.h"
1515
1616
17- static BOOL pgwin32_get_dynamic_tokeninfo (HANDLE token ,
18- TOKEN_INFORMATION_CLASS class ,char * * InfoBuffer ,
19- char * errbuf ,int errsize );
20-
2117/*
2218 * Returns nonzero if the current user has administrative privileges,
2319 * or zero if not.
@@ -28,33 +24,11 @@ static BOOL pgwin32_get_dynamic_tokeninfo(HANDLE token,
2824int
2925pgwin32_is_admin (void )
3026{
31- HANDLE AccessToken ;
32- char * InfoBuffer = NULL ;
33- char errbuf [256 ];
34- PTOKEN_GROUPS Groups ;
3527PSID AdministratorsSid ;
3628PSID PowerUsersSid ;
3729SID_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 ;
5832
5933if (!AllocateAndInitializeSid (& NtAuthority ,2 ,
6034SECURITY_BUILTIN_DOMAIN_RID ,DOMAIN_ALIAS_RID_ADMINS ,0 ,0 ,0 ,0 ,0 ,
@@ -74,32 +48,35 @@ pgwin32_is_admin(void)
7448exit (1 );
7549}
7650
77- success = FALSE;
78-
79- for (x = 0 ;x < Groups -> GroupCount ;x ++ )
51+ if (!CheckTokenMembership (NULL ,AdministratorsSid ,& IsAdministrators )||
52+ !CheckTokenMembership (NULL ,PowerUsersSid ,& IsPowerUsers ))
8053{
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 );
8757}
8858
89- free (InfoBuffer );
9059FreeSid (AdministratorsSid );
9160FreeSid (PowerUsersSid );
92- return success ;
61+
62+ if (IsAdministrators || IsPowerUsers )
63+ return 1 ;
64+ else
65+ return 0 ;
9366}
9467
9568/*
9669 * We consider ourselves running as a service if one of the following is
9770 * true:
9871 *
99- * 1) We are running asLocal System (only used by services)
72+ * 1) We are running asLocalSystem (only used by services)
10073 * 2) Our token contains SECURITY_SERVICE_RID (automatically added to the
10174 * process token by the SCM when starting a service)
10275 *
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+ *
10380 * Return values:
10481 * 0 = Not service
10582 * 1 = Service
@@ -113,136 +90,62 @@ int
11390pgwin32_is_service (void )
11491{
11592static 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 ;
12194PSID ServiceSid ;
12295PSID LocalSystemSid ;
12396SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY };
124- UINT x ;
12597
12698/* Only check the first time */
12799if (_is_service != -1 )
128100return _is_service ;
129101
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 */
147103if (!AllocateAndInitializeSid (& NtAuthority ,1 ,
148104SECURITY_LOCAL_SYSTEM_RID ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
149105& LocalSystemSid ))
150106{
151107fprintf (stderr ,"could not get SID for local system account\n" );
152- CloseHandle (AccessToken );
153108return -1 ;
154109}
155110
156- if (EqualSid ( LocalSystemSid ,User -> User . Sid ))
111+ if (! CheckTokenMembership ( NULL , LocalSystemSid ,& IsMember ))
157112{
113+ fprintf (stderr ,"could not check access token membership: error code %lu\n" ,
114+ GetLastError ());
158115FreeSid (LocalSystemSid );
159- free (InfoBuffer );
160- CloseHandle (AccessToken );
161- _is_service = 1 ;
162- return _is_service ;
116+ return -1 ;
163117}
164-
165118FreeSid (LocalSystemSid );
166- free (InfoBuffer );
167119
168- /* Now check for group SID */
169- if (!pgwin32_get_dynamic_tokeninfo (AccessToken ,TokenGroups ,& InfoBuffer ,
170- errbuf ,sizeof (errbuf )))
120+ if (IsMember )
171121{
172- fprintf ( stderr , "%s" , errbuf ) ;
173- return -1 ;
122+ _is_service = 1 ;
123+ return _is_service ;
174124}
175125
176- Groups = (PTOKEN_GROUPS )InfoBuffer ;
177-
126+ /* Check for service group membership */
178127if (!AllocateAndInitializeSid (& NtAuthority ,1 ,
179128SECURITY_SERVICE_RID ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
180129& ServiceSid ))
181130{
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 ());
185133return -1 ;
186134}
187135
188- _is_service = 0 ;
189- for (x = 0 ;x < Groups -> GroupCount ;x ++ )
136+ if (!CheckTokenMembership (NULL ,ServiceSid ,& IsMember ))
190137{
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 ;
196142}
197-
198- free (InfoBuffer );
199143FreeSid (ServiceSid );
200144
201- CloseHandle (AccessToken );
145+ if (IsMember )
146+ _is_service = 1 ;
147+ else
148+ _is_service = 0 ;
202149
203150return _is_service ;
204151}
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- }