Leaked source code of windows server 2003
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.

372 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. if (!InitializeAcl(pdacl, sizeof dacl, ACL_REVISION))
  78. return FALSE;
  79. AddAccessAllowedAce(pdacl, ACL_REVISION, 1, pSid);
  80. SECURITY_DESCRIPTOR sd;
  81. if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
  82. return FALSE;
  83. SID sidWorld = { SID_REVISION, 1, SECURITY_WORLD_SID_AUTHORITY, SECURITY_WORLD_RID };
  84. SetSecurityDescriptorOwner(&sd, &sidWorld, FALSE);
  85. SetSecurityDescriptorGroup(&sd, &sidWorld, FALSE);
  86. SetSecurityDescriptorDacl(&sd, TRUE, pdacl, FALSE);
  87. // now let AccessCheck do all the hard work
  88. GENERIC_MAPPING gm = { 0, 0, 0, 1 };
  89. PRIVILEGE_SET ps;
  90. DWORD cb = sizeof ps;
  91. DWORD ga;
  92. return AccessCheck(&sd, hToken, 1, &gm, &ps, &cb, &ga, pbIsMember);
  93. }
  94. #else
  95. #define AdmtCheckTokenMembership CheckTokenMembership
  96. #endif
  97. } // namespace
  98. ///////////////////////////////////////////////////////////////////////////////
  99. // Determine if user is administrator on local machine //
  100. ///////////////////////////////////////////////////////////////////////////////
  101. typedef BOOL (APIENTRY *PCHECKTOKENMEMBERSHIP)(HANDLE, PSID, PBOOL);
  102. DWORD // ret-OS return code, 0=User is admin
  103. IsAdminLocal()
  104. {
  105. DWORD dwError = NO_ERROR;
  106. PCHECKTOKENMEMBERSHIP pCheckTokenMembershipInDll = NULL;
  107. // try to load the CheckTokenMembership function from advapi32.dl
  108. HMODULE hAdvApi32 = LoadLibrary(L"advapi32.dll");
  109. if (hAdvApi32 != NULL)
  110. {
  111. pCheckTokenMembershipInDll =
  112. (PCHECKTOKENMEMBERSHIP) GetProcAddress(hAdvApi32, "CheckTokenMembership");
  113. }
  114. // create well known SID Administrators
  115. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  116. PSID psidAdministrators;
  117. BOOL bSid = AllocateAndInitializeSid(
  118. &siaNtAuthority,
  119. 2,
  120. SECURITY_BUILTIN_DOMAIN_RID,
  121. DOMAIN_ALIAS_RID_ADMINS,
  122. 0,
  123. 0,
  124. 0,
  125. 0,
  126. 0,
  127. 0,
  128. &psidAdministrators
  129. );
  130. if (bSid)
  131. {
  132. // check if token membership includes Administrators
  133. BOOL bIsMember;
  134. BOOL result;
  135. if (pCheckTokenMembershipInDll != NULL)
  136. {
  137. result = (*pCheckTokenMembershipInDll)(0, psidAdministrators, &bIsMember);
  138. }
  139. else
  140. result = AdmtCheckTokenMembership(0, psidAdministrators, &bIsMember);
  141. if (result != FALSE)
  142. {
  143. dwError = bIsMember ? NO_ERROR : ERROR_ACCESS_DENIED;
  144. }
  145. else
  146. {
  147. dwError = GetLastError();
  148. }
  149. FreeSid(psidAdministrators);
  150. }
  151. else
  152. {
  153. dwError = GetLastError();
  154. }
  155. if (hAdvApi32 != NULL)
  156. FreeLibrary(hAdvApi32);
  157. return dwError;
  158. }
  159. //------------------------------------------------------------------------------
  160. // IsDomainAdmin Function
  161. //
  162. // Synopsis
  163. // Checks if caller is a domain administrator in the specified domain.
  164. //
  165. // Arguments
  166. // psidDomain - SID for domain of interest
  167. //
  168. // Return Value
  169. // Returns ERROR_SUCCESS if caller is a domain administrator,
  170. // ERROR_ACCESS_DENIED if not or other error code if unable to check token
  171. // membership.
  172. //------------------------------------------------------------------------------
  173. DWORD __stdcall IsDomainAdmin(PSID psidDomain)
  174. {
  175. DWORD dwError = ERROR_SUCCESS;
  176. //
  177. // Validate argument.
  178. //
  179. if ((psidDomain == NULL) || (IsValidSid(psidDomain) == FALSE))
  180. {
  181. return ERROR_INVALID_PARAMETER;
  182. }
  183. // try to load the CheckTokenMembership function from advapi32.dl
  184. HMODULE hAdvApi32 = LoadLibrary(L"advapi32.dll");
  185. PCHECKTOKENMEMBERSHIP pCheckTokenMembership = NULL;
  186. if (hAdvApi32 != NULL)
  187. {
  188. pCheckTokenMembership = (PCHECKTOKENMEMBERSHIP) GetProcAddress(hAdvApi32, "CheckTokenMembership");
  189. }
  190. //
  191. // create well known SID Administrators
  192. //
  193. PSID psidDomainAdmins = NULL;
  194. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  195. PUCHAR pcSubAuthority = GetSidSubAuthorityCount(psidDomain);
  196. BOOL bSid = AllocateAndInitializeSid(
  197. &siaNtAuthority,
  198. *pcSubAuthority + 1,
  199. 0,
  200. 0,
  201. 0,
  202. 0,
  203. 0,
  204. 0,
  205. 0,
  206. 0,
  207. &psidDomainAdmins
  208. );
  209. if (bSid)
  210. {
  211. //
  212. //
  213. //
  214. if (CopySid(GetLengthSid(psidDomain), psidDomainAdmins, psidDomain))
  215. {
  216. pcSubAuthority = GetSidSubAuthorityCount(psidDomainAdmins);
  217. PDWORD pdwRid = GetSidSubAuthority(psidDomainAdmins, *pcSubAuthority);
  218. ++(*pcSubAuthority);
  219. *pdwRid = DOMAIN_GROUP_RID_ADMINS;
  220. //
  221. // check if token membership includes Domain Admins
  222. //
  223. BOOL bCheck;
  224. BOOL bIsMember;
  225. if (pCheckTokenMembership != NULL)
  226. {
  227. bCheck = (*pCheckTokenMembership)(0, psidDomainAdmins, &bIsMember);
  228. }
  229. else
  230. {
  231. bCheck = AdmtCheckTokenMembership(0, psidDomainAdmins, &bIsMember);
  232. }
  233. if (bCheck)
  234. {
  235. dwError = bIsMember ? ERROR_SUCCESS : ERROR_ACCESS_DENIED;
  236. }
  237. else
  238. {
  239. dwError = GetLastError();
  240. }
  241. }
  242. else
  243. {
  244. dwError = GetLastError();
  245. }
  246. FreeSid(psidDomainAdmins);
  247. }
  248. else
  249. {
  250. dwError = GetLastError();
  251. }
  252. if (hAdvApi32 != NULL)
  253. {
  254. FreeLibrary(hAdvApi32);
  255. }
  256. return dwError;
  257. }
  258. ///////////////////////////////////////////////////////////////////////////////
  259. // Determine if user is administrator on remote machine //
  260. ///////////////////////////////////////////////////////////////////////////////
  261. DWORD // ret-OS return code, 0=User is admin
  262. IsAdminRemote(
  263. WCHAR const * pMachine // in -\\machine name
  264. )
  265. {
  266. DWORD osRc; // OS return code
  267. WCHAR grpName[255];
  268. PSID pSid;
  269. SID_NAME_USE use;
  270. DWORD dwNameLen = 255;
  271. DWORD dwDomLen = 255;
  272. WCHAR domain[255];
  273. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  274. BOOL bIsAdmin = FALSE;
  275. // build the Administrators SID
  276. if ( AllocateAndInitializeSid(
  277. &sia,
  278. 2,
  279. SECURITY_BUILTIN_DOMAIN_RID,
  280. DOMAIN_ALIAS_RID_ADMINS,
  281. 0, 0, 0, 0, 0, 0,
  282. &pSid
  283. ) )
  284. {
  285. // and look up the administrators group on the specified machine
  286. if ( LookupAccountSid(pMachine, pSid, grpName, &dwNameLen, domain, &dwDomLen, &use) )
  287. {
  288. // remove explict administrator check
  289. bIsAdmin = TRUE;
  290. }
  291. else
  292. osRc = GetLastError();
  293. FreeSid(pSid);
  294. }
  295. else
  296. osRc = GetLastError();
  297. if ( bIsAdmin )
  298. osRc = 0;
  299. else
  300. if ( ! osRc )
  301. osRc = ERROR_ACCESS_DENIED;
  302. return osRc;
  303. }
  304. // IsAdmin.cpp - end of file