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.

500 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. PSID pAdministratorSID;
  181. static SID_IDENTIFIER_AUTHORITY sSystemSidAuthority = SECURITY_NT_AUTHORITY;
  182. fIsAnAdministrator = false;
  183. if (NT_SUCCESS(RtlAllocateAndInitializeSid(&sSystemSidAuthority,
  184. 2,
  185. SECURITY_BUILTIN_DOMAIN_RID,
  186. DOMAIN_ALIAS_RID_ADMINS,
  187. 0, 0, 0, 0, 0, 0,
  188. &pAdministratorSID)))
  189. {
  190. BOOL fAdmin = FALSE;
  191. if (CheckTokenMembership(_hToken, pAdministratorSID, &fAdmin))
  192. {
  193. fIsAnAdministrator = !!fAdmin;
  194. }
  195. (void*)RtlFreeSid(pAdministratorSID);
  196. }
  197. return(fIsAnAdministrator);
  198. }
  199. // --------------------------------------------------------------------------
  200. // CTokenInformation::UserHasPrivilege
  201. //
  202. // Arguments: <none>
  203. //
  204. // Returns: bool
  205. //
  206. // Purpose: Gets token information for the token user. This returns
  207. // whether the user is a member of the local administrator group.
  208. //
  209. // History: 2000-04-26 vtan created
  210. // --------------------------------------------------------------------------
  211. bool CTokenInformation::UserHasPrivilege (DWORD dwPrivilege)
  212. {
  213. bool fUserHasPrivilege;
  214. fUserHasPrivilege = false;
  215. if ((_hToken != NULL) && (_pvPrivilegeBuffer == NULL))
  216. {
  217. GetTokenPrivileges();
  218. }
  219. if (_pvPrivilegeBuffer != NULL)
  220. {
  221. ULONG ulIndex, ulLimit;
  222. TOKEN_PRIVILEGES *pTP;
  223. LUID luidPrivilege;
  224. luidPrivilege.LowPart = dwPrivilege;
  225. luidPrivilege.HighPart = 0;
  226. pTP = reinterpret_cast<TOKEN_PRIVILEGES*>(_pvPrivilegeBuffer);
  227. ulLimit = pTP->PrivilegeCount;
  228. for (ulIndex = 0; !fUserHasPrivilege && (ulIndex < ulLimit); ++ulIndex)
  229. {
  230. fUserHasPrivilege = (RtlEqualLuid(&pTP->Privileges[ulIndex].Luid, &luidPrivilege) != FALSE);
  231. }
  232. }
  233. return(fUserHasPrivilege);
  234. }
  235. // --------------------------------------------------------------------------
  236. // CTokenInformation::GetUserName
  237. //
  238. // Arguments: <none>
  239. //
  240. // Returns: WCHAR
  241. //
  242. // Purpose: Looks up the account name of the implicit token..
  243. //
  244. // History: 2000-08-31 vtan created
  245. // --------------------------------------------------------------------------
  246. const WCHAR* CTokenInformation::GetUserName (void)
  247. {
  248. if (_pszUserLogonName == NULL)
  249. {
  250. DWORD dwUserNameSize, dwReferencedDomainSize;
  251. SID_NAME_USE eUse;
  252. WCHAR *pszReferencedDomain;
  253. dwUserNameSize = dwReferencedDomainSize = 0;
  254. (BOOL)LookupAccountSid(NULL,
  255. GetUserSID(),
  256. NULL,
  257. &dwUserNameSize,
  258. NULL,
  259. &dwReferencedDomainSize,
  260. &eUse);
  261. pszReferencedDomain = static_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, dwReferencedDomainSize * sizeof(WCHAR)));
  262. if (pszReferencedDomain != NULL)
  263. {
  264. _pszUserLogonName = static_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, dwUserNameSize * sizeof(WCHAR)));
  265. if (_pszUserLogonName != NULL)
  266. {
  267. if (LookupAccountSid(NULL,
  268. GetUserSID(),
  269. _pszUserLogonName,
  270. &dwUserNameSize,
  271. pszReferencedDomain,
  272. &dwReferencedDomainSize,
  273. &eUse) == FALSE)
  274. {
  275. ReleaseMemory(_pszUserLogonName);
  276. }
  277. }
  278. (HLOCAL)LocalFree(pszReferencedDomain);
  279. }
  280. }
  281. return(_pszUserLogonName);
  282. }
  283. // --------------------------------------------------------------------------
  284. // CTokenInformation::GetUserDisplayName
  285. //
  286. // Arguments: <none>
  287. //
  288. // Returns: WCHAR
  289. //
  290. // Purpose: Returns the display name of the implicit token.
  291. //
  292. // History: 2000-08-31 vtan created
  293. // --------------------------------------------------------------------------
  294. const WCHAR* CTokenInformation::GetUserDisplayName (void)
  295. {
  296. if (_pszUserDisplayName == NULL)
  297. {
  298. const WCHAR *pszUserName;
  299. pszUserName = GetUserName();
  300. if (pszUserName != NULL)
  301. {
  302. USER_INFO_2 *pUserInfo;
  303. if (NERR_Success == NetUserGetInfo(NULL, pszUserName, 2, reinterpret_cast<LPBYTE*>(&pUserInfo)))
  304. {
  305. const WCHAR *pszUserDisplayName;
  306. if (pUserInfo->usri2_full_name[0] != L'\0')
  307. {
  308. pszUserDisplayName = pUserInfo->usri2_full_name;
  309. }
  310. else
  311. {
  312. pszUserDisplayName = pszUserName;
  313. }
  314. _pszUserDisplayName = static_cast<WCHAR*>(LocalAlloc(LMEM_FIXED, (lstrlen(pszUserDisplayName) + sizeof('\0')) * sizeof(WCHAR)));
  315. if (_pszUserDisplayName != NULL)
  316. {
  317. lstrcpy(_pszUserDisplayName, pszUserDisplayName);
  318. }
  319. TW32(NetApiBufferFree(pUserInfo));
  320. }
  321. }
  322. }
  323. return(_pszUserDisplayName);
  324. }
  325. // --------------------------------------------------------------------------
  326. // CTokenInformation::LogonUser
  327. //
  328. // Arguments: See the platform SDK under LogonUser.
  329. //
  330. // Returns: DWORD
  331. //
  332. // Purpose: Calls advapi32!LogonUserW with supplied credentials using
  333. // interactive logon type. Returns the error code as a DWORD
  334. // rather than the standard Win32 API method which allows the
  335. // filtering of certain error codes.
  336. //
  337. // History: 2001-03-28 vtan created
  338. // --------------------------------------------------------------------------
  339. DWORD CTokenInformation::LogonUser (const WCHAR *pszUsername, const WCHAR *pszDomain, const WCHAR *pszPassword, HANDLE *phToken)
  340. {
  341. DWORD dwErrorCode;
  342. if (::LogonUserW(const_cast<WCHAR*>(pszUsername),
  343. const_cast<WCHAR*>(pszDomain),
  344. const_cast<WCHAR*>(pszPassword),
  345. LOGON32_LOGON_INTERACTIVE,
  346. LOGON32_PROVIDER_DEFAULT,
  347. phToken) != FALSE)
  348. {
  349. dwErrorCode = ERROR_SUCCESS;
  350. }
  351. else
  352. {
  353. *phToken = NULL;
  354. dwErrorCode = GetLastError();
  355. // Ignore ERROR_PASSWORD_MUST_CHANGE and ERROR_PASSWORD_EXPIRED.
  356. if ((dwErrorCode == ERROR_PASSWORD_MUST_CHANGE) || (dwErrorCode == ERROR_PASSWORD_EXPIRED))
  357. {
  358. dwErrorCode = ERROR_SUCCESS;
  359. }
  360. }
  361. return(dwErrorCode);
  362. }
  363. // --------------------------------------------------------------------------
  364. // CTokenInformation::IsSameUser
  365. //
  366. // Arguments: hToken1 = Token of one user.
  367. // hToken2 = Token of other user.
  368. //
  369. // Returns: bool
  370. //
  371. // Purpose: Compares the user SID of the tokens for a match.
  372. //
  373. // History: 2001-03-28 vtan created
  374. // --------------------------------------------------------------------------
  375. bool CTokenInformation::IsSameUser (HANDLE hToken1, HANDLE hToken2)
  376. {
  377. PSID pSID1;
  378. PSID pSID2;
  379. CTokenInformation tokenInformation1(hToken1);
  380. CTokenInformation tokenInformation2(hToken2);
  381. pSID1 = tokenInformation1.GetUserSID();
  382. pSID2 = tokenInformation2.GetUserSID();
  383. return((pSID1 != NULL) &&
  384. (pSID2 != NULL) &&
  385. (EqualSid(pSID1, pSID2) != FALSE));
  386. }
  387. // --------------------------------------------------------------------------
  388. // CTokenInformation::GetTokenGroups
  389. //
  390. // Arguments: <none>
  391. //
  392. // Returns: <none>
  393. //
  394. // Purpose: Gets token information for the token user. This function
  395. // allocates the memory for the token groups. This memory is
  396. // available for the scope of the object.
  397. //
  398. // History: 1999-11-06 vtan created
  399. // --------------------------------------------------------------------------
  400. void CTokenInformation::GetTokenGroups (void)
  401. {
  402. DWORD dwReturnLength;
  403. dwReturnLength = 0;
  404. (BOOL)GetTokenInformation(_hToken, TokenGroups, NULL, 0, &dwReturnLength);
  405. _pvGroupBuffer = LocalAlloc(LMEM_FIXED, dwReturnLength);
  406. if ((_pvGroupBuffer != NULL) &&
  407. (GetTokenInformation(_hToken, TokenGroups, _pvGroupBuffer, dwReturnLength, &dwReturnLength) == FALSE))
  408. {
  409. ReleaseMemory(_pvGroupBuffer);
  410. _pvGroupBuffer = NULL;
  411. }
  412. }
  413. // --------------------------------------------------------------------------
  414. // CTokenInformation::GetTokenPrivileges
  415. //
  416. // Arguments: <none>
  417. //
  418. // Returns: <none>
  419. //
  420. // Purpose: Gets token privileges for the token user. This function
  421. // allocates the memory for the token privileges. This memory is
  422. // available for the scope of the object.
  423. //
  424. // History: 2000-04-26 vtan created
  425. // --------------------------------------------------------------------------
  426. void CTokenInformation::GetTokenPrivileges (void)
  427. {
  428. DWORD dwReturnLength;
  429. dwReturnLength = 0;
  430. (BOOL)GetTokenInformation(_hToken, TokenPrivileges, NULL, 0, &dwReturnLength);
  431. _pvPrivilegeBuffer = LocalAlloc(LMEM_FIXED, dwReturnLength);
  432. if ((_pvPrivilegeBuffer != NULL) &&
  433. (GetTokenInformation(_hToken, TokenPrivileges, _pvPrivilegeBuffer, dwReturnLength, &dwReturnLength) == FALSE))
  434. {
  435. ReleaseMemory(_pvPrivilegeBuffer);
  436. _pvPrivilegeBuffer = NULL;
  437. }
  438. }