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.

407 lines
11 KiB

  1. #include "shellprv.h"
  2. #include "TokenUtil.h"
  3. #pragma hdrstop
  4. // Gets the current process's user token and returns
  5. // it. It can later be free'd with LocalFree.
  6. //
  7. // NOTE: This code is duped in shlwapi\shellacl.c. If you change it, modify
  8. // it there as well.
  9. STDAPI_(PTOKEN_USER) GetUserToken(HANDLE hUser)
  10. {
  11. DWORD dwSize = 64;
  12. HANDLE hToClose = NULL;
  13. if (hUser == NULL)
  14. {
  15. OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hUser);
  16. hToClose = hUser;
  17. }
  18. PTOKEN_USER pUser = (PTOKEN_USER)LocalAlloc(LPTR, dwSize);
  19. if (pUser)
  20. {
  21. DWORD dwNewSize;
  22. BOOL fOk = GetTokenInformation(hUser, TokenUser, pUser, dwSize, &dwNewSize);
  23. if (!fOk && (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
  24. {
  25. LocalFree((HLOCAL)pUser);
  26. pUser = (PTOKEN_USER)LocalAlloc(LPTR, dwNewSize);
  27. if (pUser)
  28. {
  29. fOk = GetTokenInformation(hUser, TokenUser, pUser, dwNewSize, &dwNewSize);
  30. }
  31. }
  32. if (!fOk)
  33. {
  34. LocalFree((HLOCAL)pUser);
  35. pUser = NULL;
  36. }
  37. }
  38. if (hToClose)
  39. {
  40. CloseHandle(hToClose);
  41. }
  42. return pUser;
  43. }
  44. // Returns a localalloc'd string containing the text version of the current user's SID.
  45. STDAPI_(LPTSTR) GetUserSid(HANDLE hToken)
  46. {
  47. LPTSTR pString = NULL;
  48. PTOKEN_USER pUser = GetUserToken(hToken);
  49. if (pUser)
  50. {
  51. UNICODE_STRING UnicodeString;
  52. if (STATUS_SUCCESS == RtlConvertSidToUnicodeString(&UnicodeString, pUser->User.Sid, TRUE))
  53. {
  54. UINT nChars = (UnicodeString.Length / 2) + 1;
  55. pString = (LPTSTR)LocalAlloc(LPTR, nChars * sizeof(TCHAR));
  56. if (pString)
  57. {
  58. SHUnicodeToTChar(UnicodeString.Buffer, pString, nChars);
  59. }
  60. RtlFreeUnicodeString(&UnicodeString);
  61. }
  62. LocalFree((HLOCAL)pUser);
  63. }
  64. return pString;
  65. }
  66. /*++
  67. sets the security attributes for a given privilege.
  68. Arguments:
  69. PrivilegeName - Name of the privilege we are manipulating.
  70. NewPrivilegeAttribute - The new attribute value to use.
  71. OldPrivilegeAttribute - Pointer to receive the old privilege value. OPTIONAL
  72. Return value:
  73. NO_ERROR or WIN32 error.
  74. --*/
  75. DWORD SetPrivilegeAttribute(LPCTSTR PrivilegeName, DWORD NewPrivilegeAttribute, DWORD *OldPrivilegeAttribute)
  76. {
  77. LUID PrivilegeValue;
  78. TOKEN_PRIVILEGES TokenPrivileges, OldTokenPrivileges;
  79. DWORD ReturnLength;
  80. HANDLE TokenHandle;
  81. //
  82. // First, find out the LUID Value of the privilege
  83. //
  84. if (!LookupPrivilegeValue(NULL, PrivilegeName, &PrivilegeValue))
  85. {
  86. return GetLastError();
  87. }
  88. //
  89. // Get the token handle
  90. //
  91. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle))
  92. {
  93. return GetLastError();
  94. }
  95. //
  96. // Set up the privilege set we will need
  97. //
  98. TokenPrivileges.PrivilegeCount = 1;
  99. TokenPrivileges.Privileges[0].Luid = PrivilegeValue;
  100. TokenPrivileges.Privileges[0].Attributes = NewPrivilegeAttribute;
  101. ReturnLength = sizeof( TOKEN_PRIVILEGES );
  102. if (!AdjustTokenPrivileges (
  103. TokenHandle,
  104. FALSE,
  105. &TokenPrivileges,
  106. sizeof( TOKEN_PRIVILEGES ),
  107. &OldTokenPrivileges,
  108. &ReturnLength
  109. ))
  110. {
  111. CloseHandle(TokenHandle);
  112. return GetLastError();
  113. }
  114. else
  115. {
  116. if (OldPrivilegeAttribute != NULL)
  117. {
  118. *OldPrivilegeAttribute = OldTokenPrivileges.Privileges[0].Attributes;
  119. }
  120. CloseHandle(TokenHandle);
  121. return NO_ERROR;
  122. }
  123. }
  124. //
  125. // Purpose: Determines if the user is a member of the administrators group.
  126. //
  127. // Parameters: void
  128. //
  129. // Return: TRUE if user is a admin
  130. // FALSE if not
  131. // Comments:
  132. //
  133. // History: Date Author Comment
  134. // 4/12/95 ericflo Created
  135. // 11/4/99 jeffreys Use CheckTokenMembership
  136. //
  137. STDAPI_(BOOL) IsUserAnAdmin()
  138. {
  139. return SHTestTokenMembership(NULL, DOMAIN_ALIAS_RID_ADMINS);
  140. }
  141. // is user a guest but not a full user?
  142. STDAPI_(BOOL) IsUserAGuest()
  143. {
  144. return SHTestTokenMembership(NULL, DOMAIN_ALIAS_RID_GUESTS);
  145. }
  146. STDAPI_(BOOL) GetUserProfileKey(HANDLE hToken, HKEY *phkey)
  147. {
  148. LPTSTR pUserSid = GetUserSid(hToken);
  149. if (pUserSid)
  150. {
  151. LONG err = RegOpenKeyEx(HKEY_USERS, pUserSid, 0, KEY_READ | KEY_WRITE, phkey);
  152. if (err == ERROR_ACCESS_DENIED)
  153. err = RegOpenKeyEx(HKEY_USERS, pUserSid, 0, KEY_READ, phkey);
  154. LocalFree(pUserSid);
  155. return err == ERROR_SUCCESS;
  156. }
  157. return FALSE;
  158. }
  159. //
  160. // Arguments: phToken = Handle to token.
  161. //
  162. // Returns: BOOL
  163. //
  164. // Purpose: Opens the thread token. If no thread impersonation token is
  165. // present open the process token.
  166. //
  167. // History: 2000-02-28 vtan created
  168. STDAPI_(BOOL) SHOpenEffectiveToken(HANDLE *phToken)
  169. {
  170. return OpenEffectiveToken(TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, phToken);
  171. }
  172. //
  173. // Arguments: hToken = Handle to token (may be NULL).
  174. // pszPrivilegeName = Name of privilege to check for.
  175. //
  176. // Returns: BOOL
  177. //
  178. // Purpose: Uses the given token or if no token is specified the effective
  179. // token and looks through the list of privileges contained in
  180. // token for a match against the given privilege being checked.
  181. //
  182. // History: 2000-02-28 vtan created
  183. STDAPI_(BOOL) SHTestTokenPrivilege(HANDLE hToken, LPCTSTR pszPrivilegeName)
  184. {
  185. // Validate privilege name.
  186. if (pszPrivilegeName == NULL)
  187. {
  188. return FALSE;
  189. }
  190. BOOL fResult = FALSE;
  191. HANDLE hTokenToFree = NULL;
  192. if (hToken == NULL)
  193. {
  194. if (SHOpenEffectiveToken(&hTokenToFree) != FALSE)
  195. {
  196. hToken = hTokenToFree;
  197. }
  198. }
  199. if (hToken != NULL)
  200. {
  201. LUID luidPrivilege;
  202. if (LookupPrivilegeValue(NULL, pszPrivilegeName, &luidPrivilege) != FALSE)
  203. {
  204. DWORD dwTokenPrivilegesSize = 0;
  205. GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwTokenPrivilegesSize);
  206. TOKEN_PRIVILEGES *pTokenPrivileges = static_cast<TOKEN_PRIVILEGES*>(LocalAlloc(LMEM_FIXED, dwTokenPrivilegesSize));
  207. if (pTokenPrivileges != NULL)
  208. {
  209. DWORD dwReturnLength;
  210. if (GetTokenInformation(hToken, TokenPrivileges, pTokenPrivileges, dwTokenPrivilegesSize, &dwReturnLength) != FALSE)
  211. {
  212. DWORD dwIndex;
  213. for (dwIndex = 0; !fResult && (dwIndex < pTokenPrivileges->PrivilegeCount); ++dwIndex)
  214. {
  215. fResult = (RtlEqualLuid(&luidPrivilege, &pTokenPrivileges->Privileges[dwIndex].Luid));
  216. }
  217. }
  218. (HLOCAL)LocalFree(pTokenPrivileges);
  219. }
  220. }
  221. }
  222. if (hTokenToFree != NULL)
  223. {
  224. TBOOL(CloseHandle(hTokenToFree));
  225. }
  226. return fResult;
  227. }
  228. //
  229. // Arguments: hToken = Handle to token (may be NULL).
  230. // ulRID = RID of local group to test membership of.
  231. //
  232. // Returns: BOOL
  233. //
  234. // Purpose: Uses advapi32!CheckTokenMembership to test whether the given
  235. // token is a member of the local group with the specified RID.
  236. // This function wraps CheckTokenMember and only checks local
  237. // groups.
  238. //
  239. // History: 2000-03-22 vtan created
  240. STDAPI_(BOOL) SHTestTokenMembership(HANDLE hToken, ULONG ulRID)
  241. {
  242. static SID_IDENTIFIER_AUTHORITY sSystemSidAuthority = SECURITY_NT_AUTHORITY;
  243. PSID pSIDLocalGroup;
  244. BOOL fResult = FALSE;
  245. if (AllocateAndInitializeSid(&sSystemSidAuthority,
  246. 2,
  247. SECURITY_BUILTIN_DOMAIN_RID,
  248. ulRID,
  249. 0, 0, 0, 0, 0, 0,
  250. &pSIDLocalGroup) != FALSE)
  251. {
  252. if (CheckTokenMembership(hToken, pSIDLocalGroup, &fResult) == FALSE)
  253. {
  254. TraceMsg(TF_WARNING, "shell32: SHTestTokenMembership call to advapi32!CheckTokenMembership failed with error %d", GetLastError());
  255. fResult = FALSE;
  256. }
  257. FreeSid(pSIDLocalGroup);
  258. }
  259. return fResult;
  260. }
  261. //
  262. // Arguments: pszPrivilegeName = Name of privilege to be enabled.
  263. // pfnPrivilegedFunction = Pointer to function to invoke.
  264. // pv = Caller supplied data.
  265. //
  266. // Returns: HRESULT
  267. //
  268. // Purpose: Enables the given privilege in the current thread's
  269. // impersonation or primary process' token, invokes the given
  270. // function pointer with the caller supplied data and then
  271. // restores the privilege back to its previous state.
  272. //
  273. // History: 2000-03-13 vtan created
  274. STDAPI SHInvokePrivilegedFunction(LPCTSTR pszPrivilegeName, PFNPRIVILEGEDFUNCTION pfnPrivilegedFunction, void *pv)
  275. {
  276. if ((pszPrivilegeName == NULL) || (pfnPrivilegedFunction == NULL))
  277. {
  278. return E_INVALIDARG;
  279. }
  280. CPrivilegeEnable privilege(pszPrivilegeName);
  281. return pfnPrivilegedFunction(pv);
  282. }
  283. //
  284. // Arguments: <none>
  285. //
  286. // Returns: DWORD
  287. //
  288. // Purpose: Returns the ID of the active console session.
  289. //
  290. // History: 2000-03-13 vtan created
  291. STDAPI_(DWORD) SHGetActiveConsoleSessionId (void)
  292. {
  293. return static_cast<DWORD>(USER_SHARED_DATA->ActiveConsoleId);
  294. }
  295. //
  296. // Arguments: hToken = Handle to the user token.
  297. //
  298. // Returns: DWORD
  299. //
  300. // Purpose: Returns the session ID associated with the given token. If no
  301. // token is specified the effective token is used. This will
  302. // allow a service to call this function when impersonating a
  303. // client.
  304. //
  305. // The token must have TOKEN_QUERY access.
  306. //
  307. // History: 2000-03-13 vtan created
  308. STDAPI_(DWORD) SHGetUserSessionId(HANDLE hToken)
  309. {
  310. ULONG ulUserSessionID = 0; // default to session 0
  311. HANDLE hTokenToFree = NULL;
  312. if (hToken == NULL)
  313. {
  314. TBOOL(SHOpenEffectiveToken(&hTokenToFree));
  315. hToken = hTokenToFree;
  316. }
  317. if (hToken != NULL)
  318. {
  319. DWORD dwReturnLength;
  320. TBOOL(GetTokenInformation(hToken,
  321. TokenSessionId,
  322. &ulUserSessionID,
  323. sizeof(ulUserSessionID),
  324. &dwReturnLength));
  325. }
  326. if (hTokenToFree != NULL)
  327. {
  328. TBOOL(CloseHandle(hTokenToFree));
  329. }
  330. return ulUserSessionID;
  331. }
  332. //
  333. // Arguments: <none>
  334. //
  335. // Returns: BOOL
  336. //
  337. // Purpose: Returns whether the current process is the console session.
  338. //
  339. // History: 2000-03-27 vtan created
  340. STDAPI_(BOOL) SHIsCurrentProcessConsoleSession(void)
  341. {
  342. return USER_SHARED_DATA->ActiveConsoleId == NtCurrentPeb()->SessionId;
  343. }