66 * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
77 *
88 * IDENTIFICATION
9- * $PostgreSQL: pgsql/src/backend/port/win32/security.c,v 1.6 2004/11/09 13:01:25 petere Exp $
9+ * $PostgreSQL: pgsql/src/backend/port/win32/security.c,v 1.7 2004/11/16 19:52:22 tgl Exp $
1010 *
1111 *-------------------------------------------------------------------------
1212 */
1313
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+
1721/*
1822 * Returns nonzero if the current user has administrative privileges,
1923 * or zero if not.
@@ -26,8 +30,8 @@ pgwin32_is_admin(void)
2630{
2731HANDLE AccessToken ;
2832char * InfoBuffer = NULL ;
33+ char errbuf [256 ];
2934PTOKEN_GROUPS Groups ;
30- DWORD InfoBufferSize ;
3135PSID AdministratorsSid ;
3236PSID PowerUsersSid ;
3337SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY };
@@ -41,36 +45,15 @@ pgwin32_is_admin(void)
4145exit (1 );
4246}
4347
44- if (GetTokenInformation (AccessToken ,TokenGroups ,NULL ,0 ,& InfoBufferSize ))
48+ if (!pgwin32_get_dynamic_tokeninfo (AccessToken ,TokenGroups ,
49+ & InfoBuffer ,errbuf ,sizeof (errbuf )))
4550{
46- write_stderr ("could not get token information: got zero size\n" );
51+ write_stderr (errbuf );
4752exit (1 );
4853}
4954
50- if (GetLastError ()!= ERROR_INSUFFICIENT_BUFFER )
51- {
52- write_stderr ("could not get token information: error code %d\n" ,
53- (int )GetLastError ());
54- exit (1 );
55- }
56-
57- InfoBuffer = malloc (InfoBufferSize );
58- if (!InfoBuffer )
59- {
60- write_stderr ("could not allocate %i bytes for token information\n" ,
61- (int )InfoBufferSize );
62- exit (1 );
63- }
6455Groups = (PTOKEN_GROUPS )InfoBuffer ;
6556
66- if (!GetTokenInformation (AccessToken ,TokenGroups ,InfoBuffer ,
67- InfoBufferSize ,& InfoBufferSize ))
68- {
69- write_stderr ("could not get token information: error code %d\n" ,
70- (int )GetLastError ());
71- exit (1 );
72- }
73-
7457CloseHandle (AccessToken );
7558
7659if (!AllocateAndInitializeSid (& NtAuthority ,2 ,
@@ -131,10 +114,10 @@ pgwin32_is_service(void)
131114{
132115static int _is_service = -1 ;
133116HANDLE AccessToken ;
134- UCHAR InfoBuffer [ 1024 ] ;
135- PTOKEN_GROUPS Groups = ( PTOKEN_GROUPS ) InfoBuffer ;
136- PTOKEN_USER User = ( PTOKEN_USER ) InfoBuffer ;
137- DWORD InfoBufferSize ;
117+ char * InfoBuffer = NULL ;
118+ char errbuf [ 256 ] ;
119+ PTOKEN_GROUPS Groups ;
120+ PTOKEN_USER User ;
138121PSID ServiceSid ;
139122PSID LocalSystemSid ;
140123SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY };
@@ -152,13 +135,15 @@ pgwin32_is_service(void)
152135}
153136
154137/* First check for local system */
155- if (!GetTokenInformation (AccessToken ,TokenUser ,InfoBuffer ,1024 ,& InfoBufferSize ))
138+ if (!pgwin32_get_dynamic_tokeninfo (AccessToken ,TokenUser ,& InfoBuffer ,
139+ errbuf ,sizeof (errbuf )))
156140{
157- fprintf (stderr ,"could not get token information: error code %d\n" ,
158- (int )GetLastError ());
141+ fprintf (stderr ,errbuf );
159142return -1 ;
160143}
161144
145+ User = (PTOKEN_USER )InfoBuffer ;
146+
162147if (!AllocateAndInitializeSid (& NtAuthority ,1 ,
163148SECURITY_LOCAL_SYSTEM_RID ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
164149& LocalSystemSid ))
@@ -171,26 +156,31 @@ pgwin32_is_service(void)
171156if (EqualSid (LocalSystemSid ,User -> User .Sid ))
172157{
173158FreeSid (LocalSystemSid );
159+ free (InfoBuffer );
174160CloseHandle (AccessToken );
175161_is_service = 1 ;
176162return _is_service ;
177163}
178164
179165FreeSid (LocalSystemSid );
166+ free (InfoBuffer );
180167
181168/* Now check for group SID */
182- if (!GetTokenInformation (AccessToken ,TokenGroups ,InfoBuffer ,1024 ,& InfoBufferSize ))
169+ if (!pgwin32_get_dynamic_tokeninfo (AccessToken ,TokenGroups ,& InfoBuffer ,
170+ errbuf ,sizeof (errbuf )))
183171{
184- fprintf (stderr ,"could not get token information: error code %d\n" ,
185- (int )GetLastError ());
172+ fprintf (stderr ,errbuf );
186173return -1 ;
187174}
188175
176+ Groups = (PTOKEN_GROUPS )InfoBuffer ;
177+
189178if (!AllocateAndInitializeSid (& NtAuthority ,1 ,
190179SECURITY_SERVICE_RID ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
191180& ServiceSid ))
192181{
193182fprintf (stderr ,"could not get SID for service group\n" );
183+ free (InfoBuffer );
194184CloseHandle (AccessToken );
195185return -1 ;
196186}
@@ -205,9 +195,54 @@ pgwin32_is_service(void)
205195}
206196}
207197
198+ free (InfoBuffer );
208199FreeSid (ServiceSid );
209200
210201CloseHandle (AccessToken );
211202
212203return _is_service ;
213204}
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 %d\n" ,
227+ (int )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 %d\n" ,
243+ (int )GetLastError ());
244+ return FALSE;
245+ }
246+
247+ return TRUE;
248+ }