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.

600 lines
17 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  5. //
  6. // File: desktop.cxx
  7. //
  8. // Contents: Creation/initialization of the Scheduling Agent windowstation
  9. // and its desktop, "SAWinSta\SADesktop". This windowstation
  10. // needs to exist to run tasks when no user is logged on, or the
  11. // logged on user is different than the task-specific account.
  12. //
  13. // Classes: None.
  14. //
  15. // Functions: None.
  16. //
  17. // History: 26-Jun-96 MarkBl Created
  18. //
  19. //----------------------------------------------------------------------------
  20. #include "..\pch\headers.hxx"
  21. #pragma hdrstop
  22. #include "debug.hxx"
  23. #include "..\inc\security.hxx"
  24. #define SA_WINDOW_STATION L"SAWinSta"
  25. #define SA_DESKTOP L"SADesktop"
  26. //
  27. // Define all access to windows objects
  28. //
  29. // From windows\gina\winlogon\secutil.c
  30. //
  31. #define DESKTOP_ALL (DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | \
  32. DESKTOP_CREATEMENU | DESKTOP_HOOKCONTROL | \
  33. DESKTOP_JOURNALRECORD | DESKTOP_JOURNALPLAYBACK | \
  34. DESKTOP_ENUMERATE | DESKTOP_WRITEOBJECTS | \
  35. DESKTOP_SWITCHDESKTOP | STANDARD_RIGHTS_REQUIRED)
  36. #define WINSTA_ALL (WINSTA_ENUMDESKTOPS | WINSTA_READATTRIBUTES | \
  37. WINSTA_ACCESSCLIPBOARD | WINSTA_CREATEDESKTOP | \
  38. WINSTA_WRITEATTRIBUTES | WINSTA_ACCESSGLOBALATOMS | \
  39. WINSTA_EXITWINDOWS | WINSTA_ENUMERATE | \
  40. WINSTA_READSCREEN | \
  41. STANDARD_RIGHTS_REQUIRED)
  42. #define WINSTA_ATOMS (WINSTA_ACCESSGLOBALATOMS | \
  43. WINSTA_ACCESSCLIPBOARD )
  44. HDESK CreateSADesktop(HWINSTA hWinSta);
  45. HWINSTA CreateSAWindowStation(void);
  46. PSID GetProcessSid(void);
  47. BOOL InitializeSAWindow(void);
  48. BOOL SetSADesktopSecurity(
  49. HDESK hDesktop,
  50. PSID pSchedAgentSid,
  51. PSID pBatchSid);
  52. BOOL SetSAWindowStationSecurity(
  53. HWINSTA hWinSta,
  54. PSID pSchedAgentSid,
  55. PSID pBatchSid);
  56. void UninitializeSAWindow(void);
  57. // Globals used in this module exclusively.
  58. // Initialized in InitializeSAWindow, closed in UnitializeSAWindow.
  59. //
  60. HWINSTA ghSAWinsta = NULL; // Handle to window station, "SAWinSta".
  61. HDESK ghSADesktop = NULL; // Handle to desktop, "SADesktop"
  62. //+---------------------------------------------------------------------------
  63. //
  64. // Function: InitializeSAWindow
  65. //
  66. // Synopsis: Create and set security info on the windowstation\desktop,
  67. // "SAWinSta\SADesktop". This desktop exists for tasks which
  68. // run under an account different than the currently logged
  69. // on user, or when no user is logged on. Note, these tasks will
  70. // never appear on the interactive desktop.
  71. //
  72. // Arguments: None.
  73. //
  74. // Returns: TRUE -- Everything succeeded.
  75. // FALSE -- Encountered an error.
  76. //
  77. // Notes: None.
  78. //
  79. //----------------------------------------------------------------------------
  80. BOOL
  81. InitializeSAWindow(void)
  82. {
  83. BOOL fRet = TRUE;
  84. PSID pBatchSid;
  85. PSID pSchedAgentSid;
  86. HWINSTA hWinSta = NULL;
  87. HWINSTA hServiceWinSta = NULL;
  88. HDESK hDesktop = NULL;
  89. BOOL fChangedWinSta = FALSE;
  90. //
  91. // Retrieve local system and batch account SIDs.
  92. //
  93. SID_IDENTIFIER_AUTHORITY SidAuth = SECURITY_NT_AUTHORITY;
  94. if (!AllocateAndInitializeSid(&SidAuth,
  95. 1,
  96. SECURITY_BATCH_RID,
  97. 0, 0, 0, 0, 0, 0, 0,
  98. &pBatchSid))
  99. {
  100. schDebugOut((DEB_ERROR,
  101. "InitializeSAWindow, AllocateAndInitializeSid failed, " \
  102. "status = 0x%lx\n",
  103. GetLastError()));
  104. return(FALSE);
  105. }
  106. if ((pSchedAgentSid = GetProcessSid()) == NULL)
  107. {
  108. fRet = FALSE;
  109. goto CleanExit;
  110. }
  111. //
  112. // Get current service window station.
  113. //
  114. hServiceWinSta = GetProcessWindowStation();
  115. if (hServiceWinSta == NULL) {
  116. fRet = FALSE;
  117. goto CleanExit;
  118. }
  119. //
  120. // Create the window station & desktop.
  121. //
  122. if ((hWinSta = CreateSAWindowStation()) == NULL)
  123. {
  124. fRet = FALSE;
  125. goto CleanExit;
  126. }
  127. if (!SetProcessWindowStation(hWinSta))
  128. {
  129. schDebugOut((DEB_ERROR,
  130. "InitializeSAWindow, SetProcessWindowStation failed, " \
  131. "status = 0x%lx\n",
  132. GetLastError()));
  133. fRet = FALSE;
  134. goto CleanExit;
  135. }
  136. fChangedWinSta = TRUE;
  137. if ((hDesktop = CreateSADesktop(hWinSta)) == NULL)
  138. {
  139. fRet = FALSE;
  140. goto CleanExit;
  141. }
  142. //
  143. // Set security on the window station & desktop.
  144. //
  145. if (!SetSAWindowStationSecurity(hWinSta, pSchedAgentSid, pBatchSid))
  146. {
  147. fRet = FALSE;
  148. goto CleanExit;
  149. }
  150. if (!SetSADesktopSecurity(hDesktop, pSchedAgentSid, pBatchSid))
  151. {
  152. fRet = FALSE;
  153. goto CleanExit;
  154. }
  155. CleanExit:
  156. //
  157. // If we have changed the window station, switch back to service window
  158. // station.
  159. //
  160. if (fChangedWinSta) {
  161. schAssert(hServiceWinSta);
  162. if (!SetProcessWindowStation(hServiceWinSta))
  163. {
  164. schDebugOut((DEB_ERROR,
  165. "InitializeSAWindow, SetProcessWindowStation failed, status = 0x%lx\n",
  166. GetLastError()));
  167. fRet = FALSE;
  168. }
  169. }
  170. if (pBatchSid != NULL) FreeSid(pBatchSid);
  171. if (pSchedAgentSid != NULL) LocalFree(pSchedAgentSid);
  172. if (fRet)
  173. {
  174. ghSAWinsta = hWinSta;
  175. ghSADesktop = hDesktop;
  176. }
  177. else
  178. {
  179. if (hWinSta != NULL) CloseHandle(hWinSta);
  180. if (hDesktop != NULL) CloseHandle(hDesktop);
  181. //
  182. // even though the initial NULL values should still be untouched,
  183. // we'll be extra paranoid here and pretend that gremlins may have fiddled with them
  184. //
  185. ghSAWinsta = NULL;
  186. ghSADesktop = NULL;
  187. }
  188. return(fRet);
  189. }
  190. //+---------------------------------------------------------------------------
  191. //
  192. // Function: UninitializeSAWindow
  193. //
  194. // Synopsis: Close the global window station & desktop handles.
  195. //
  196. // Arguments: None.
  197. //
  198. // Returns: None.
  199. //
  200. // Notes: None.
  201. //
  202. //----------------------------------------------------------------------------
  203. void
  204. UninitializeSAWindow(void)
  205. {
  206. if (ghSADesktop != NULL)
  207. {
  208. CloseDesktop(ghSADesktop);
  209. ghSADesktop = NULL;
  210. }
  211. if (ghSAWinsta != NULL)
  212. {
  213. CloseWindowStation(ghSAWinsta);
  214. ghSAWinsta = NULL;
  215. }
  216. }
  217. //+---------------------------------------------------------------------------
  218. //
  219. // Function: GetProcessSid
  220. //
  221. // Synopsis: Obtain the SID of this process.
  222. //
  223. // Arguments: None.
  224. //
  225. // Returns: This process' sid.
  226. // NULL on failure.
  227. //
  228. // Notes: None.
  229. //
  230. //----------------------------------------------------------------------------
  231. PSID
  232. GetProcessSid(void)
  233. {
  234. PSECURITY_DESCRIPTOR psdProcessSD = NULL;
  235. PSID pProcessSid = NULL;
  236. PSID pProcessSidTmp;
  237. DWORD cbSize;
  238. HANDLE hProcess;
  239. BOOL fOwnerDefaulted;
  240. hProcess = GetCurrentProcess();
  241. if (hProcess == NULL)
  242. {
  243. schDebugOut((DEB_ERROR,
  244. "GetProcessSid, GetCurrentProcess failed, status = 0x%lx\n",
  245. GetLastError()));
  246. return(NULL);
  247. }
  248. //
  249. // Retrieve the buffer size necessary to retrieve this process' SD.
  250. //
  251. if (!GetKernelObjectSecurity(hProcess,
  252. OWNER_SECURITY_INFORMATION,
  253. NULL,
  254. 0,
  255. &cbSize) &&
  256. GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  257. {
  258. psdProcessSD = LocalAlloc(LMEM_FIXED, cbSize);
  259. if (psdProcessSD == NULL)
  260. {
  261. schDebugOut((DEB_ERROR,
  262. "GetProcessSid, process security descriptor allocation " \
  263. "failure\n"));
  264. return(NULL);
  265. }
  266. //
  267. // Actually retrieve this process' SD.
  268. //
  269. if (!GetKernelObjectSecurity(hProcess,
  270. OWNER_SECURITY_INFORMATION,
  271. psdProcessSD,
  272. cbSize,
  273. &cbSize))
  274. {
  275. schDebugOut((DEB_ERROR,
  276. "GetProcessSid, GetKernelObjectSecurity failed, " \
  277. "status = 0x%lx\n",
  278. GetLastError()));
  279. goto ErrorExit;
  280. }
  281. }
  282. else
  283. {
  284. schAssert(0 && "GetKernelObjectSecurity() succeeded!");
  285. return(NULL);
  286. }
  287. //
  288. // Retrieve the owner SID from the SD.
  289. //
  290. if (!GetSecurityDescriptorOwner(psdProcessSD,
  291. &pProcessSidTmp,
  292. &fOwnerDefaulted))
  293. {
  294. schDebugOut((DEB_ERROR,
  295. "GetProcessSid, GetSecurityDescriptorOwner failed, " \
  296. "status = 0x%lx\n",
  297. GetLastError()));
  298. goto ErrorExit;
  299. }
  300. //
  301. // An unnecessary check, maybe, but safe.
  302. //
  303. if (!IsValidSid(pProcessSidTmp))
  304. {
  305. schDebugOut((DEB_ERROR,
  306. "GetProcessSid, IsValidSid failed, status = 0x%lx\n",
  307. GetLastError()));
  308. goto ErrorExit;
  309. }
  310. //
  311. // Make a copy of the SID since that returned from GetSecuritySD refers
  312. // within the security descriptor allocated above.
  313. //
  314. cbSize = GetLengthSid(pProcessSidTmp);
  315. pProcessSid = LocalAlloc(LMEM_FIXED, cbSize);
  316. if (pProcessSid == NULL)
  317. {
  318. schDebugOut((DEB_ERROR,
  319. "GetProcessSid, process SID allocation failure\n"));
  320. goto ErrorExit;
  321. }
  322. if (!CopySid(cbSize, pProcessSid, pProcessSidTmp))
  323. {
  324. LocalFree(pProcessSid);
  325. pProcessSid = NULL;
  326. schDebugOut((DEB_ERROR,
  327. "GetProcessSid, CopySid failed, status = 0x%lx\n",
  328. GetLastError()));
  329. }
  330. ErrorExit:
  331. if (psdProcessSD != NULL) LocalFree(psdProcessSD);
  332. return(pProcessSid);
  333. }
  334. //+---------------------------------------------------------------------------
  335. //
  336. // Function: CreateSAWindowStation
  337. //
  338. // Synopsis: Create the window station named "SAWinSta".
  339. //
  340. // Arguments: None.
  341. //
  342. // Returns: Window station handle on success.
  343. // NULL on failure.
  344. //
  345. // Notes: None.
  346. //
  347. //----------------------------------------------------------------------------
  348. HWINSTA
  349. CreateSAWindowStation(void)
  350. {
  351. HWINSTA hWinSta;
  352. if ((hWinSta = CreateWindowStation(SA_WINDOW_STATION,
  353. NULL,
  354. MAXIMUM_ALLOWED,
  355. NULL)) == NULL)
  356. {
  357. schDebugOut((DEB_ERROR,
  358. "CreateSAWindowStation, CreateWindowStation failed, " \
  359. "status = 0x%lx\n",
  360. GetLastError()));
  361. return(NULL);
  362. }
  363. return(hWinSta);
  364. }
  365. //+---------------------------------------------------------------------------
  366. //
  367. // Function: CreateSADesktop
  368. //
  369. // Synopsis: Create the desktop, "SADesktop", on the window station
  370. // indicated.
  371. //
  372. // Arguments: [hWinSta] -- Window station.
  373. //
  374. // Returns: Desktop handle on success.
  375. // NULL on failure.
  376. //
  377. // Notes: None.
  378. //
  379. //----------------------------------------------------------------------------
  380. HDESK
  381. CreateSADesktop(HWINSTA hWinSta)
  382. {
  383. HDESK hDesktop;
  384. if ((hDesktop = CreateDesktop(SA_DESKTOP,
  385. NULL,
  386. NULL,
  387. 0,
  388. MAXIMUM_ALLOWED,
  389. NULL)) == NULL)
  390. {
  391. schDebugOut((DEB_ERROR,
  392. "CreateSADesktop, CreateDesktop failed, status = 0x%lx\n",
  393. GetLastError()));
  394. return(NULL);
  395. }
  396. return(hDesktop);
  397. }
  398. //+---------------------------------------------------------------------------
  399. //
  400. // Function: SetSAWindowStationSecurity
  401. //
  402. // Synopsis: Set permissions on the scheduling agent window station for
  403. // this process and batch users.
  404. //
  405. // Arguments: [hWinSta] -- Window station.
  406. // [pSchedAgentSid] -- Scheduling Agent process SID.
  407. // [pBatchSid] -- Batch SID.
  408. //
  409. // Returns: TRUE -- Function succeeded,
  410. // FALSE -- Otherwise.
  411. //
  412. // Notes: None.
  413. //
  414. //----------------------------------------------------------------------------
  415. BOOL
  416. SetSAWindowStationSecurity(
  417. HWINSTA hWinSta,
  418. PSID pSchedAgentSid,
  419. PSID pBatchSid)
  420. {
  421. #define WS_ACE_COUNT 4
  422. PACCESS_ALLOWED_ACE rgAce[WS_ACE_COUNT] = {
  423. NULL, NULL, NULL, NULL }; // Supply this to CreateSD so we
  424. // don't have to allocate memory.
  425. MYACE rgMyAce[WS_ACE_COUNT] = {
  426. { WINSTA_ALL, // Acess mask.
  427. NO_PROPAGATE_INHERIT_ACE, // Inherit flags.
  428. pSchedAgentSid }, // SID.
  429. { GENERIC_ALL,
  430. OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE,
  431. pSchedAgentSid },
  432. { WINSTA_ALL & ~(DELETE | WRITE_DAC | WRITE_OWNER), // need to leave READ_CONTROL in this or jobs can't run
  433. NO_PROPAGATE_INHERIT_ACE,
  434. pBatchSid },
  435. { GENERIC_READ | GENERIC_EXECUTE,
  436. INHERIT_ONLY_ACE,
  437. pBatchSid }
  438. };
  439. schAssert(WS_ACE_COUNT == (sizeof(rgAce)/sizeof(PACCESS_ALLOWED_ACE)) &&
  440. WS_ACE_COUNT == (sizeof(rgMyAce) / sizeof(MYACE)));
  441. PSECURITY_DESCRIPTOR pSecurityDescriptor;
  442. SECURITY_INFORMATION si;
  443. DWORD Status = 0;
  444. if ((pSecurityDescriptor = CreateSecurityDescriptor(WS_ACE_COUNT,
  445. rgMyAce,
  446. rgAce)) == NULL)
  447. {
  448. return(FALSE);
  449. }
  450. si = DACL_SECURITY_INFORMATION;
  451. if (!SetUserObjectSecurity(hWinSta, &si, pSecurityDescriptor))
  452. {
  453. Status = GetLastError();
  454. }
  455. DeleteSecurityDescriptor(pSecurityDescriptor);
  456. if (Status)
  457. {
  458. schDebugOut((DEB_ERROR,
  459. "SetSASetWindowStationSecurity, SetUserObjectSecurity failed, " \
  460. "status = 0x%lx\n",
  461. Status));
  462. return(FALSE);
  463. }
  464. return(TRUE);
  465. }
  466. //+---------------------------------------------------------------------------
  467. //
  468. // Function: SetSADesktopSecurity
  469. //
  470. // Synopsis: Set permissions on the scheduling agent desktop for this
  471. // process and batch users.
  472. //
  473. // Arguments: [hDesktop] -- Desktop.
  474. // [pSchedAgentSid] -- Scheduling Agent process SID.
  475. // [pBatchSid] -- Batch SID.
  476. //
  477. // Returns: TRUE -- Function succeeded,
  478. // FALSE -- Otherwise.
  479. //
  480. // Notes: None.
  481. //
  482. //----------------------------------------------------------------------------
  483. BOOL
  484. SetSADesktopSecurity(
  485. HDESK hDesktop,
  486. PSID pSchedAgentSid,
  487. PSID pBatchSid)
  488. {
  489. #define DT_ACE_COUNT 2
  490. PACCESS_ALLOWED_ACE rgAce[DT_ACE_COUNT] = {
  491. NULL, NULL }; // Supply this to CreateSD so we
  492. // don't have to allocate memory.
  493. MYACE rgMyAce[DT_ACE_COUNT] = {
  494. { DESKTOP_ALL, // Acess mask.
  495. 0, // Inherit flags.
  496. pSchedAgentSid }, // SID.
  497. { DESKTOP_ALL & ~STANDARD_RIGHTS_REQUIRED,
  498. 0,
  499. pBatchSid }
  500. };
  501. schAssert(DT_ACE_COUNT == (sizeof(rgAce)/sizeof(PACCESS_ALLOWED_ACE)) &&
  502. DT_ACE_COUNT == (sizeof(rgMyAce) / sizeof(MYACE)));
  503. PSECURITY_DESCRIPTOR pSecurityDescriptor;
  504. SECURITY_INFORMATION si;
  505. DWORD Status = 0;
  506. if ((pSecurityDescriptor = CreateSecurityDescriptor(DT_ACE_COUNT,
  507. rgMyAce,
  508. rgAce)) == NULL)
  509. {
  510. return(FALSE);
  511. }
  512. si = DACL_SECURITY_INFORMATION;
  513. if (!SetUserObjectSecurity(hDesktop, &si, pSecurityDescriptor))
  514. {
  515. Status = GetLastError();
  516. }
  517. DeleteSecurityDescriptor(pSecurityDescriptor);
  518. if (Status)
  519. {
  520. schDebugOut((DEB_ERROR,
  521. "SetSADesktopSecurity, SetUserObjectSecurity failed, " \
  522. "status = 0x%lx\n",
  523. Status));
  524. return(FALSE);
  525. }
  526. return(TRUE);
  527. }