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.

512 lines
16 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: TokenInformation.h
  3. //
  4. // Copyright (c) 1999-2000, Microsoft Corporation
  5. //
  6. // Class to get information about either the current thread/process token or
  7. // a specified token.
  8. //
  9. // History: 1999-10-05 vtan created
  10. // 2000-02-01 vtan moved from Neptune to Whistler
  11. // --------------------------------------------------------------------------
  12. #include "StandardHeader.h"
  13. #include "TokenInformation.h"
  14. // --------------------------------------------------------------------------
  15. // CTokenInformation::CTokenInformation
  16. //
  17. // Arguments: hToken = Optional user token to get information on.
  18. //
  19. // Returns: <none>
  20. //
  21. // Purpose: Duplicates the given token if provided. Otherwise the thread
  22. // token is opened or the process token if that doesn't exist.
  23. //
  24. // History: 1999-10-05 vtan created
  25. // --------------------------------------------------------------------------
  26. CTokenInformation::CTokenInformation (HANDLE hToken) :
  27. _hToken(hToken),
  28. _hTokenToRelease(NULL),
  29. _pvGroupBuffer(NULL),
  30. _pvPrivilegeBuffer(NULL),
  31. _pvUserBuffer(NULL),
  32. _pszUserLogonName(NULL),
  33. _pszUserDisplayName(NULL)
  34. {
  35. if (hToken == NULL)
  36. {
  37. if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &_hToken) == FALSE)
  38. {
  39. TBOOL(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &_hToken));
  40. }
  41. if (_hToken != NULL)
  42. {
  43. _hTokenToRelease = _hToken;
  44. }
  45. }
  46. }
  47. // --------------------------------------------------------------------------
  48. // CTokenInformation::~CTokenInformation
  49. //
  50. // Arguments: <none>
  51. //
  52. // Returns: <none>
  53. //
  54. // Purpose: Releases resources used by the object.
  55. //
  56. // History: 1999-10-05 vtan created
  57. // --------------------------------------------------------------------------
  58. CTokenInformation::~CTokenInformation (void)
  59. {
  60. ReleaseMemory(_pszUserLogonName);
  61. ReleaseMemory(_pszUserDisplayName);
  62. ReleaseMemory(_pvUserBuffer);
  63. ReleaseMemory(_pvPrivilegeBuffer);
  64. ReleaseMemory(_pvGroupBuffer);
  65. ReleaseHandle(_hTokenToRelease);
  66. }
  67. // --------------------------------------------------------------------------
  68. // CTokenInformation::GetLogonSID
  69. //
  70. // Arguments: <none>
  71. //
  72. // Returns: PSID
  73. //
  74. // Purpose: Gets token information for the token groups. Walks the groups
  75. // looking for the SID with SE_GROUP_LOGON_ID and returns a
  76. // pointer to this SID. This memory is available for the scope
  77. // of the object.
  78. //
  79. // History: 1999-10-05 vtan created
  80. // --------------------------------------------------------------------------
  81. PSID CTokenInformation::GetLogonSID (void)
  82. {
  83. PSID pSID;
  84. pSID = NULL;
  85. if ((_hToken != NULL) && (_pvGroupBuffer == NULL))
  86. {
  87. GetTokenGroups();
  88. }
  89. if (_pvGroupBuffer != NULL)
  90. {
  91. ULONG ulIndex, ulLimit;
  92. TOKEN_GROUPS *pTG;
  93. pTG = reinterpret_cast<TOKEN_GROUPS*>(_pvGroupBuffer);
  94. ulLimit = pTG->GroupCount;
  95. for (ulIndex = 0; (pSID == NULL) && (ulIndex < ulLimit); ++ulIndex)
  96. {
  97. if ((pTG->Groups[ulIndex].Attributes & SE_GROUP_LOGON_ID) != 0)
  98. {
  99. pSID = pTG->Groups[ulIndex].Sid;
  100. }
  101. }
  102. }
  103. return(pSID);
  104. }
  105. // --------------------------------------------------------------------------
  106. // CTokenInformation::GetUserSID
  107. //
  108. // Arguments: <none>
  109. //
  110. // Returns: PSID
  111. //
  112. // Purpose: Gets token information for the token user. This returns the
  113. // SID for the user of the token. This memory is available for
  114. // the scope of the object.
  115. //
  116. // History: 1999-10-05 vtan created
  117. // --------------------------------------------------------------------------
  118. PSID CTokenInformation::GetUserSID (void)
  119. {
  120. PSID pSID;
  121. if ((_pvUserBuffer == NULL) && (_hToken != NULL))
  122. {
  123. DWORD dwReturnLength;
  124. dwReturnLength = 0;
  125. (BOOL)GetTokenInformation(_hToken, TokenUser, NULL, 0, &dwReturnLength);
  126. _pvUserBuffer = LocalAlloc(LMEM_FIXED, dwReturnLength);
  127. if ((_pvUserBuffer != NULL) &&
  128. (GetTokenInformation(_hToken, TokenUser, _pvUserBuffer, dwReturnLength, &dwReturnLength) == FALSE))
  129. {
  130. ReleaseMemory(_pvUserBuffer);
  131. _pvUserBuffer = NULL;
  132. }
  133. }
  134. if (_pvUserBuffer != NULL)
  135. {
  136. pSID = reinterpret_cast<TOKEN_USER*>(_pvUserBuffer)->User.Sid;
  137. }
  138. else
  139. {
  140. pSID = NULL;
  141. }
  142. return(pSID);
  143. }
  144. // --------------------------------------------------------------------------
  145. // CTokenInformation::IsUserTheSystem
  146. //
  147. // Arguments: <none>
  148. //
  149. // Returns: bool
  150. //
  151. // Purpose: Gets token information for the token user. This returns
  152. // whether the user is the local system.
  153. //
  154. // History: 1999-12-13 vtan created
  155. // --------------------------------------------------------------------------
  156. bool CTokenInformation::IsUserTheSystem (void)
  157. {
  158. static const LUID sLUIDSystem = SYSTEM_LUID;
  159. ULONG ulReturnLength;
  160. TOKEN_STATISTICS tokenStatistics;
  161. return((GetTokenInformation(_hToken, TokenStatistics, &tokenStatistics, sizeof(tokenStatistics), &ulReturnLength) != FALSE) &&
  162. RtlEqualLuid(&tokenStatistics.AuthenticationId, &sLUIDSystem));
  163. }
  164. // --------------------------------------------------------------------------
  165. // CTokenInformation::IsUserAnAdministrator
  166. //
  167. // Arguments: <none>
  168. //
  169. // Returns: bool
  170. //
  171. // Purpose: Gets token information for the token user. This returns
  172. // whether the user is a member of the local administrator group.
  173. //
  174. // History: 92-05-06 davidc created
  175. // 1999-11-06 vtan stolen
  176. // --------------------------------------------------------------------------
  177. bool CTokenInformation::IsUserAnAdministrator (void)
  178. {
  179. bool fIsAnAdministrator;
  180. fIsAnAdministrator = false;
  181. if ((_hToken != NULL) && (_pvGroupBuffer == NULL))
  182. {
  183. GetTokenGroups();
  184. }
  185. if (_pvGroupBuffer != NULL)
  186. {
  187. PSID pAdministratorSID;
  188. static SID_IDENTIFIER_AUTHORITY sSystemSidAuthority = SECURITY_NT_AUTHORITY;
  189. if (NT_SUCCESS(RtlAllocateAndInitializeSid(&sSystemSidAuthority,
  190. 2,
  191. SECURITY_BUILTIN_DOMAIN_RID,
  192. DOMAIN_ALIAS_RID_ADMINS,
  193. 0, 0, 0, 0, 0, 0,
  194. &pAdministratorSID)))
  195. {
  196. ULONG ulIndex, ulLimit;
  197. TOKEN_GROUPS *pTG;
  198. pTG = reinterpret_cast<TOKEN_GROUPS*>(_pvGroupBuffer);
  199. ulLimit = pTG->GroupCount;
  200. for (ulIndex = 0; !fIsAnAdministrator && (ulIndex < ulLimit); ++ulIndex)
  201. {
  202. fIsAnAdministrator = ((RtlEqualSid(pTG->Groups[ulIndex].Sid, pAdministratorSID) != FALSE) &&
  203. ((pTG->Groups[ulIndex].Attributes & SE_GROUP_ENABLED) != 0));
  204. }
  205. (void*)RtlFreeSid(pAdministratorSID);
  206. }
  207. }
  208. return(fIsAnAdministrator);
  209. }
  210. // --------------------------------------------------------------------------
  211. // CTokenInformation::UserHasPrivilege
  212. //
  213. // Arguments: <none>
  214. //
  215. // Returns: bool
  216. //
  217. // Purpose: Gets token information for the token user. This returns
  218. // whether the user is a member of the local administrator group.
  219. //
  220. // History: 2000-04-26 vtan created
  221. // --------------------------------------------------------------------------
  222. bool CTokenInformation::UserHasPrivilege (DWORD dwPrivilege)
  223. {
  224. bool fUserHasPrivilege;
  225. fUserHasPrivilege = false;
  226. if ((_hToken != NULL) && (_pvPrivilegeBuffer == NULL))
  227. {
  228. GetTokenPrivileges();
  229. }
  230. if (_pvPrivilegeBuffer != NULL)
  231. {
  232. ULONG ulIndex, ulLimit;
  233. TOKEN_PRIVILEGES *pTP;
  234. LUID luidPrivilege;
  235. luidPrivilege.LowPart = dwPrivilege;
  236. luidPrivilege.HighPart = 0;
  237. pTP = reinterpret_cast<TOKEN_PRIVILEGES*>(_pvPrivilegeBuffer);
  238. ulLimit = pTP->PrivilegeCount;
  239. for (ulIndex = 0; !fUserHasPrivilege && (ulIndex < ulLimit); ++ulIndex)
  240. {
  241. fUserHasPrivilege = (RtlEqualLuid(&pTP->Privileges[ulIndex].Luid, &luidPrivilege) != FALSE);
  242. }
  243. }
  244. return(fUserHasPrivilege);
  245. }
  246. // --------------------------------------------------------------------------
  247. // CTokenInformation::GetUserName
  248. //
  249. // Arguments: <none>
  250. //
  251. // Returns: WCHAR
  252. //
  253. // Purpose: Looks up the account name of the implicit token..
  254. //
  255. // History: 2000-08-31 vtan created
  256. // --------------------------------------------------------------------------
  257. const WCHAR* CTokenInformation::GetUserName (void)
  258. {
  259. if (_pszUserLogonName == NULL)
  260. {
  261. DWORD dwUserNameSize, dwReferencedDomainSize;
  262. SID_NAME_USE eUse;
  263. WCHAR *pszReferencedDomain;
  264. dwUserNameSize = dwReferencedDomainSize = 0;
  265. (BOOL)LookupAccountSid(NULL,
  266. GetUserSID(),
  267. NULL,
  268. &dwUserNameSize,
  269. NULL,
  270. &dwReferencedDomainSize,
  271. &eUse);
  272. pszReferencedDomain = static_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, dwReferencedDomainSize * sizeof(WCHAR)));
  273. if (pszReferencedDomain != NULL)
  274. {
  275. _pszUserLogonName = static_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, dwUserNameSize * sizeof(WCHAR)));
  276. if (_pszUserLogonName != NULL)
  277. {
  278. if (LookupAccountSid(NULL,
  279. GetUserSID(),
  280. _pszUserLogonName,
  281. &dwUserNameSize,
  282. pszReferencedDomain,
  283. &dwReferencedDomainSize,
  284. &eUse) == FALSE)
  285. {
  286. ReleaseMemory(_pszUserLogonName);
  287. }
  288. }
  289. (HLOCAL)LocalFree(pszReferencedDomain);
  290. }
  291. }
  292. return(_pszUserLogonName);
  293. }
  294. // --------------------------------------------------------------------------
  295. // CTokenInformation::GetUserDisplayName
  296. //
  297. // Arguments: <none>
  298. //
  299. // Returns: WCHAR
  300. //
  301. // Purpose: Returns the display name of the implicit token.
  302. //
  303. // History: 2000-08-31 vtan created
  304. // --------------------------------------------------------------------------
  305. const WCHAR* CTokenInformation::GetUserDisplayName (void)
  306. {
  307. if (_pszUserDisplayName == NULL)
  308. {
  309. const WCHAR *pszUserName;
  310. pszUserName = GetUserName();
  311. if (pszUserName != NULL)
  312. {
  313. USER_INFO_2 *pUserInfo;
  314. if (NERR_Success == NetUserGetInfo(NULL, pszUserName, 2, reinterpret_cast<LPBYTE*>(&pUserInfo)))
  315. {
  316. const WCHAR *pszUserDisplayName;
  317. if (pUserInfo->usri2_full_name[0] != L'\0')
  318. {
  319. pszUserDisplayName = pUserInfo->usri2_full_name;
  320. }
  321. else
  322. {
  323. pszUserDisplayName = pszUserName;
  324. }
  325. _pszUserDisplayName = static_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, (lstrlen(pszUserDisplayName) + sizeof('\0')) * sizeof(WCHAR)));
  326. if (_pszUserDisplayName != NULL)
  327. {
  328. lstrcpy(_pszUserDisplayName, pszUserDisplayName);
  329. }
  330. TW32(NetApiBufferFree(pUserInfo));
  331. }
  332. }
  333. }
  334. return(_pszUserDisplayName);
  335. }
  336. // --------------------------------------------------------------------------
  337. // CTokenInformation::LogonUser
  338. //
  339. // Arguments: See the platform SDK under LogonUser.
  340. //
  341. // Returns: DWORD
  342. //
  343. // Purpose: Calls advapi32!LogonUserW with supplied credentials using
  344. // interactive logon type. Returns the error code as a DWORD
  345. // rather than the standard Win32 API method which allows the
  346. // filtering of certain error codes.
  347. //
  348. // History: 2001-03-28 vtan created
  349. // --------------------------------------------------------------------------
  350. DWORD CTokenInformation::LogonUser (const WCHAR *pszUsername, const WCHAR *pszDomain, const WCHAR *pszPassword, HANDLE *phToken)
  351. {
  352. DWORD dwErrorCode;
  353. if (::LogonUserW(const_cast<WCHAR*>(pszUsername),
  354. const_cast<WCHAR*>(pszDomain),
  355. const_cast<WCHAR*>(pszPassword),
  356. LOGON32_LOGON_INTERACTIVE,
  357. LOGON32_PROVIDER_DEFAULT,
  358. phToken) != FALSE)
  359. {
  360. dwErrorCode = ERROR_SUCCESS;
  361. }
  362. else
  363. {
  364. *phToken = NULL;
  365. dwErrorCode = GetLastError();
  366. // Ignore ERROR_PASSWORD_MUST_CHANGE and ERROR_PASSWORD_EXPIRED.
  367. if ((dwErrorCode == ERROR_PASSWORD_MUST_CHANGE) || (dwErrorCode == ERROR_PASSWORD_EXPIRED))
  368. {
  369. dwErrorCode = ERROR_SUCCESS;
  370. }
  371. }
  372. return(dwErrorCode);
  373. }
  374. // --------------------------------------------------------------------------
  375. // CTokenInformation::IsSameUser
  376. //
  377. // Arguments: hToken1 = Token of one user.
  378. // hToken2 = Token of other user.
  379. //
  380. // Returns: bool
  381. //
  382. // Purpose: Compares the user SID of the tokens for a match.
  383. //
  384. // History: 2001-03-28 vtan created
  385. // --------------------------------------------------------------------------
  386. bool CTokenInformation::IsSameUser (HANDLE hToken1, HANDLE hToken2)
  387. {
  388. PSID pSID1;
  389. PSID pSID2;
  390. CTokenInformation tokenInformation1(hToken1);
  391. CTokenInformation tokenInformation2(hToken2);
  392. pSID1 = tokenInformation1.GetUserSID();
  393. pSID2 = tokenInformation2.GetUserSID();
  394. return((pSID1 != NULL) &&
  395. (pSID2 != NULL) &&
  396. (EqualSid(pSID1, pSID2) != FALSE));
  397. }
  398. // --------------------------------------------------------------------------
  399. // CTokenInformation::GetTokenGroups
  400. //
  401. // Arguments: <none>
  402. //
  403. // Returns: <none>
  404. //
  405. // Purpose: Gets token information for the token user. This function
  406. // allocates the memory for the token groups. This memory is
  407. // available for the scope of the object.
  408. //
  409. // History: 1999-11-06 vtan created
  410. // --------------------------------------------------------------------------
  411. void CTokenInformation::GetTokenGroups (void)
  412. {
  413. DWORD dwReturnLength;
  414. dwReturnLength = 0;
  415. (BOOL)GetTokenInformation(_hToken, TokenGroups, NULL, 0, &dwReturnLength);
  416. _pvGroupBuffer = LocalAlloc(LMEM_FIXED, dwReturnLength);
  417. if ((_pvGroupBuffer != NULL) &&
  418. (GetTokenInformation(_hToken, TokenGroups, _pvGroupBuffer, dwReturnLength, &dwReturnLength) == FALSE))
  419. {
  420. ReleaseMemory(_pvGroupBuffer);
  421. _pvGroupBuffer = NULL;
  422. }
  423. }
  424. // --------------------------------------------------------------------------
  425. // CTokenInformation::GetTokenPrivileges
  426. //
  427. // Arguments: <none>
  428. //
  429. // Returns: <none>
  430. //
  431. // Purpose: Gets token privileges for the token user. This function
  432. // allocates the memory for the token privileges. This memory is
  433. // available for the scope of the object.
  434. //
  435. // History: 2000-04-26 vtan created
  436. // --------------------------------------------------------------------------
  437. void CTokenInformation::GetTokenPrivileges (void)
  438. {
  439. DWORD dwReturnLength;
  440. dwReturnLength = 0;
  441. (BOOL)GetTokenInformation(_hToken, TokenPrivileges, NULL, 0, &dwReturnLength);
  442. _pvPrivilegeBuffer = LocalAlloc(LMEM_FIXED, dwReturnLength);
  443. if ((_pvPrivilegeBuffer != NULL) &&
  444. (GetTokenInformation(_hToken, TokenPrivileges, _pvPrivilegeBuffer, dwReturnLength, &dwReturnLength) == FALSE))
  445. {
  446. ReleaseMemory(_pvPrivilegeBuffer);
  447. _pvPrivilegeBuffer = NULL;
  448. }
  449. }