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.

339 lines
8.2 KiB

  1. /*===================================================================
  2. Microsoft IIS
  3. Microsoft Confidential.
  4. Copyright 1996-1997 Microsoft Corporation. All Rights Reserved.
  5. Component: Server object
  6. File: NTSec.cxx
  7. Owner: AndrewS
  8. This file contains code related to NT security on WinSta's and Desktops
  9. ===================================================================*/
  10. #include <dbgutil.h>
  11. #include <apiutil.h>
  12. #include <loadmd.hxx>
  13. #include <loadadm.hxx>
  14. #include <ole2.h>
  15. #include <inetsvcs.h>
  16. #include "ntsec.h"
  17. // Globals
  18. HWINSTA ghWinSta = NULL;
  19. HWINSTA ghWinStaPrev = NULL;
  20. HDESK ghDesktop = NULL;
  21. HDESK ghdeskPrev = NULL;
  22. HRESULT InitOleSecurity(BOOL);
  23. /*===================================================================
  24. InitDesktopWinsta
  25. Create a desktop and a winstation for IIS to use
  26. Parameters:
  27. Returns:
  28. HRESULT NOERROR on success
  29. Side effects
  30. Sets global variables
  31. ===================================================================*/
  32. HRESULT InitDesktopWinsta(
  33. BOOL fAllowError
  34. )
  35. {
  36. HRESULT hr = NOERROR;
  37. DWORD err;
  38. HWINSTA hWinSta = NULL;
  39. HDESK hDesktop = NULL;
  40. OSVERSIONINFO osInfo;
  41. BOOL fWinNT = FALSE;
  42. osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  43. if ( GetVersionEx( &osInfo ) ) {
  44. fWinNT = (osInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
  45. }
  46. // Only applies to NT
  47. if ( !fWinNT )
  48. return(NOERROR);
  49. // Save our old window station so we can restore it later
  50. ghWinStaPrev = GetProcessWindowStation();
  51. if (ghWinStaPrev == NULL)
  52. goto LErr;
  53. // Create a winsta for IIS to use
  54. if ((hWinSta = CreateWindowStation(SZ_IIS_WINSTA, NULL, WINSTA_ALL, NULL)) == NULL)
  55. {
  56. if ( !fAllowError )
  57. {
  58. goto LErr;
  59. }
  60. }
  61. else
  62. {
  63. // Set this as IIS's window station
  64. if (!SetProcessWindowStation(hWinSta))
  65. goto LErr;
  66. }
  67. // Save the old desktop because we might need it later for an obscure error condition
  68. if ((ghdeskPrev = GetThreadDesktop(GetCurrentThreadId())) == NULL)
  69. {
  70. goto LErr;
  71. }
  72. // Create a desktop for IIS to use
  73. if ((hDesktop = CreateDesktop(SZ_IIS_DESKTOP, NULL, NULL, 0, DESKTOP_ALL, NULL)) == NULL)
  74. {
  75. if ( !fAllowError )
  76. {
  77. goto LErr;
  78. }
  79. }
  80. // store these handles in the globals
  81. ghWinSta = hWinSta;
  82. ghDesktop = hDesktop;
  83. // Now initialize Ole security
  84. hr = InitOleSecurity(fAllowError);
  85. return(hr);
  86. LErr:
  87. if (ghWinStaPrev != NULL)
  88. SetProcessWindowStation(ghWinStaPrev);
  89. if (hWinSta != NULL)
  90. CloseWindowStation(hWinSta);
  91. if (hDesktop != NULL)
  92. CloseDesktop(hDesktop);
  93. err = GetLastError();
  94. hr = HRESULT_FROM_WIN32(err);
  95. return(hr);
  96. }
  97. /*===================================================================
  98. UnInitDesktopWinsta
  99. Destroy the IIS desktop and winstation
  100. Parameters:
  101. None
  102. Returns:
  103. Nothing
  104. Side effects
  105. Sets global variables
  106. ===================================================================*/
  107. VOID UnInitDesktopWinsta()
  108. {
  109. BOOL fClosed;
  110. if (ghWinSta != NULL)
  111. {
  112. // Set winsta back to the old winsta so we can close the new one
  113. fClosed = SetProcessWindowStation(ghWinStaPrev);
  114. DBG_ASSERT(fClosed);
  115. fClosed = CloseWindowStation(ghWinSta);
  116. DBG_ASSERT(fClosed);
  117. ghWinSta = NULL;
  118. }
  119. if (ghDesktop != NULL)
  120. {
  121. BOOL fRetried = FALSE;
  122. LRetry:
  123. DBG_ASSERT(ghDesktop != NULL);
  124. fClosed = CloseDesktop(ghDesktop);
  125. // If this fails, it probably means that we are in the obscure case where
  126. // IIS's CacheExtensions registry setting is 0. In this case, we are shutting
  127. // down in a worker thread. This worker thread is using the desktop, so
  128. // it cant be closed. In this case, attempt to set the desktop back to the
  129. // original IIS desktop, and then retry closing the desktop. Only retry once.
  130. if (!fClosed && !fRetried)
  131. {
  132. fRetried = TRUE;
  133. if (!SetThreadDesktop(ghdeskPrev))
  134. DBG_ASSERT(FALSE);
  135. goto LRetry;
  136. }
  137. DBG_ASSERT(fClosed);
  138. ghDesktop = NULL;
  139. }
  140. return;
  141. }
  142. /*===================================================================
  143. SetDesktop
  144. Set the desktop for the calling thread
  145. Parameters:
  146. None
  147. Returns:
  148. NOERROR on success
  149. Side effects:
  150. Sets desktop
  151. ===================================================================*/
  152. HRESULT SetDesktop(
  153. BOOL fAllowError
  154. )
  155. {
  156. DWORD err;
  157. if (!SetThreadDesktop(ghDesktop))
  158. goto LErr;
  159. return(NOERROR);
  160. LErr:
  161. if ( !fAllowError )
  162. {
  163. DBG_ASSERT(FALSE);
  164. }
  165. err = GetLastError();
  166. return(HRESULT_FROM_WIN32(err));
  167. }
  168. /*===================================================================
  169. InitOleSecurity
  170. Setup for and call CoInitializeSecurity. This will avoid problems with
  171. DCOM security on sites that have no default security.
  172. Parameters:
  173. None
  174. Returns:
  175. Retail -- Always returns NOERROR, failures are ignored.
  176. We dont want to have a failure of setting up security
  177. stop IIS from running at all.
  178. Debug -- DBG_ASSERTs on error and returns error code
  179. Side effects:
  180. Sets desktop
  181. ===================================================================*/
  182. HRESULT InitOleSecurity(
  183. BOOL fAllowError
  184. )
  185. {
  186. HRESULT hr = NOERROR;
  187. BOOL fDoCoUninit = TRUE;
  188. DWORD err;
  189. SECURITY_DESCRIPTOR SecurityDesc;
  190. SID NullSid = { SID_REVISION, 1, SECURITY_NULL_SID_AUTHORITY, SECURITY_NULL_RID };
  191. HDESK hdeskSave = NULL;
  192. /*
  193. * We need to set up a security descriptor with an empty ACL so that
  194. * we can CoInitializeSecurity but not give everyone access to the server.
  195. */
  196. if (!InitializeSecurityDescriptor(&SecurityDesc, SECURITY_DESCRIPTOR_REVISION))
  197. goto LErr;
  198. ACL Acl;
  199. // Initialize a new ACL.
  200. if (!InitializeAcl(&Acl, sizeof(ACL), ACL_REVISION2))
  201. goto LErr;
  202. // Add new ACL to the security descriptor.
  203. if (!SetSecurityDescriptorDacl( &SecurityDesc, TRUE, &Acl, FALSE ))
  204. goto LErr;
  205. if (!SetSecurityDescriptorOwner(&SecurityDesc, &NullSid, FALSE))
  206. goto LErr;
  207. if (!SetSecurityDescriptorGroup(&SecurityDesc, &NullSid, FALSE))
  208. goto LErr;
  209. /*
  210. * This work must be done on the desktop that our threads are going to use.
  211. * However, we are currently running on IIS's thread, and we dont want to
  212. * whack their desktop. So, set to our desktop, do the CoInitializeSecurity,
  213. * then set the old desktop back again. Ole will cache the desktop that
  214. * was set when this CoInitSec was done.
  215. */
  216. if (FAILED(hr = SetDesktop(fAllowError)))
  217. {
  218. goto LErr;
  219. }
  220. hr = CoInitialize(NULL);
  221. if( FAILED(hr) )
  222. {
  223. fDoCoUninit = FALSE;
  224. }
  225. hr = CoInitializeSecurity(
  226. NULL,
  227. -1,
  228. NULL,
  229. NULL,
  230. RPC_C_AUTHN_LEVEL_CONNECT,
  231. RPC_C_IMP_LEVEL_IMPERSONATE,
  232. NULL,
  233. EOAC_DYNAMIC_CLOAKING,
  234. NULL );
  235. if( FAILED(hr) )
  236. {
  237. DBGERROR(( DBG_CONTEXT,
  238. "CoInitializeSecurity failed running with default "
  239. "DCOM security settings, hr=%8x\n",
  240. hr
  241. ));
  242. }
  243. if( fDoCoUninit )
  244. {
  245. CoUninitialize();
  246. }
  247. // Set the desktop back to what IIS expected it to be
  248. if (!SetThreadDesktop(ghdeskPrev))
  249. {
  250. // Nothing we can do if this fails
  251. DBG_ASSERT(FALSE);
  252. }
  253. //
  254. // This may fire if CoInitializeSecurity fails. So it is probably
  255. // overactive we would have let the CoInitializeSecurity call fail
  256. // in the past, before some PREFIX changes.
  257. //
  258. DBG_ASSERT(SUCCEEDED(hr));
  259. return(hr);
  260. LErr:
  261. DBG_ASSERT(FALSE);
  262. if (SUCCEEDED(hr))
  263. {
  264. err = GetLastError();
  265. hr = HRESULT_FROM_WIN32(err);
  266. }
  267. #ifdef DEBUG
  268. return(hr);
  269. #else
  270. return(NOERROR);
  271. #endif
  272. }