Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

313 lines
9.6 KiB

  1. //#pragma title( "IsAdmin.cpp - Determine if user is administrator" )
  2. /*
  3. Copyright (c) 1995-1998, Mission Critical Software, Inc. All rights reserved.
  4. ===============================================================================
  5. Module - IsAdmin.cpp
  6. System - Common
  7. Author - Rich Denham
  8. Created - 1996-06-04
  9. Description - Determine if user is administrator (local or remote)
  10. Updates -
  11. ===============================================================================
  12. */
  13. #ifdef USE_STDAFX
  14. # include "stdafx.h"
  15. #else
  16. # include <windows.h>
  17. #endif
  18. #include <lm.h>
  19. #include "Common.hpp"
  20. #include "UString.hpp"
  21. #include "IsAdmin.hpp"
  22. namespace
  23. {
  24. #ifndef SECURITY_MAX_SID_SIZE
  25. #define SECURITY_MAX_SID_SIZE (sizeof(SID) - sizeof(DWORD) + (SID_MAX_SUB_AUTHORITIES * sizeof(DWORD)))
  26. #endif
  27. const DWORD MAX_VERSION_2_ACE_SIZE = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + SECURITY_MAX_SID_SIZE;
  28. // GetEffectiveToken
  29. //
  30. // Brown, Keith. 2000. Programming Windows Security. Reading MA: Addison-Wesley
  31. // Pages 120-121
  32. HANDLE __stdcall GetEffectiveToken(DWORD dwDesiredAccess, BOOL bImpersonation, SECURITY_IMPERSONATION_LEVEL silLevel)
  33. {
  34. HANDLE hToken = 0;
  35. if (!OpenThreadToken(GetCurrentThread(), dwDesiredAccess, TRUE, &hToken))
  36. {
  37. if (GetLastError() == ERROR_NO_TOKEN)
  38. {
  39. DWORD dwAccess = bImpersonation ? TOKEN_DUPLICATE : dwDesiredAccess;
  40. if (OpenProcessToken(GetCurrentProcess(), dwAccess, &hToken))
  41. {
  42. if (bImpersonation)
  43. {
  44. // convert primary to impersonation token
  45. HANDLE hImpersonationToken = 0;
  46. DuplicateTokenEx(hToken, dwDesiredAccess, 0, silLevel, TokenImpersonation, &hImpersonationToken);
  47. CloseHandle(hToken);
  48. hToken = hImpersonationToken;
  49. }
  50. }
  51. }
  52. }
  53. return hToken;
  54. }
  55. // CheckTokenMembership
  56. //
  57. // Brown, Keith. 2000. Programming Windows Security. Reading MA: Addison-Wesley
  58. // Pages 130-131
  59. //#if (_WIN32_WINNT < 0x0500)
  60. #if TRUE // always use our function
  61. BOOL WINAPI AdmtCheckTokenMembership(HANDLE hToken, PSID pSid, PBOOL pbIsMember)
  62. {
  63. // if no token was passed, CTM uses the effective
  64. // security context (the thread or process token)
  65. if (!hToken)
  66. {
  67. hToken = GetEffectiveToken(TOKEN_QUERY, TRUE, SecurityIdentification);
  68. }
  69. if (!hToken)
  70. {
  71. return FALSE;
  72. }
  73. // create a security descriptor that grants a
  74. // specific permission only to the specified SID
  75. BYTE dacl[sizeof ACL + MAX_VERSION_2_ACE_SIZE];
  76. ACL* pdacl = (ACL*)dacl;
  77. InitializeAcl(pdacl, sizeof dacl, ACL_REVISION);
  78. AddAccessAllowedAce(pdacl, ACL_REVISION, 1, pSid);
  79. SECURITY_DESCRIPTOR sd;
  80. InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
  81. SID sidWorld = { SID_REVISION, 1, SECURITY_WORLD_SID_AUTHORITY, SECURITY_WORLD_RID };
  82. SetSecurityDescriptorOwner(&sd, &sidWorld, FALSE);
  83. SetSecurityDescriptorGroup(&sd, &sidWorld, FALSE);
  84. SetSecurityDescriptorDacl(&sd, TRUE, pdacl, FALSE);
  85. // now let AccessCheck do all the hard work
  86. GENERIC_MAPPING gm = { 0, 0, 0, 1 };
  87. PRIVILEGE_SET ps;
  88. DWORD cb = sizeof ps;
  89. DWORD ga;
  90. return AccessCheck(&sd, hToken, 1, &gm, &ps, &cb, &ga, pbIsMember);
  91. }
  92. #else
  93. #define AdmtCheckTokenMembership CheckTokenMembership
  94. #endif
  95. } // namespace
  96. ///////////////////////////////////////////////////////////////////////////////
  97. // Determine if user is administrator on local machine //
  98. ///////////////////////////////////////////////////////////////////////////////
  99. DWORD // ret-OS return code, 0=User is admin
  100. IsAdminLocal()
  101. {
  102. DWORD dwError = NO_ERROR;
  103. // create well known SID Administrators
  104. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  105. PSID psidAdministrators;
  106. BOOL bSid = AllocateAndInitializeSid(
  107. &siaNtAuthority,
  108. 2,
  109. SECURITY_BUILTIN_DOMAIN_RID,
  110. DOMAIN_ALIAS_RID_ADMINS,
  111. 0,
  112. 0,
  113. 0,
  114. 0,
  115. 0,
  116. 0,
  117. &psidAdministrators
  118. );
  119. if (bSid)
  120. {
  121. // check if token membership includes Administrators
  122. BOOL bIsMember;
  123. if (AdmtCheckTokenMembership(0, psidAdministrators, &bIsMember))
  124. {
  125. dwError = bIsMember ? NO_ERROR : ERROR_ACCESS_DENIED;
  126. }
  127. else
  128. {
  129. dwError = GetLastError();
  130. }
  131. FreeSid(psidAdministrators);
  132. }
  133. else
  134. {
  135. dwError = GetLastError();
  136. }
  137. return dwError;
  138. }
  139. ///////////////////////////////////////////////////////////////////////////////
  140. // Determine if user is administrator on remote machine //
  141. ///////////////////////////////////////////////////////////////////////////////
  142. DWORD // ret-OS return code, 0=User is admin
  143. IsAdminRemote(
  144. WCHAR const * pMachine // in -\\machine name
  145. )
  146. {
  147. DWORD osRc; // OS return code
  148. HANDLE hToken=INVALID_HANDLE_VALUE; // process token
  149. BYTE bufTokenGroups[10000]; // token group information
  150. DWORD lenTokenGroups; // returned length of token group information
  151. BYTE bufTokenUser[1000];
  152. DWORD lenTokenUser;
  153. // SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  154. PTOKEN_GROUPS ptgGroups = (PTOKEN_GROUPS) bufTokenGroups;
  155. PTOKEN_USER ptUser = (PTOKEN_USER)bufTokenUser;
  156. // DWORD iGroup; // group number index
  157. LPLOCALGROUP_MEMBERS_INFO_0 pBuf = NULL;
  158. DWORD dwPrefMaxLen = 255;
  159. DWORD dwEntriesRead = 0;
  160. DWORD dwTotalEntries = 0;
  161. DWORD_PTR dwResumeHandle = 0;
  162. // DWORD dwTotalCount = 0;
  163. // DWORD rcOs = 0;
  164. WCHAR grpName[255];
  165. PSID pSid;
  166. SID_NAME_USE use;
  167. DWORD dwNameLen = 255;
  168. DWORD dwDomLen = 255;
  169. WCHAR domain[255];
  170. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  171. // SID_IDENTIFIER_AUTHORITY creatorIA = SECURITY_CREATOR_SID_AUTHORITY;
  172. BOOL bIsAdmin = FALSE;
  173. if ( OpenProcessToken( GetCurrentProcess(), TOKEN_READ, &hToken ) )
  174. {
  175. if ( GetTokenInformation( hToken, TokenGroups, bufTokenGroups, sizeof bufTokenGroups, &lenTokenGroups ) )
  176. {
  177. if ( GetTokenInformation(hToken,TokenUser,bufTokenUser,sizeof bufTokenUser,&lenTokenUser) )
  178. {
  179. // build the Administrators SID
  180. if ( AllocateAndInitializeSid(
  181. &sia,
  182. 2,
  183. SECURITY_BUILTIN_DOMAIN_RID,
  184. DOMAIN_ALIAS_RID_ADMINS,
  185. 0, 0, 0, 0, 0, 0,
  186. &pSid
  187. ) )
  188. {
  189. // and look up the administrators group on the specified machine
  190. if ( LookupAccountSid(pMachine, pSid, grpName, &dwNameLen, domain, &dwDomLen, &use) )
  191. {
  192. /*
  193. // enumerate the contents of the administrators group on the specified machine
  194. do
  195. {
  196. osRc = NetLocalGroupGetMembers(
  197. const_cast<WCHAR*>(pMachine),
  198. grpName,
  199. 0,
  200. (LPBYTE*)&pBuf,
  201. dwPrefMaxLen,
  202. &dwEntriesRead,
  203. &dwTotalEntries,
  204. &dwResumeHandle
  205. );
  206. if ( !osRc || osRc == ERROR_MORE_DATA )
  207. {
  208. for ( UINT i = 0 ; i < dwEntriesRead ; i++ )
  209. {
  210. // for each SID in the administrators group, see if that SID is in our token
  211. if ( EqualSid( pBuf[i].lgrmi0_sid , ptUser->User.Sid) )
  212. {
  213. bIsAdmin = TRUE;
  214. break;
  215. }
  216. for ( iGroup = 0;
  217. iGroup < ptgGroups->GroupCount;
  218. iGroup++ )
  219. {
  220. if ( EqualSid( pBuf[i].lgrmi0_sid,ptgGroups->Groups[iGroup].Sid ) )
  221. {
  222. osRc = 0;
  223. bIsAdmin = TRUE;
  224. break;
  225. }
  226. }
  227. if ( bIsAdmin )
  228. break;
  229. }
  230. }
  231. if ( pBuf )
  232. NetApiBufferFree(pBuf);
  233. if ( bIsAdmin )
  234. break;
  235. } while ( osRc == ERROR_MORE_DATA );
  236. */
  237. // remove explict administrator check
  238. bIsAdmin = TRUE;
  239. }
  240. else
  241. osRc = GetLastError();
  242. FreeSid(pSid);
  243. }
  244. else
  245. osRc = GetLastError();
  246. }
  247. else
  248. osRc = GetLastError();
  249. }
  250. else
  251. osRc = GetLastError();
  252. }
  253. else
  254. osRc = GetLastError();
  255. if ( hToken != INVALID_HANDLE_VALUE )
  256. {
  257. CloseHandle( hToken );
  258. hToken = INVALID_HANDLE_VALUE;
  259. }
  260. if ( bIsAdmin )
  261. osRc = 0;
  262. else
  263. if ( ! osRc )
  264. osRc = ERROR_ACCESS_DENIED;
  265. return osRc;
  266. }
  267. // IsAdmin.cpp - end of file