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,...)
4853int
4954pgwin32_is_admin (void )
5055{
56+ HANDLE AccessToken ;
57+ char * InfoBuffer = NULL ;
58+ char errbuf [256 ];
59+ PTOKEN_GROUPS Groups ;
5160PSID AdministratorsSid ;
5261PSID PowerUsersSid ;
5362SID_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
5784if (!AllocateAndInitializeSid (& NtAuthority ,2 ,
5885SECURITY_BUILTIN_DOMAIN_RID ,
@@ -74,35 +101,34 @@ pgwin32_is_admin(void)
74101exit (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 );
85119FreeSid (AdministratorsSid );
86120FreeSid (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 asLocalSystem (only used by services)
128+ * 1) We are running asLocal 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
117143pgwin32_is_service (void )
118144{
119145static 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 ;
121151PSID ServiceSid ;
122152PSID LocalSystemSid ;
123153SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY };
154+ UINT x ;
124155
125156/* Only check the first time */
126157if (_is_service != -1 )
127158return _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+
130177if (!AllocateAndInitializeSid (& NtAuthority ,1 ,
131178SECURITY_LOCAL_SYSTEM_RID ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
132179& LocalSystemSid ))
133180{
134181fprintf (stderr ,"could not get SID for local system account\n" );
182+ CloseHandle (AccessToken );
135183return -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 ());
142188FreeSid (LocalSystemSid );
143- return -1 ;
189+ free (InfoBuffer );
190+ CloseHandle (AccessToken );
191+ _is_service = 1 ;
192+ return _is_service ;
144193}
194+
145195FreeSid (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+
154208if (!AllocateAndInitializeSid (& NtAuthority ,1 ,
155209SECURITY_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 );
160215return -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 );
170230FreeSid (ServiceSid );
171231
172- if (IsMember )
173- _is_service = 1 ;
174- else
175- _is_service = 0 ;
232+ CloseHandle (AccessToken );
176233
177234return _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+ }