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.

405 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, REGSAM samDesired, HKEY *phkey)
  147. {
  148. LPTSTR pUserSid = GetUserSid(hToken);
  149. if (pUserSid)
  150. {
  151. LONG err = RegOpenKeyEx(HKEY_USERS, pUserSid, 0, samDesired, phkey);
  152. LocalFree(pUserSid);
  153. return err == ERROR_SUCCESS;
  154. }
  155. return FALSE;
  156. }
  157. //
  158. // Arguments: phToken = Handle to token.
  159. //
  160. // Returns: BOOL
  161. //
  162. // Purpose: Opens the thread token. If no thread impersonation token is
  163. // present open the process token.
  164. //
  165. // History: 2000-02-28 vtan created
  166. STDAPI_(BOOL) SHOpenEffectiveToken(HANDLE *phToken)
  167. {
  168. return OpenEffectiveToken(TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, phToken);
  169. }
  170. //
  171. // Arguments: hToken = Handle to token (may be NULL).
  172. // pszPrivilegeName = Name of privilege to check for.
  173. //
  174. // Returns: BOOL
  175. //
  176. // Purpose: Uses the given token or if no token is specified the effective
  177. // token and looks through the list of privileges contained in
  178. // token for a match against the given privilege being checked.
  179. //
  180. // History: 2000-02-28 vtan created
  181. STDAPI_(BOOL) SHTestTokenPrivilege(HANDLE hToken, LPCTSTR pszPrivilegeName)
  182. {
  183. // Validate privilege name.
  184. if (pszPrivilegeName == NULL)
  185. {
  186. return FALSE;
  187. }
  188. BOOL fResult = FALSE;
  189. HANDLE hTokenToFree = NULL;
  190. if (hToken == NULL)
  191. {
  192. if (SHOpenEffectiveToken(&hTokenToFree) != FALSE)
  193. {
  194. hToken = hTokenToFree;
  195. }
  196. }
  197. if (hToken != NULL)
  198. {
  199. LUID luidPrivilege;
  200. if (LookupPrivilegeValue(NULL, pszPrivilegeName, &luidPrivilege) != FALSE)
  201. {
  202. DWORD dwTokenPrivilegesSize = 0;
  203. GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwTokenPrivilegesSize);
  204. TOKEN_PRIVILEGES *pTokenPrivileges = static_cast<TOKEN_PRIVILEGES*>(LocalAlloc(LMEM_FIXED, dwTokenPrivilegesSize));
  205. if (pTokenPrivileges != NULL)
  206. {
  207. DWORD dwReturnLength;
  208. if (GetTokenInformation(hToken, TokenPrivileges, pTokenPrivileges, dwTokenPrivilegesSize, &dwReturnLength) != FALSE)
  209. {
  210. DWORD dwIndex;
  211. for (dwIndex = 0; !fResult && (dwIndex < pTokenPrivileges->PrivilegeCount); ++dwIndex)
  212. {
  213. fResult = (RtlEqualLuid(&luidPrivilege, &pTokenPrivileges->Privileges[dwIndex].Luid));
  214. }
  215. }
  216. (HLOCAL)LocalFree(pTokenPrivileges);
  217. }
  218. }
  219. }
  220. if (hTokenToFree != NULL)
  221. {
  222. TBOOL(CloseHandle(hTokenToFree));
  223. }
  224. return fResult;
  225. }
  226. //
  227. // Arguments: hToken = Handle to token (may be NULL).
  228. // ulRID = RID of local group to test membership of.
  229. //
  230. // Returns: BOOL
  231. //
  232. // Purpose: Uses advapi32!CheckTokenMembership to test whether the given
  233. // token is a member of the local group with the specified RID.
  234. // This function wraps CheckTokenMember and only checks local
  235. // groups.
  236. //
  237. // History: 2000-03-22 vtan created
  238. STDAPI_(BOOL) SHTestTokenMembership(HANDLE hToken, ULONG ulRID)
  239. {
  240. static SID_IDENTIFIER_AUTHORITY sSystemSidAuthority = SECURITY_NT_AUTHORITY;
  241. PSID pSIDLocalGroup;
  242. BOOL fResult = FALSE;
  243. if (AllocateAndInitializeSid(&sSystemSidAuthority,
  244. 2,
  245. SECURITY_BUILTIN_DOMAIN_RID,
  246. ulRID,
  247. 0, 0, 0, 0, 0, 0,
  248. &pSIDLocalGroup) != FALSE)
  249. {
  250. if (CheckTokenMembership(hToken, pSIDLocalGroup, &fResult) == FALSE)
  251. {
  252. TraceMsg(TF_WARNING, "shell32: SHTestTokenMembership call to advapi32!CheckTokenMembership failed with error %d", GetLastError());
  253. fResult = FALSE;
  254. }
  255. FreeSid(pSIDLocalGroup);
  256. }
  257. return fResult;
  258. }
  259. //
  260. // Arguments: pszPrivilegeName = Name of privilege to be enabled.
  261. // pfnPrivilegedFunction = Pointer to function to invoke.
  262. // pv = Caller supplied data.
  263. //
  264. // Returns: HRESULT
  265. //
  266. // Purpose: Enables the given privilege in the current thread's
  267. // impersonation or primary process' token, invokes the given
  268. // function pointer with the caller supplied data and then
  269. // restores the privilege back to its previous state.
  270. //
  271. // History: 2000-03-13 vtan created
  272. STDAPI SHInvokePrivilegedFunction(LPCTSTR pszPrivilegeName, PFNPRIVILEGEDFUNCTION pfnPrivilegedFunction, void *pv)
  273. {
  274. if ((pszPrivilegeName == NULL) || (pfnPrivilegedFunction == NULL))
  275. {
  276. return E_INVALIDARG;
  277. }
  278. CPrivilegeEnable privilege(pszPrivilegeName);
  279. return pfnPrivilegedFunction(pv);
  280. }
  281. //
  282. // Arguments: <none>
  283. //
  284. // Returns: DWORD
  285. //
  286. // Purpose: Returns the ID of the active console session.
  287. //
  288. // History: 2000-03-13 vtan created
  289. STDAPI_(DWORD) SHGetActiveConsoleSessionId (void)
  290. {
  291. return static_cast<DWORD>(USER_SHARED_DATA->ActiveConsoleId);
  292. }
  293. //
  294. // Arguments: hToken = Handle to the user token.
  295. //
  296. // Returns: DWORD
  297. //
  298. // Purpose: Returns the session ID associated with the given token. If no
  299. // token is specified the effective token is used. This will
  300. // allow a service to call this function when impersonating a
  301. // client.
  302. //
  303. // The token must have TOKEN_QUERY access.
  304. //
  305. // History: 2000-03-13 vtan created
  306. STDAPI_(DWORD) SHGetUserSessionId(HANDLE hToken)
  307. {
  308. ULONG ulUserSessionID = 0; // default to session 0
  309. HANDLE hTokenToFree = NULL;
  310. if (hToken == NULL)
  311. {
  312. TBOOL(SHOpenEffectiveToken(&hTokenToFree));
  313. hToken = hTokenToFree;
  314. }
  315. if (hToken != NULL)
  316. {
  317. DWORD dwReturnLength;
  318. TBOOL(GetTokenInformation(hToken,
  319. TokenSessionId,
  320. &ulUserSessionID,
  321. sizeof(ulUserSessionID),
  322. &dwReturnLength));
  323. }
  324. if (hTokenToFree != NULL)
  325. {
  326. TBOOL(CloseHandle(hTokenToFree));
  327. }
  328. return ulUserSessionID;
  329. }
  330. //
  331. // Arguments: <none>
  332. //
  333. // Returns: BOOL
  334. //
  335. // Purpose: Returns whether the current process is the console session.
  336. //
  337. // History: 2000-03-27 vtan created
  338. STDAPI_(BOOL) SHIsCurrentProcessConsoleSession(void)
  339. {
  340. return USER_SHARED_DATA->ActiveConsoleId == NtCurrentPeb()->SessionId;
  341. }