8cf1dafeb74acc677696667a3fa39dea86b091da
[openafs.git] / src / WINNT / client_config / isadmin.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 extern "C" {
11 #include <afs/param.h>
12 #include <afs/stds.h>
13 }
14
15 #include <windows.h>
16 #include <WINNT/TaLocale.h>
17
18
19 /*
20  * ISWINNT ____________________________________________________________________
21  *
22  */
23
24 BOOL IsWindowsNT (void)
25 {
26    static BOOL fChecked = FALSE;
27    static BOOL fIsWinNT = FALSE;
28
29    if (!fChecked)
30       {
31       fChecked = TRUE;
32
33       OSVERSIONINFO Version;
34       memset (&Version, 0x00, sizeof(Version));
35       Version.dwOSVersionInfoSize = sizeof(Version);
36
37       if (GetVersionEx (&Version))
38          {
39          if (Version.dwPlatformId == VER_PLATFORM_WIN32_NT)
40             fIsWinNT = TRUE;
41          }
42       }
43
44    return fIsWinNT;
45 }
46
47
48 /*
49  * ISADMIN ____________________________________________________________________
50  *
51  */
52
53 #define AFSCLIENT_ADMIN_GROUPNAME "AFS Client Admins"
54
55 BOOL IsAdmin (void)
56 {
57     static BOOL fAdmin = FALSE;
58     static BOOL fTested = FALSE;
59
60     if (!fTested)
61     {
62         /* Obtain the SID for the AFS client admin group.  If the group does
63          * not exist, then assume we have AFS client admin privileges.
64          */
65         PSID psidAdmin = NULL;
66         DWORD dwSize, dwSize2;
67         char pszAdminGroup[ MAX_COMPUTERNAME_LENGTH + sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2 ];
68         char *pszRefDomain = NULL;
69         SID_NAME_USE snu = SidTypeGroup;
70
71         dwSize = sizeof(pszAdminGroup);
72
73         if (!GetComputerName(pszAdminGroup, &dwSize)) {
74             /* Can't get computer name.  We return false in this case.
75                Retain fAdmin and fTested. This shouldn't happen.*/
76             return FALSE;
77         }
78
79         dwSize = 0;
80         dwSize2 = 0;
81
82         strcat(pszAdminGroup,"\\");
83         strcat(pszAdminGroup, AFSCLIENT_ADMIN_GROUPNAME);
84
85         LookupAccountName(NULL, pszAdminGroup, NULL, &dwSize, NULL, &dwSize2, &snu);
86         /* that should always fail. */
87
88         if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
89             /* if we can't find the group, then we allow the operation */
90             fAdmin = TRUE;
91             return TRUE;
92         }
93
94         if (dwSize == 0 || dwSize2 == 0) {
95             /* Paranoia */
96             fAdmin = TRUE;
97             return TRUE;
98         }
99
100         psidAdmin = (PSID)malloc(dwSize); memset(psidAdmin,0,dwSize);
101         pszRefDomain = (char *)malloc(dwSize2);
102
103         if (!LookupAccountName(NULL, pszAdminGroup, psidAdmin, &dwSize, pszRefDomain, &dwSize2, &snu)) {
104             /* We can't lookup the group now even though we looked it up earlier.  
105                Could this happen? */
106             fAdmin = TRUE;
107         } else {
108             /* Then open our current ProcessToken */
109             HANDLE hToken;
110
111             if (OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hToken))
112             {
113
114                 if (!CheckTokenMembership(hToken, psidAdmin, &fAdmin)) {
115                     /* We'll have to allocate a chunk of memory to store the list of
116                      * groups to which this user belongs; find out how much memory
117                      * we'll need.
118                      */
119                     DWORD dwSize = 0;
120                     PTOKEN_GROUPS pGroups;
121
122                     GetTokenInformation (hToken, TokenGroups, NULL, dwSize, &dwSize);
123
124                     pGroups = (PTOKEN_GROUPS)malloc(dwSize);
125
126                     /* Allocate that buffer, and read in the list of groups. */
127                     if (GetTokenInformation (hToken, TokenGroups, pGroups, dwSize, &dwSize))
128                     {
129                         /* Look through the list of group SIDs and see if any of them
130                          * matches the AFS Client Admin group SID.
131                          */
132                         size_t iGroup = 0;
133                         for (; (!fAdmin) && (iGroup < pGroups->GroupCount); ++iGroup)
134                         {
135                             if (EqualSid (psidAdmin, pGroups->Groups[ iGroup ].Sid)) {
136                                 fAdmin = TRUE;
137                             }
138                         }
139                     }
140
141                     if (pGroups)
142                         free(pGroups);
143                 }
144
145                 /* if do not have permission because we were not explicitly listed
146                  * in the Admin Client Group let's see if we are the SYSTEM account
147                  */
148                 if (!fAdmin) {
149                     PTOKEN_USER pTokenUser;
150                     SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
151                     PSID pSidLocalSystem = 0;
152                     DWORD gle;
153
154                     GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
155
156                     pTokenUser = (PTOKEN_USER)malloc(dwSize);
157
158                     if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize))
159                         gle = GetLastError();
160
161                     if (AllocateAndInitializeSid( &SIDAuth, 1,
162                                                   SECURITY_LOCAL_SYSTEM_RID,
163                                                   0, 0, 0, 0, 0, 0, 0,
164                                                   &pSidLocalSystem))
165                     {
166                         if (EqualSid(pTokenUser->User.Sid, pSidLocalSystem)) {
167                             fAdmin = TRUE;
168                         }
169
170                         FreeSid(pSidLocalSystem);
171                     }
172
173                     if ( pTokenUser )
174                         free(pTokenUser);
175                 }
176             }
177         }
178
179         free(psidAdmin);
180         free(pszRefDomain);
181
182         fTested = TRUE;
183     }
184
185     return fAdmin;
186 }
187