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.

400 lines
10 KiB

  1. //******************************************************************************
  2. //
  3. // Copyright (c) 1999-2000, Microsoft Corporation, All rights reserved
  4. //
  5. //*****************************************************************************
  6. #include "precomp.h"
  7. #include <stdio.h>
  8. #include <wbemcomn.h>
  9. #include <tkncache.h>
  10. #include <groupsforuser.h>
  11. #include <selfinst.h>
  12. #include <tchar.h>
  13. CWmiToken::CWmiToken(ADDREF CTokenCache* pCache, const PSID pSid,
  14. ACQUIRE HANDLE hToken) :
  15. CUnkBase<IWbemToken, &IID_IWbemToken>(NULL), m_hToken(hToken),
  16. m_pCache(pCache), m_pSid(NULL), m_bOwnHandle(true)
  17. {
  18. if(m_pCache)
  19. m_pCache->AddRef();
  20. if(pSid)
  21. {
  22. m_pSid = (PSID)new BYTE[GetLengthSid(pSid)];
  23. if(m_pSid == NULL)
  24. return;
  25. CopySid(GetLengthSid(pSid), m_pSid, pSid);
  26. }
  27. }
  28. CWmiToken::CWmiToken(READ_ONLY HANDLE hToken) :
  29. CUnkBase<IWbemToken, &IID_IWbemToken>(NULL), m_hToken(hToken),
  30. m_pCache(NULL), m_pSid(NULL), m_bOwnHandle(false)
  31. {
  32. }
  33. CWmiToken::~CWmiToken()
  34. {
  35. if(m_pCache)
  36. m_pCache->Release();
  37. if(m_bOwnHandle)
  38. CloseHandle(m_hToken);
  39. delete [] (BYTE*)m_pSid;
  40. }
  41. STDMETHODIMP CWmiToken::AccessCheck(DWORD dwDesiredAccess, const BYTE* pSD,
  42. DWORD* pdwGrantedAccess)
  43. {
  44. if(m_hToken == NULL)
  45. return WBEM_E_CRITICAL_ERROR;
  46. // BUGBUG: figure out what this is for!
  47. GENERIC_MAPPING map;
  48. map.GenericRead = 1;
  49. map.GenericWrite = 0x1C;
  50. map.GenericExecute = 2;
  51. map.GenericAll = 0x6001f;
  52. PRIVILEGE_SET ps;
  53. DWORD dwPrivLength = sizeof(ps);
  54. BOOL bStatus;
  55. BOOL bRes = ::AccessCheck((SECURITY_DESCRIPTOR*)pSD, m_hToken,
  56. dwDesiredAccess, &map, &ps,
  57. &dwPrivLength, pdwGrantedAccess, &bStatus);
  58. if(!bRes)
  59. {
  60. return WBEM_E_ACCESS_DENIED;
  61. }
  62. else
  63. {
  64. return WBEM_S_NO_ERROR;
  65. }
  66. }
  67. #ifdef __NOAUTHZ_
  68. typedef NTSTATUS (NTAPI *PNtCreateToken)(
  69. OUT PHANDLE TokenHandle,
  70. IN ACCESS_MASK DesiredAccess,
  71. IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
  72. IN TOKEN_TYPE TokenType,
  73. IN PLUID AuthenticationId,
  74. IN PLARGE_INTEGER ExpirationTime,
  75. IN PTOKEN_USER User,
  76. IN PTOKEN_GROUPS Groups,
  77. IN PTOKEN_PRIVILEGES Privileges,
  78. IN PTOKEN_OWNER Owner OPTIONAL,
  79. IN PTOKEN_PRIMARY_GROUP PrimaryGroup,
  80. IN PTOKEN_DEFAULT_DACL DefaultDacl OPTIONAL,
  81. IN PTOKEN_SOURCE TokenSource
  82. );
  83. void EnableAllPrivileges()
  84. {
  85. BOOL bRes;
  86. HANDLE hToken = NULL;
  87. bRes = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, FALSE, &hToken);
  88. // Get the privileges
  89. // ==================
  90. DWORD dwLen;
  91. TOKEN_USER tu;
  92. memset(&tu,0,sizeof(TOKEN_USER));
  93. bRes = GetTokenInformation(hToken, TokenPrivileges, &tu, sizeof(TOKEN_USER), &dwLen);
  94. BYTE* pBuffer = new BYTE[dwLen];
  95. if(pBuffer == NULL)
  96. {
  97. CloseHandle(hToken);
  98. return ;
  99. }
  100. bRes = GetTokenInformation(hToken, TokenPrivileges, pBuffer, dwLen,
  101. &dwLen);
  102. if(!bRes)
  103. {
  104. CloseHandle(hToken);
  105. delete [] pBuffer;
  106. return ;
  107. }
  108. // Iterate through all the privileges and enable them all
  109. // ======================================================
  110. TOKEN_PRIVILEGES* pPrivs = (TOKEN_PRIVILEGES*)pBuffer;
  111. for(DWORD i = 0; i < pPrivs->PrivilegeCount; i++)
  112. {
  113. pPrivs->Privileges[i].Attributes |= SE_PRIVILEGE_ENABLED;
  114. TCHAR szBuffer[256];
  115. DWORD dwLen = 256;
  116. LookupPrivilegeName(NULL, &pPrivs->Privileges[i].Luid, szBuffer, &dwLen);
  117. }
  118. // Store the information back into the token
  119. // =========================================
  120. bRes = AdjustTokenPrivileges(hToken, FALSE, pPrivs, 0, NULL, NULL);
  121. delete [] pBuffer;
  122. CloseHandle(hToken);
  123. }
  124. BOOL CTokenCache::ConstructTokenFromHandle(HANDLE hToken, const BYTE* pSid,
  125. IWbemToken** ppToken)
  126. {
  127. BOOL bRes;
  128. //
  129. // Retrieve the user sid from the token given to us
  130. //
  131. DWORD dwSidLen = 0;
  132. bRes = GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSidLen);
  133. if(dwSidLen == 0)
  134. return FALSE;
  135. TOKEN_USER* pUser = (TOKEN_USER*)new BYTE[dwSidLen];
  136. if(pUser == NULL)
  137. return FALSE;
  138. CVectorDeleteMe<BYTE> vdm1((BYTE*)pUser);
  139. bRes = GetTokenInformation(hToken, TokenUser, pUser, dwSidLen, &dwSidLen);
  140. if(!bRes)
  141. return FALSE;
  142. //
  143. // Compare to the required SID --- must match for success
  144. //
  145. if(!EqualSid((PSID)pSid, pUser->User.Sid))
  146. return FALSE;
  147. //
  148. // Construct an IWbemToken object to return.
  149. //
  150. CWmiToken* pNewToken = new CWmiToken(this, (const PSID)pSid, hToken);
  151. if(pNewToken == NULL)
  152. return FALSE;
  153. pNewToken->QueryInterface(IID_IWbemToken, (void**)ppToken);
  154. return TRUE;
  155. }
  156. HRESULT STDMETHODCALLTYPE CTokenCache::GetToken(const BYTE* pSid,
  157. IWbemToken** ppToken)
  158. {
  159. //
  160. // Search for the SID in the array
  161. //
  162. {
  163. CInCritSec ics(&m_cs);
  164. DWORD dwLen = GetLengthSid((const PSID)pSid);
  165. for(int i = 0; i < m_apTokens.GetSize(); i++)
  166. {
  167. CWmiToken* pToken = m_apTokens[i];
  168. if(EqualSid(pToken->m_pSid, (const PSID)pSid))
  169. {
  170. // Found it!
  171. *ppToken = pToken;
  172. pToken->AddRef();
  173. return S_OK;
  174. }
  175. }
  176. }
  177. //
  178. // Not there. Examine the currently available tokens to see if they match.
  179. // Note that we are not going to cache them if found --- we do not want to
  180. // hold on to normally available tokens after the user logs off.
  181. //
  182. BOOL bRes;
  183. HRESULT hres;
  184. // Thread token first
  185. HANDLE hThreadToken = NULL;
  186. bRes = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,
  187. &hThreadToken);
  188. if(bRes)
  189. {
  190. CCloseMe cm(hThreadToken);
  191. if(ConstructTokenFromHandle(hThreadToken, pSid, ppToken))
  192. return WBEM_S_NO_ERROR;
  193. }
  194. // Process token next
  195. RevertToSelf();
  196. HANDLE hProcessToken = NULL;
  197. bRes = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hProcessToken);
  198. if(bRes)
  199. {
  200. CCloseMe cm(hProcessToken);
  201. if(ConstructTokenFromHandle(hProcessToken, pSid, ppToken))
  202. return WBEM_S_NO_ERROR;
  203. }
  204. // COM impersonation last
  205. hres = CoImpersonateClient();
  206. if(SUCCEEDED(hres))
  207. {
  208. bRes = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,
  209. &hThreadToken);
  210. CoRevertToSelf();
  211. if(bRes)
  212. {
  213. CCloseMe cm(hThreadToken);
  214. if(ConstructTokenFromHandle(hThreadToken, pSid, ppToken))
  215. return WBEM_S_NO_ERROR;
  216. }
  217. }
  218. //
  219. //
  220. // No standard token matched --- we are going to have to construct our own
  221. // token. Get the DC to enumerate all the SIDs for this user
  222. //
  223. PSID* aGroupSids = NULL;
  224. DWORD dwSidCount = 0;
  225. try
  226. {
  227. NTSTATUS ntst = EnumGroupsForUser((const PSID)pSid, NULL, &aGroupSids,
  228. &dwSidCount);
  229. if(ntst != STATUS_SUCCESS)
  230. {
  231. WMI_REPORT((WMI_CANNOT_GET_USER_GROUPS, pSid));
  232. //
  233. // Continue --- even though we don't have all the groups, we might be
  234. // able to get there
  235. //
  236. }
  237. //
  238. // Get the NtCreateToken entry point in NTDLL
  239. //
  240. ImpersonateSelf(SecurityImpersonation);
  241. EnableAllPrivileges();
  242. HINSTANCE hInst = LoadLibrary(_TEXT("ntdll.dll"));
  243. PNtCreateToken pNtCreateToken = (PNtCreateToken)GetProcAddress(hInst, "NtCreateToken");
  244. FreeLibrary(hInst);
  245. //
  246. // Prepare the paramters for NtCreateToken
  247. //
  248. HANDLE hHandle;
  249. LUID luidAuth = SYSTEM_LUID;
  250. LARGE_INTEGER exp;
  251. exp.QuadPart = 0;
  252. TOKEN_USER User;
  253. User.User.Sid = (const PSID)pSid;
  254. User.User.Attributes = 0;
  255. //
  256. // Allocate a TOKEN_GROUPS large enough for all the SIDs
  257. //
  258. TOKEN_GROUPS* pGroups = (TOKEN_GROUPS*)
  259. new BYTE[sizeof(TOKEN_GROUPS) + dwSidCount* sizeof(SID_AND_ATTRIBUTES)];
  260. if(pGroups == NULL)
  261. return WBEM_E_OUT_OF_MEMORY;
  262. CVectorDeleteMe<BYTE> vdm((BYTE*)pGroups);
  263. pGroups->GroupCount = dwSidCount;
  264. for(DWORD i = 0; i < dwSidCount; i++)
  265. {
  266. pGroups->Groups[i].Sid = aGroupSids[i];
  267. pGroups->Groups[i].Attributes = 0;
  268. }
  269. TOKEN_PRIVILEGES Privs;
  270. Privs.PrivilegeCount = 0;
  271. TOKEN_PRIMARY_GROUP Prim;
  272. if(dwSidCount > 0)
  273. Prim.PrimaryGroup = aGroupSids[0];
  274. else
  275. Prim.PrimaryGroup = (const PSID)pSid;
  276. TOKEN_SOURCE Source;
  277. strcpy(Source.SourceName, "me");
  278. Source.SourceIdentifier.HighPart = 0;
  279. Source.SourceIdentifier.LowPart = 0;
  280. NTSTATUS st = (*pNtCreateToken)(
  281. &hHandle,
  282. TOKEN_ALL_ACCESS,
  283. NULL, // attr
  284. TokenPrimary,
  285. &luidAuth,
  286. &exp,
  287. &User,
  288. pGroups,
  289. &Privs,
  290. NULL, // owner
  291. &Prim,
  292. NULL, // dacl
  293. &Source);
  294. if(st != STATUS_SUCCESS)
  295. {
  296. WMI_REPORT((WMI_CANNOT_CREATE_TOKEN, pSid, st));
  297. return WBEM_E_FAILED;
  298. }
  299. //
  300. // Construct a new CWmiToken object and add it to the list
  301. //
  302. {
  303. CInCritSec ics(&m_cs);
  304. CWmiToken* pNewToken = new CWmiToken(this, (const PSID) pSid, hHandle);
  305. if(pNewToken == NULL)
  306. return WBEM_E_OUT_OF_MEMORY;
  307. m_apTokens.Add(pNewToken);
  308. return pNewToken->QueryInterface(IID_IWbemToken, (void**)ppToken);
  309. }
  310. }
  311. catch(...)
  312. {
  313. RevertToSelf();
  314. if(aGroupSids)
  315. {
  316. for(DWORD i = 0; i < dwSidCount; i++)
  317. delete [] aGroupSids[i];
  318. delete [] aGroupSids;
  319. }
  320. throw;
  321. }
  322. }
  323. HRESULT STDMETHODCALLTYPE CTokenCache::Shutdown()
  324. {
  325. m_apTokens.RemoveAll();
  326. return WBEM_S_NO_ERROR;
  327. }
  328. #endif // __NOAUTHZ_