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.

1157 lines
26 KiB

  1. /*++
  2. Copyright(c) 1995 Microsoft Corporation
  3. MODULE NAME
  4. impersn.c
  5. ABSTRACT
  6. Impersonation routines for the automatic connection service.
  7. AUTHOR
  8. Anthony Discolo (adiscolo) 04-Aug-1995
  9. REVISION HISTORY
  10. --*/
  11. #define UNICODE
  12. #define _UNICODE
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <stdlib.h>
  17. #include <windows.h>
  18. #include <stdio.h>
  19. #include <npapi.h>
  20. #include <acd.h>
  21. #include <debug.h>
  22. #include "reg.h"
  23. #include "misc.h"
  24. #include "process.h"
  25. #include "imperson.h"
  26. #include "mprlog.h"
  27. #include "rtutils.h"
  28. extern HANDLE g_hLogEvent;
  29. DWORD
  30. LoadGroupMemberships();
  31. //
  32. // The static information we
  33. // need to impersonate the currently
  34. // logged-in user.
  35. //
  36. IMPERSONATION_INFO ImpersonationInfoG;
  37. //
  38. // TRUE if ImpersonationInfoG has been initialized
  39. //
  40. BOOLEAN ImpersonationInfoInitializedG = FALSE;
  41. //
  42. // Security attributes and descriptor
  43. // necessary for creating shareable handles.
  44. //
  45. SECURITY_ATTRIBUTES SecurityAttributeG;
  46. SECURITY_DESCRIPTOR SecurityDescriptorG;
  47. HKEY hkeyCUG = NULL;
  48. #ifdef notdef
  49. BOOLEAN
  50. InteractiveSession()
  51. /*++
  52. DESCRIPTION
  53. Determine whether the active process is owned by the
  54. currently logged-in user.
  55. ARGUMENTS
  56. None.
  57. RETURNS
  58. TRUE if it is, FALSE if it isn't.
  59. --*/
  60. {
  61. HANDLE hToken;
  62. BOOLEAN bStatus;
  63. ULONG ulInfoLength;
  64. PTOKEN_GROUPS pTokenGroupList;
  65. PTOKEN_USER pTokenUser;
  66. ULONG ulGroupIndex;
  67. BOOLEAN bFoundInteractive = FALSE;
  68. PSID InteractiveSid;
  69. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  70. static BOOLEAN fIsInteractiveSession = 0xffff;
  71. #if 0
  72. //
  73. // Return the previous value of this function
  74. // if we're called multiple times?! Doesn't
  75. // GetCurrentProcess() return different values?
  76. //
  77. if (fIsInteractiveSession != 0xffff) {
  78. return fIsInteractiveSession;
  79. }
  80. #endif
  81. bStatus = AllocateAndInitializeSid(
  82. &NtAuthority,
  83. 1,
  84. SECURITY_INTERACTIVE_RID,
  85. 0, 0, 0, 0, 0, 0, 0,
  86. &InteractiveSid);
  87. if (!bStatus) {
  88. RASAUTO_TRACE("InteractiveSession: AllocateAndInitializeSid failed");
  89. return (fIsInteractiveSession = FALSE);
  90. }
  91. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
  92. RASAUTO_TRACE("InteractiveSession: OpenProcessToken failed");
  93. FreeSid(InteractiveSid);
  94. return (fIsInteractiveSession = FALSE);
  95. }
  96. //
  97. // Get a list of groups in the token.
  98. //
  99. GetTokenInformation(
  100. hToken,
  101. TokenGroups,
  102. NULL,
  103. 0,
  104. &ulInfoLength);
  105. pTokenGroupList = (PTOKEN_GROUPS)LocalAlloc(LPTR, ulInfoLength);
  106. if (pTokenGroupList == NULL) {
  107. RASAUTO_TRACE("InteractiveSession: LocalAlloc failed");
  108. FreeSid(InteractiveSid);
  109. return (fIsInteractiveSession = FALSE);
  110. }
  111. bStatus = GetTokenInformation(
  112. hToken,
  113. TokenGroups,
  114. pTokenGroupList,
  115. ulInfoLength,
  116. &ulInfoLength);
  117. if (!bStatus) {
  118. RASAUTO_TRACE("InteractiveSession: GetTokenInformation failed");
  119. FreeSid(InteractiveSid);
  120. LocalFree(pTokenGroupList);
  121. return (fIsInteractiveSession = FALSE);
  122. }
  123. //
  124. // Search group list for admin alias. If we
  125. // find a match, it most certainly is an
  126. // interactive process.
  127. //
  128. bFoundInteractive = FALSE;
  129. for (ulGroupIndex=0; ulGroupIndex < pTokenGroupList->GroupCount;
  130. ulGroupIndex++)
  131. {
  132. if (EqualSid(
  133. pTokenGroupList->Groups[ulGroupIndex].Sid,
  134. InteractiveSid))
  135. {
  136. bFoundInteractive = TRUE;
  137. break;
  138. }
  139. }
  140. if (!bFoundInteractive) {
  141. //
  142. // If we haven't found a match,
  143. // query and check the user ID.
  144. //
  145. GetTokenInformation(
  146. hToken,
  147. TokenUser,
  148. NULL,
  149. 0,
  150. &ulInfoLength);
  151. pTokenUser = LocalAlloc(LPTR, ulInfoLength);
  152. if (pTokenUser == NULL) {
  153. RASAUTO_TRACE("InteractiveSession: LocalAlloc failed");
  154. FreeSid(InteractiveSid);
  155. LocalFree(pTokenGroupList);
  156. return (fIsInteractiveSession = FALSE);
  157. }
  158. bStatus = GetTokenInformation(
  159. hToken,
  160. TokenUser,
  161. pTokenUser,
  162. ulInfoLength,
  163. &ulInfoLength);
  164. if (!bStatus) {
  165. RASAUTO_TRACE("InteractiveSession: GetTokenInformation failed");
  166. FreeSid(InteractiveSid);
  167. LocalFree(pTokenGroupList);
  168. LocalFree(pTokenUser);
  169. return (fIsInteractiveSession = FALSE);
  170. }
  171. if (EqualSid(pTokenUser->User.Sid, InteractiveSid))
  172. fIsInteractiveSession = TRUE;
  173. LocalFree(pTokenUser);
  174. }
  175. FreeSid(InteractiveSid);
  176. LocalFree(pTokenGroupList);
  177. return (fIsInteractiveSession = bFoundInteractive);
  178. }
  179. #endif
  180. BOOLEAN
  181. SetProcessImpersonationToken(
  182. HANDLE hProcess
  183. )
  184. {
  185. NTSTATUS status;
  186. HANDLE hThread,
  187. hToken = NULL;
  188. //
  189. // Open the impersonation token for the
  190. // process we want to impersonate.
  191. //
  192. if (ImpersonationInfoG.hTokenImpersonation == NULL)
  193. {
  194. if (!OpenProcessToken(
  195. hProcess,
  196. TOKEN_ALL_ACCESS,
  197. &hToken))
  198. {
  199. RASAUTO_TRACE1(
  200. "SetProcessImpersonationToken: OpenProcessToken failed (dwErr=%d)",
  201. GetLastError());
  202. return FALSE;
  203. }
  204. //
  205. // Duplicate the impersonation token.
  206. //
  207. if(!DuplicateToken(
  208. hToken,
  209. TokenImpersonation,
  210. &ImpersonationInfoG.hTokenImpersonation))
  211. {
  212. RASAUTO_TRACE1(
  213. "SetProcessImpersonationToken: NtSetInformationThread failed (error=%d)",
  214. GetLastError());
  215. return FALSE;
  216. }
  217. }
  218. //
  219. // Set the impersonation token on the current
  220. // thread. We are now running in the same
  221. // security context as the supplied process.
  222. //
  223. hThread = NtCurrentThread();
  224. status = NtSetInformationThread(
  225. hThread,
  226. ThreadImpersonationToken,
  227. (PVOID)&ImpersonationInfoG.hTokenImpersonation,
  228. sizeof (ImpersonationInfoG.hTokenImpersonation));
  229. if (status != STATUS_SUCCESS)
  230. {
  231. RASAUTO_TRACE1(
  232. "SetProcessImpersonationToken: NtSetInformationThread failed (error=%d)",
  233. GetLastError());
  234. }
  235. if(NULL != hToken)
  236. {
  237. CloseHandle(hToken);
  238. }
  239. return (status == STATUS_SUCCESS);
  240. } // SetProcessImpersonationToken
  241. VOID
  242. ClearImpersonationToken()
  243. {
  244. //
  245. // Clear the impersonation token on the current
  246. // thread. We are now running in LocalSystem
  247. // security context.
  248. //
  249. if (!SetThreadToken(NULL, NULL)) {
  250. DWORD retcode = GetLastError();
  251. RASAUTO_TRACE1(
  252. "ClearImpersonationToken: SetThreadToken failed (error=%d)",
  253. retcode);
  254. //
  255. // Event log that thread failed to revert.
  256. //
  257. RouterLogWarning(
  258. g_hLogEvent,
  259. ROUTERLOG_CANNOT_REVERT_IMPERSONATION,
  260. 0, NULL, retcode) ;
  261. }
  262. } // ClearImpersonationToken
  263. BOOLEAN
  264. SetPrivilege(
  265. HANDLE hToken,
  266. LPCTSTR Privilege,
  267. BOOLEAN fEnable
  268. )
  269. {
  270. TOKEN_PRIVILEGES tp;
  271. LUID luid;
  272. TOKEN_PRIVILEGES tpPrevious;
  273. DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
  274. if (!LookupPrivilegeValue(NULL, Privilege, &luid))
  275. return FALSE;
  276. //
  277. // First pass. Get current privilege setting.
  278. //
  279. tp.PrivilegeCount = 1;
  280. tp.Privileges[0].Luid = luid;
  281. tp.Privileges[0].Attributes = 0;
  282. AdjustTokenPrivileges(
  283. hToken,
  284. FALSE,
  285. &tp,
  286. sizeof(TOKEN_PRIVILEGES),
  287. &tpPrevious,
  288. &cbPrevious);
  289. if (GetLastError() != ERROR_SUCCESS)
  290. return FALSE;
  291. //
  292. // Second pass. Set privilege based on previous setting
  293. //
  294. tpPrevious.PrivilegeCount = 1;
  295. tpPrevious.Privileges[0].Luid = luid;
  296. if (fEnable)
  297. tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
  298. else {
  299. tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
  300. tpPrevious.Privileges[0].Attributes);
  301. }
  302. AdjustTokenPrivileges(
  303. hToken,
  304. FALSE,
  305. &tpPrevious,
  306. cbPrevious,
  307. NULL,
  308. NULL);
  309. if (GetLastError() != ERROR_SUCCESS)
  310. return FALSE;
  311. return TRUE;
  312. } // SetPrivilege
  313. BOOLEAN
  314. GetCurrentlyLoggedOnUser(
  315. HANDLE *phProcess
  316. )
  317. {
  318. BOOLEAN fSuccess = FALSE;
  319. HKEY hkey;
  320. DWORD dwErr, dwType;
  321. DWORD dwDisp;
  322. WCHAR *pszShell = NULL, **pszShellArray = NULL;
  323. PSYSTEM_PROCESS_INFORMATION pSystemInfo, pProcessInfo;
  324. PWCHAR psz, pszStart;
  325. DWORD i, dwSize, dwcCommands;
  326. NTSTATUS status;
  327. HANDLE hProcess = NULL;
  328. DWORD dwPid = 0;
  329. //
  330. // Get the shell process name. We will look for this
  331. // to find out who the currently logged-on user is.
  332. // Create a unicode string that describes this name.
  333. //
  334. if (RegCreateKeyEx(
  335. HKEY_LOCAL_MACHINE,
  336. SHELL_REGKEY,
  337. 0,
  338. NULL,
  339. REG_OPTION_NON_VOLATILE,
  340. KEY_ALL_ACCESS,
  341. NULL,
  342. &hkey,
  343. &dwDisp) == ERROR_SUCCESS)
  344. {
  345. dwSize = 0;
  346. if (RegQueryValueEx(
  347. hkey,
  348. SHELL_REGVAL,
  349. NULL,
  350. &dwType,
  351. NULL,
  352. &dwSize) == ERROR_SUCCESS)
  353. {
  354. pszShell = (PWCHAR)LocalAlloc(LPTR, dwSize + sizeof (WCHAR));
  355. if (pszShell == NULL) {
  356. RegCloseKey(hkey);
  357. return FALSE;
  358. }
  359. dwErr = RegQueryValueEx(
  360. hkey,
  361. SHELL_REGVAL,
  362. NULL,
  363. &dwType,
  364. (LPBYTE)pszShell,
  365. &dwSize);
  366. RegCloseKey(hkey);
  367. if (dwErr != ERROR_SUCCESS || dwType != REG_SZ) {
  368. LocalFree(pszShell);
  369. pszShell = NULL;
  370. }
  371. }
  372. }
  373. //
  374. // If no shell was found, use DEFAULT_SHELL.
  375. //
  376. if (pszShell == NULL) {
  377. pszShell = (PWCHAR)LocalAlloc(
  378. LPTR,
  379. (lstrlen(DEFAULT_SHELL) + 1) * sizeof (WCHAR));
  380. if (pszShell == NULL)
  381. return FALSE;
  382. lstrcpy(pszShell, DEFAULT_SHELL);
  383. }
  384. RASAUTO_TRACE1("ImpersonateCurrentlyLoggedInUser: pszShell is %S", pszShell);
  385. //
  386. // This string can be a comma separated list,
  387. // so we need to parse it into a list of commands.
  388. //
  389. dwcCommands = 1;
  390. for (psz = pszShell; *psz != L'\0'; psz++) {
  391. if (*psz == L',')
  392. dwcCommands++;
  393. }
  394. //
  395. // Allocate the list of string pointers.
  396. //
  397. pszShellArray = LocalAlloc(LPTR, sizeof (PWCHAR) * dwcCommands);
  398. if (pszShellArray == NULL) {
  399. LocalFree(pszShell);
  400. return FALSE;
  401. }
  402. //
  403. // Ignore any arguments from the command line.
  404. //
  405. dwcCommands = 0;
  406. psz = pszShell;
  407. pszStart = NULL;
  408. for (;;) {
  409. if (*psz == L'\0') {
  410. if (pszStart != NULL)
  411. pszShellArray[dwcCommands++] = pszStart;
  412. break;
  413. }
  414. else if (*psz == L',') {
  415. if (pszStart != NULL)
  416. pszShellArray[dwcCommands++] = pszStart;
  417. *psz = L'\0';
  418. pszStart = NULL;
  419. }
  420. else if (*psz == L' ') {
  421. if (pszStart != NULL)
  422. *psz = L'\0';
  423. }
  424. else {
  425. if (pszStart == NULL)
  426. pszStart = psz;
  427. }
  428. psz++;
  429. }
  430. for (i = 0; i < dwcCommands; i++) {
  431. RASAUTO_TRACE2(
  432. "ImpersonateCurrentlyLoggedInUser: pszShellArray[%d] is %S",
  433. i,
  434. pszShellArray[i]);
  435. }
  436. //
  437. // Get the process list.
  438. //
  439. pSystemInfo = GetSystemProcessInfo();
  440. if(NULL == pSystemInfo)
  441. {
  442. LocalFree(pszShell);
  443. LocalFree(pszShellArray);
  444. return FALSE;
  445. }
  446. while(TRUE)
  447. {
  448. //
  449. // See if any of the processes are running.
  450. //
  451. pProcessInfo =
  452. FindProcessByNameList(
  453. pSystemInfo,
  454. pszShellArray,
  455. dwcCommands,
  456. dwPid,
  457. ImpersonationInfoG.fSessionInitialized,
  458. ImpersonationInfoG.dwCurSessionId);
  459. //
  460. // Open the process token if we've found a match.
  461. //
  462. if (pProcessInfo != NULL)
  463. {
  464. HANDLE hToken;
  465. //
  466. // Open the process.
  467. //
  468. hProcess = OpenProcess(
  469. PROCESS_ALL_ACCESS,
  470. FALSE,
  471. PtrToUlong(pProcessInfo->UniqueProcessId));
  472. if (hProcess == NULL)
  473. {
  474. RASAUTO_TRACE2(
  475. "ImpersonateCurrentlyLoggedInUser: OpenProcess(%d) failed (dwErr=%d)",
  476. PtrToUlong(pProcessInfo->UniqueProcessId),
  477. GetLastError());
  478. dwPid = PtrToUlong(pProcessInfo->UniqueProcessId);
  479. }
  480. else
  481. {
  482. fSuccess = TRUE;
  483. break;
  484. }
  485. }
  486. else
  487. {
  488. break;
  489. }
  490. }
  491. #ifdef notdef
  492. done:
  493. #endif
  494. //
  495. // Free resources.
  496. //
  497. FreeSystemProcessInfo(pSystemInfo);
  498. if (pszShell != NULL)
  499. LocalFree(pszShell);
  500. if (pszShellArray != NULL)
  501. LocalFree(pszShellArray);
  502. //
  503. // Return process handle.
  504. //
  505. *phProcess = hProcess;
  506. return fSuccess;
  507. } // GetCurrentlyLoggedOnUser
  508. DWORD
  509. SetCurrentLoginSession(
  510. IN DWORD dwSessionId)
  511. {
  512. RASAUTO_TRACE1("SetCurrentLoginSession %d", dwSessionId);
  513. EnterCriticalSection(&ImpersonationInfoG.csLock);
  514. ImpersonationInfoG.dwCurSessionId = dwSessionId;
  515. ImpersonationInfoG.fSessionInitialized = TRUE;
  516. LeaveCriticalSection(&ImpersonationInfoG.csLock);
  517. return NO_ERROR;
  518. }
  519. HANDLE
  520. RefreshImpersonation(
  521. HANDLE hProcess
  522. )
  523. {
  524. NTSTATUS status;
  525. EnterCriticalSection(&ImpersonationInfoG.csLock);
  526. //
  527. // If the process still exists,
  528. // we can return.
  529. //
  530. if (ImpersonationInfoG.hProcess != NULL &&
  531. hProcess == ImpersonationInfoG.hProcess)
  532. {
  533. RASAUTO_TRACE1("RefreshImpersonation: hProcess=0x%x no change", hProcess);
  534. goto done;
  535. }
  536. //
  537. // Otherwise recalcuate the current information.
  538. // We have to clear the previous impersonation token,
  539. // if any.
  540. //
  541. if (hProcess != NULL)
  542. ClearImpersonationToken();
  543. if (ImpersonationInfoG.hProcess == NULL) {
  544. RASAUTO_TRACE("RefreshImpersonation: recalcuating token");
  545. if (!GetCurrentlyLoggedOnUser(&ImpersonationInfoG.hProcess)) {
  546. RASAUTO_TRACE("RefreshImpersonation: GetCurrentlyLoggedOnUser failed");
  547. goto done;
  548. }
  549. RASAUTO_TRACE("RefreshImpersonation: new user logged in");
  550. }
  551. //
  552. // Impersonate the currently logged-in user.
  553. //
  554. if (!SetProcessImpersonationToken(ImpersonationInfoG.hProcess))
  555. {
  556. RASAUTO_TRACE(
  557. "RefreshImpersonation: SetProcessImpersonationToken failed");
  558. goto done;
  559. }
  560. #ifdef notdef // imperson
  561. //
  562. // Reset HKEY_CURRENT_USER to get the
  563. // correct value with the new impersonation
  564. // token.
  565. //
  566. RegCloseKey(HKEY_CURRENT_USER);
  567. #endif
  568. RASAUTO_TRACE1(
  569. "RefreshImpersonation: new hProcess=0x%x",
  570. ImpersonationInfoG.hProcess);
  571. TraceCurrentUser();
  572. //
  573. // Open the currently logged on users hive and store it in a global
  574. //
  575. if(NULL != hkeyCUG)
  576. {
  577. NtClose(hkeyCUG);
  578. hkeyCUG = NULL;
  579. }
  580. if(STATUS_SUCCESS != RtlOpenCurrentUser(KEY_ALL_ACCESS, &hkeyCUG))
  581. {
  582. RASAUTO_TRACE("Failed to open HKCU for the current user");
  583. }
  584. done:
  585. LeaveCriticalSection(&ImpersonationInfoG.csLock);
  586. return ImpersonationInfoG.hProcess;
  587. } // RefreshImpersonation
  588. VOID
  589. RevertImpersonation()
  590. /*++
  591. DESCRIPTION
  592. Close all open handles associated with the
  593. logged-in user who has just logged out.
  594. ARGUMENTS
  595. None.
  596. RETURN VALUE
  597. None.
  598. --*/
  599. {
  600. EnterCriticalSection(&ImpersonationInfoG.csLock);
  601. if(ImpersonationInfoG.hToken != NULL)
  602. {
  603. CloseHandle(ImpersonationInfoG.hToken);
  604. ImpersonationInfoG.hToken = NULL;
  605. }
  606. if(ImpersonationInfoG.hTokenImpersonation != NULL)
  607. {
  608. CloseHandle(ImpersonationInfoG.hTokenImpersonation);
  609. ImpersonationInfoG.hTokenImpersonation = NULL;
  610. }
  611. if(ImpersonationInfoG.hProcess != NULL)
  612. {
  613. CloseHandle(ImpersonationInfoG.hProcess);
  614. ImpersonationInfoG.hProcess = NULL;
  615. }
  616. ImpersonationInfoG.fGroupsLoaded = FALSE;
  617. if(NULL != hkeyCUG)
  618. {
  619. NtClose(hkeyCUG);
  620. hkeyCUG = NULL;
  621. }
  622. //
  623. // Clear the thread's impersonation
  624. // token, or it won't be able to open
  625. // another user's process the next
  626. // time around.
  627. //
  628. ClearImpersonationToken();
  629. LeaveCriticalSection(&ImpersonationInfoG.csLock);
  630. } // RevertImpersonation
  631. DWORD
  632. InitSecurityDescriptor(
  633. IN PSECURITY_DESCRIPTOR pSecurityDescriptor
  634. )
  635. /*++
  636. DESCRIPTION
  637. Initialize a security descriptor allowing administrator
  638. access for the sharing of handles between rasman.dll.
  639. This code courtesy of Gurdeep. You need to ask him
  640. exactly what it does.
  641. ARGUMENTS
  642. pSecurityDescriptor: a pointer to the security descriptor
  643. to be initialized.
  644. RETURN VALUE
  645. Win32 error code.
  646. --*/
  647. {
  648. DWORD dwErr = 0;
  649. DWORD cbDaclSize;
  650. PULONG pSubAuthority;
  651. PSID pObjSid = NULL;
  652. PACL pDacl = NULL;
  653. SID_IDENTIFIER_AUTHORITY sidIdentifierWorldAuth =
  654. SECURITY_WORLD_SID_AUTHORITY;
  655. DWORD dwAcls;
  656. //
  657. // Set up the SID for the adminstrators that
  658. // will be allowed access. This SID will have
  659. // 1 sub-authorities: SECURITY_BUILTIN_DOMAIN_RID.
  660. //
  661. pObjSid = (PSID)LocalAlloc(LPTR, GetSidLengthRequired(1));
  662. if (pObjSid == NULL) {
  663. RASAUTO_TRACE("InitSecurityDescriptor: LocalAlloc failed");
  664. return GetLastError();
  665. }
  666. if (!InitializeSid(pObjSid, &sidIdentifierWorldAuth, 1)) {
  667. dwErr = GetLastError();
  668. RASAUTO_TRACE1("InitSecurityDescriptor: InitializeSid failed (dwErr=0x%x)", dwErr);
  669. goto done;
  670. }
  671. //
  672. // Set the sub-authorities.
  673. //
  674. pSubAuthority = GetSidSubAuthority(pObjSid, 0);
  675. *pSubAuthority = SECURITY_WORLD_RID;
  676. //
  677. // Set up the DACL that will allow
  678. // all processes with the above SID all
  679. // access. It should be large enough to
  680. // hold all ACEs.
  681. //
  682. cbDaclSize = sizeof(ACCESS_ALLOWED_ACE) +
  683. GetLengthSid(pObjSid) +
  684. sizeof (ACL);
  685. pDacl = (PACL)LocalAlloc(LPTR, cbDaclSize);
  686. if (pDacl == NULL ) {
  687. RASAUTO_TRACE("InitSecurityDescriptor: LocalAlloc failed");
  688. dwErr = GetLastError();
  689. goto done;
  690. }
  691. if (!InitializeAcl(pDacl, cbDaclSize, ACL_REVISION2)) {
  692. dwErr = GetLastError();
  693. RASAUTO_TRACE1("InitSecurityDescriptor: InitializeAcl failed (dwErr=0x%x)", dwErr);
  694. goto done;
  695. }
  696. dwAcls = SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL;
  697. dwAcls &= ~(WRITE_DAC | WRITE_OWNER);
  698. //
  699. // Add the ACE to the DACL
  700. //
  701. if (!AddAccessAllowedAce(
  702. pDacl,
  703. ACL_REVISION2,
  704. dwAcls,
  705. pObjSid))
  706. {
  707. dwErr = GetLastError();
  708. RASAUTO_TRACE1("InitSecurityDescriptor: AddAccessAllowedAce failed (dwErr=0x%x)", dwErr);
  709. goto done;
  710. }
  711. //
  712. // Create the security descriptor an put
  713. // the DACL in it.
  714. //
  715. if (!InitializeSecurityDescriptor(pSecurityDescriptor, 1)) {
  716. dwErr = GetLastError();
  717. RASAUTO_TRACE1("InitSecurityDescriptor: InitializeSecurityDescriptor failed (dwErr=0x%x)", dwErr);
  718. goto done;
  719. }
  720. if (!SetSecurityDescriptorDacl(
  721. pSecurityDescriptor,
  722. TRUE,
  723. pDacl,
  724. FALSE))
  725. {
  726. dwErr = GetLastError();
  727. RASAUTO_TRACE1("InitSecurityDescriptor: SetSecurityDescriptorDacl failed (dwErr=0x%x)", dwErr);
  728. goto done;
  729. }
  730. //
  731. // Set owner for the descriptor.
  732. //
  733. if (!SetSecurityDescriptorOwner(pSecurityDescriptor, NULL, FALSE)) {
  734. dwErr = GetLastError();
  735. RASAUTO_TRACE1("InitSecurityDescriptor: SetSecurityDescriptorOwner failed (dwErr=0x%x)", dwErr);
  736. goto done;
  737. }
  738. //
  739. // Set group for the descriptor.
  740. //
  741. if (!SetSecurityDescriptorGroup(pSecurityDescriptor, NULL, FALSE)) {
  742. dwErr = GetLastError();
  743. RASAUTO_TRACE1("InitSecurityDescriptor: SetSecurityDescriptorGroup failed (dwErr=0x%x)", dwErr);
  744. goto done;
  745. }
  746. done:
  747. //
  748. // Cleanup if necessary.
  749. //
  750. if (dwErr) {
  751. if (pObjSid != NULL)
  752. LocalFree(pObjSid);
  753. if (pDacl != NULL)
  754. LocalFree(pDacl);
  755. }
  756. return dwErr;
  757. }
  758. DWORD
  759. InitSecurityAttribute()
  760. /*++
  761. DESCRIPTION
  762. Initializes the global security attribute used in
  763. creating shareable handles.
  764. This code courtesy of Gurdeep. You need to ask him
  765. exactly what it does.
  766. ARGUMENTS
  767. None.
  768. RETURN VALUE
  769. Win32 error code.
  770. --*/
  771. {
  772. DWORD dwErr;
  773. //
  774. // Initialize the security descriptor.
  775. //
  776. dwErr = InitSecurityDescriptor(&SecurityDescriptorG);
  777. if (dwErr)
  778. return dwErr;
  779. //
  780. // Initialize the security attributes.
  781. //
  782. SecurityAttributeG.nLength = sizeof(SECURITY_ATTRIBUTES);
  783. SecurityAttributeG.lpSecurityDescriptor = &SecurityDescriptorG;
  784. SecurityAttributeG.bInheritHandle = TRUE;
  785. return 0;
  786. }
  787. VOID
  788. TraceCurrentUser(VOID)
  789. {
  790. //WCHAR szUserName[512];
  791. //DWORD dwSize = sizeof (szUserName) - 1;
  792. //GetUserName(szUserName, &dwSize);
  793. RASAUTO_TRACE1(
  794. "TraceCurrentUser: impersonating Current User %d",
  795. ImpersonationInfoG.dwCurSessionId);
  796. } // TraceCurrentUser
  797. DWORD
  798. DwGetHkcu()
  799. {
  800. DWORD dwErr = ERROR_SUCCESS;
  801. if(NULL == hkeyCUG)
  802. {
  803. dwErr = RtlOpenCurrentUser(
  804. KEY_ALL_ACCESS,
  805. &hkeyCUG);
  806. if(ERROR_SUCCESS != dwErr)
  807. {
  808. RASAUTO_TRACE1("DwGetHhcu: failed to open current user. 0x%x",
  809. dwErr);
  810. goto done;
  811. }
  812. }
  813. done:
  814. return dwErr;
  815. }
  816. DWORD
  817. InitializeImpersonation()
  818. /*++
  819. DESCRIPTION
  820. Initializes the global structures used for impersonation
  821. ARGUMENTS
  822. None
  823. RETURN VALUE
  824. Win32 error code.
  825. --*/
  826. {
  827. DWORD dwError = ERROR_SUCCESS;
  828. if (!ImpersonationInfoInitializedG)
  829. {
  830. ZeroMemory(&ImpersonationInfoG, sizeof(ImpersonationInfoG));
  831. InitializeCriticalSection(&ImpersonationInfoG.csLock);
  832. ImpersonationInfoInitializedG = TRUE;
  833. }
  834. return dwError;
  835. }
  836. VOID
  837. CleanupImpersonation()
  838. /*++
  839. DESCRIPTION
  840. Cleans up the global structures used for impersonation
  841. ARGUMENTS
  842. None
  843. RETURN VALUE
  844. None
  845. --*/
  846. {
  847. if (ImpersonationInfoInitializedG)
  848. {
  849. EnterCriticalSection(&ImpersonationInfoG.csLock);
  850. if (NULL != ImpersonationInfoG.pGuestSid)
  851. {
  852. FreeSid(ImpersonationInfoG.pGuestSid);
  853. ImpersonationInfoG.pGuestSid = NULL;
  854. }
  855. LeaveCriticalSection(&ImpersonationInfoG.csLock);
  856. DeleteCriticalSection(&ImpersonationInfoG.csLock);
  857. ImpersonationInfoInitializedG = FALSE;
  858. }
  859. }
  860. BOOLEAN
  861. ImpersonatingGuest()
  862. /*++
  863. DESCRIPTION
  864. Returns whether or not the user that is currently being impersonating
  865. is a member of the local guests group
  866. ARGUMENTS
  867. None
  868. RETURN VALUE
  869. BOOLEAN -- TRUE if currently impersonating a guests, FALSE otherwise
  870. --*/
  871. {
  872. BOOLEAN fIsGuest = FALSE;
  873. ASSERT(ImpersonationInfoInitializedG);
  874. EnterCriticalSection(&ImpersonationInfoG.csLock);
  875. if (ERROR_SUCCESS == LoadGroupMemberships())
  876. {
  877. fIsGuest = ImpersonationInfoG.fGuest;
  878. }
  879. LeaveCriticalSection(&ImpersonationInfoG.csLock);
  880. return fIsGuest;
  881. }
  882. DWORD
  883. LoadGroupMemberships()
  884. /*++
  885. DESCRIPTION
  886. Caches the group membership information for the impersonated user.
  887. ARGUMENTS
  888. None
  889. RETURN VALUE
  890. Win32 error code.
  891. --*/
  892. {
  893. DWORD dwError = ERROR_SUCCESS;
  894. SID_IDENTIFIER_AUTHORITY IdentifierAuthority = SECURITY_NT_AUTHORITY;
  895. BOOL fIsGuest;
  896. EnterCriticalSection(&ImpersonationInfoG.csLock);
  897. do
  898. {
  899. if (ImpersonationInfoG.fGroupsLoaded)
  900. {
  901. //
  902. // Information already loaded
  903. //
  904. break;
  905. }
  906. if (NULL == ImpersonationInfoG.hTokenImpersonation)
  907. {
  908. //
  909. // There isn't an impersonated user.
  910. //
  911. dwError = ERROR_CAN_NOT_COMPLETE;
  912. break;
  913. }
  914. if (NULL == ImpersonationInfoG.pGuestSid)
  915. {
  916. //
  917. // Allocate the SID for the local guests group;
  918. //
  919. if (!AllocateAndInitializeSid(
  920. &IdentifierAuthority,
  921. 2,
  922. SECURITY_BUILTIN_DOMAIN_RID,
  923. DOMAIN_ALIAS_RID_GUESTS,
  924. 0,
  925. 0,
  926. 0,
  927. 0,
  928. 0,
  929. 0,
  930. &ImpersonationInfoG.pGuestSid
  931. ))
  932. {
  933. dwError = GetLastError();
  934. break;
  935. }
  936. }
  937. if (!CheckTokenMembership(
  938. ImpersonationInfoG.hTokenImpersonation,
  939. ImpersonationInfoG.pGuestSid,
  940. &fIsGuest
  941. ))
  942. {
  943. dwError = GetLastError();
  944. break;
  945. }
  946. ImpersonationInfoG.fGuest = !!fIsGuest;
  947. } while (FALSE);
  948. LeaveCriticalSection(&ImpersonationInfoG.csLock);
  949. return dwError;
  950. }
  951. VOID
  952. LockImpersonation()
  953. {
  954. ASSERT(ImpersonationInfoInitializedG);
  955. if(ImpersonationInfoInitializedG)
  956. {
  957. EnterCriticalSection(&ImpersonationInfoG.csLock);
  958. }
  959. }
  960. VOID
  961. UnlockImpersonation()
  962. {
  963. ASSERT(ImpersonationInfoInitializedG);
  964. if(ImpersonationInfoInitializedG)
  965. {
  966. LeaveCriticalSection(&ImpersonationInfoG.csLock);
  967. }
  968. }