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.

584 lines
17 KiB

  1. /*++
  2. Copyright (c) 1998-2002 Microsoft Corporation
  3. Module Name:
  4. create.c
  5. Abstract:
  6. This module contains code for opening a handle to UL.
  7. Author:
  8. Keith Moore (keithmo) 10-Jun-1998
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text( PAGE, UlCreate )
  14. #endif // ALLOC_PRAGMA
  15. #define IS_NAMED_FILE_OBJECT(pFileObject) \
  16. ((pFileObject)->FileName.Length != 0)
  17. //
  18. // Public functions.
  19. //
  20. /***************************************************************************++
  21. Routine Description:
  22. This is the routine that handles Create IRPs in Http.sys. Create IRPs are
  23. issued when the file object is created.
  24. Control Channel (\Device\Http\Control)
  25. - unnamed only
  26. - open only, create to fail.
  27. - Open will be allowed by any user.
  28. - EA must have proper major/minorversion, everything else must be NULL/0
  29. AppPool (\Device\Http\AppPool)
  30. - can be unnamed or named
  31. - unnamed --> anyone can create, no one can open (server API customers)
  32. - named --> admin only can create, anyone with correct SD can open
  33. (IIS WAS + Worker process)
  34. - EA must have proper major/minorversion, everything else must be NULL/0
  35. Filter (\Device\Http\Filter)
  36. - only named and MUST be either SSLFilterChannel or SSLClientFilterChannel.
  37. - SSLFilterChannel can be created only by admin/local system, opened with
  38. correct SD.
  39. - SSLClientFilterChannel can be created by anyone, opened by anyone
  40. with correct SD, but only if EnableHttpClient is set
  41. - EA must have proper major/minorversion, everything else must be NULL/0
  42. Server (\Device\Http\Server\)
  43. - only unnamed
  44. - Create only, open to fail.
  45. - can be done by anyone.
  46. - Should be allowed only if EnableHttpClient is present.
  47. - EA must have major/minorversion, server & TRANSPORT_ADDRESS structure.
  48. Proxy is optional.
  49. Arguments:
  50. pDeviceObject - Supplies a pointer to the target device object.
  51. pIrp - Supplies a pointer to IO request packet.
  52. Return Value:
  53. NTSTATUS - Completion status.
  54. --***************************************************************************/
  55. NTSTATUS
  56. UlCreate(
  57. IN PDEVICE_OBJECT pDeviceObject,
  58. IN PIRP pIrp
  59. )
  60. {
  61. NTSTATUS status;
  62. PIO_STACK_LOCATION pIrpSp;
  63. PFILE_OBJECT pFileObject = NULL;
  64. PFILE_FULL_EA_INFORMATION pEaBuffer;
  65. PHTTP_OPEN_PACKET pOpenPacket;
  66. UCHAR createDisposition;
  67. PWSTR pName = NULL;
  68. USHORT nameLength;
  69. PIO_SECURITY_CONTEXT pSecurityContext;
  70. STRING CompareVersionName;
  71. STRING EaName;
  72. PWSTR pSafeName = NULL;
  73. //
  74. // Sanity check.
  75. //
  76. PAGED_CODE();
  77. UL_ENTER_DRIVER( "UlCreate", pIrp );
  78. #if defined(_WIN64)
  79. //
  80. // We do not support 32-bit processes on 64-bit platforms.
  81. //
  82. if (IoIs32bitProcess(pIrp))
  83. {
  84. status = STATUS_NOT_SUPPORTED;
  85. goto complete;
  86. }
  87. #endif
  88. //
  89. // Find and validate the open packet.
  90. //
  91. pEaBuffer = (PFILE_FULL_EA_INFORMATION)(pIrp->AssociatedIrp.SystemBuffer);
  92. if (pEaBuffer == NULL)
  93. {
  94. status = STATUS_INVALID_PARAMETER;
  95. goto complete;
  96. }
  97. RtlInitString(&CompareVersionName, HTTP_OPEN_PACKET_NAME);
  98. EaName.MaximumLength = pEaBuffer->EaNameLength + 1;
  99. EaName.Length = pEaBuffer->EaNameLength;
  100. EaName.Buffer = pEaBuffer->EaName;
  101. if ( RtlEqualString(&CompareVersionName, &EaName, FALSE) )
  102. {
  103. //
  104. // Found the version information in the EA
  105. //
  106. if( pEaBuffer->EaValueLength != sizeof(*pOpenPacket) )
  107. {
  108. status = STATUS_INVALID_PARAMETER;
  109. goto complete;
  110. }
  111. if(pEaBuffer->NextEntryOffset != 0)
  112. {
  113. status = STATUS_INVALID_PARAMETER;
  114. goto complete;
  115. }
  116. pOpenPacket = (PHTTP_OPEN_PACKET)
  117. (pEaBuffer->EaName + pEaBuffer->EaNameLength + 1 );
  118. ASSERT(pOpenPacket == ALIGN_UP_POINTER(pOpenPacket, PVOID));
  119. //
  120. // For now, we'll fail if the incoming version doesn't EXACTLY match
  121. // the expected version. In future, we may need to be a bit more
  122. // flexible to allow down-level clients.
  123. //
  124. if (pOpenPacket->MajorVersion != HTTP_INTERFACE_VERSION_MAJOR ||
  125. pOpenPacket->MinorVersion != HTTP_INTERFACE_VERSION_MINOR)
  126. {
  127. status = STATUS_REVISION_MISMATCH;
  128. goto complete;
  129. }
  130. if(pDeviceObject != g_pUcServerDeviceObject &&
  131. (pOpenPacket->ProxyNameLength != 0 ||
  132. pOpenPacket->ServerNameLength != 0 ||
  133. pOpenPacket->TransportAddressLength != 0 ||
  134. pOpenPacket->pProxyName != NULL ||
  135. pOpenPacket->pServerName != NULL ||
  136. pOpenPacket->pTransportAddress != NULL))
  137. {
  138. status = STATUS_INVALID_PARAMETER;
  139. goto complete;
  140. }
  141. }
  142. else
  143. {
  144. status = STATUS_INVALID_PARAMETER;
  145. goto complete;
  146. }
  147. //
  148. // Snag the current IRP stack pointer, then extract the creation
  149. // disposition. IO stores this as the high byte of the Options field.
  150. // Also snag the file object; we'll need it often.
  151. //
  152. pIrpSp = IoGetCurrentIrpStackLocation( pIrp );
  153. createDisposition = (UCHAR)( pIrpSp->Parameters.Create.Options >> 24 );
  154. pFileObject = pIrpSp->FileObject;
  155. pSecurityContext = pIrpSp->Parameters.Create.SecurityContext;
  156. ASSERT( pSecurityContext != NULL );
  157. //
  158. // Determine if this is a request to open a control channel or
  159. // open/create an app pool.
  160. //
  161. if (pDeviceObject == g_pUlControlDeviceObject)
  162. {
  163. //
  164. // It's a control channel.
  165. //
  166. // Validate the creation disposition. We allow open only.
  167. //
  168. if (createDisposition != FILE_OPEN)
  169. {
  170. status = STATUS_INVALID_PARAMETER;
  171. goto complete;
  172. }
  173. // These things can't be named
  174. if (IS_NAMED_FILE_OBJECT(pFileObject))
  175. {
  176. status = STATUS_INVALID_PARAMETER;
  177. goto complete;
  178. }
  179. ASSERT(pFileObject->FileName.Buffer == NULL);
  180. UlTrace(OPEN_CLOSE, (
  181. "UlCreate: opening a control channel: %p\n",
  182. pFileObject
  183. ));
  184. //
  185. // Open the control channel.
  186. //
  187. status = UlCreateControlChannel(GET_PP_CONTROL_CHANNEL(pFileObject));
  188. if (NT_SUCCESS(status))
  189. {
  190. ASSERT( GET_CONTROL_CHANNEL(pFileObject) != NULL );
  191. MARK_VALID_CONTROL_CHANNEL( pFileObject );
  192. }
  193. }
  194. else if (pDeviceObject == g_pUlFilterDeviceObject)
  195. {
  196. //
  197. // It's a filter channel - It has to be named and has to be either
  198. // a client or a server filter channel.
  199. //
  200. if (!IS_NAMED_FILE_OBJECT(pFileObject))
  201. {
  202. status = STATUS_INVALID_PARAMETER;
  203. goto complete;
  204. }
  205. ASSERT(L'\\' == pFileObject->FileName.Buffer[0]);
  206. pName = pFileObject->FileName.Buffer + 1;
  207. nameLength = pFileObject->FileName.Length - sizeof(WCHAR);
  208. pSafeName = UL_ALLOCATE_POOL(
  209. PagedPool,
  210. nameLength + sizeof(WCHAR),
  211. UL_STRING_LOG_BUFFER_POOL_TAG
  212. );
  213. if(pSafeName == NULL)
  214. {
  215. status = STATUS_INSUFFICIENT_RESOURCES;
  216. goto complete;
  217. }
  218. RtlCopyMemory(pSafeName, pName, nameLength);
  219. pSafeName[nameLength/sizeof(WCHAR)] = L'\0';
  220. pName = pSafeName;
  221. if(IsServerFilterChannel(pName, nameLength))
  222. {
  223. // Yes - it's a filter channel. We'll allow Create or Open but
  224. // both have to be admin only.
  225. //
  226. // If it's create, we'll do an access check
  227. //
  228. if(createDisposition == FILE_CREATE)
  229. {
  230. status = UlAccessCheck(
  231. g_pAdminAllSystemAll,
  232. pSecurityContext->AccessState,
  233. pSecurityContext->DesiredAccess,
  234. pIrp->RequestorMode,
  235. pName
  236. );
  237. if(!NT_SUCCESS(status))
  238. {
  239. goto complete;
  240. }
  241. }
  242. else if(createDisposition == FILE_OPEN)
  243. {
  244. // We are opening an existing channel - the access check
  245. // will be done inside UlAttachFilterProcess
  246. }
  247. else
  248. {
  249. // Neither FILE_CREATE nor FILE_OPEN. Bail!
  250. status = STATUS_INVALID_PARAMETER;
  251. goto complete;
  252. }
  253. UlTrace(OPEN_CLOSE, (
  254. "UlCreate: opening a server filter channel: %p, %.*ls\n",
  255. pFileObject, nameLength / sizeof(WCHAR), pName
  256. ));
  257. }
  258. else if(IsClientFilterChannel(pName, nameLength))
  259. {
  260. // It's a client - Only Create. Also, make sure that the client
  261. // code is really enabled.
  262. if (createDisposition != FILE_CREATE || !g_HttpClientEnabled)
  263. {
  264. status = STATUS_INVALID_PARAMETER;
  265. goto complete;
  266. }
  267. UlTrace(OPEN_CLOSE, (
  268. "UlCreate: opening a client filter channel: %p, %.*ls\n",
  269. pFileObject, nameLength / sizeof(WCHAR), pName
  270. ));
  271. //
  272. // No access checks for the client!
  273. //
  274. }
  275. else
  276. {
  277. //
  278. // If it is neither server nor client filter channel, fail the
  279. // call.
  280. //
  281. status = STATUS_INVALID_PARAMETER;
  282. goto complete;
  283. }
  284. status = UlAttachFilterProcess(
  285. pName,
  286. nameLength,
  287. (BOOLEAN)(createDisposition == FILE_CREATE),
  288. pSecurityContext->AccessState,
  289. pSecurityContext->DesiredAccess,
  290. pIrp->RequestorMode,
  291. GET_PP_FILTER_PROCESS(pFileObject)
  292. );
  293. if (NT_SUCCESS(status))
  294. {
  295. ASSERT( GET_FILTER_PROCESS(pFileObject) != NULL );
  296. MARK_VALID_FILTER_CHANNEL( pFileObject );
  297. }
  298. }
  299. else if(pDeviceObject == g_pUlAppPoolDeviceObject )
  300. {
  301. //
  302. // It's an app pool.
  303. //
  304. //
  305. // Bind to the specified app pool.
  306. //
  307. if (!IS_NAMED_FILE_OBJECT(pFileObject))
  308. {
  309. ASSERT(pFileObject->FileName.Buffer == NULL);
  310. pName = NULL;
  311. nameLength = 0;
  312. // Validate the creation disposition. We allow create only
  313. // for unnamed app-pools.
  314. if(createDisposition != FILE_CREATE)
  315. {
  316. status = STATUS_INVALID_PARAMETER;
  317. goto complete;
  318. }
  319. UlTrace(OPEN_CLOSE, (
  320. "UlCreate: opening an unnamed AppPool: %p\n",
  321. pFileObject
  322. ));
  323. }
  324. else
  325. {
  326. if (pFileObject->FileName.Length > UL_MAX_APP_POOL_NAME_SIZE)
  327. {
  328. status = STATUS_OBJECT_NAME_INVALID;
  329. goto complete;
  330. }
  331. // Skip the preceding '\' in the FileName added by iomgr.
  332. //
  333. ASSERT(L'\\' == pFileObject->FileName.Buffer[0]);
  334. pName = pFileObject->FileName.Buffer + 1;
  335. nameLength = pFileObject->FileName.Length - sizeof(WCHAR);
  336. pSafeName = UL_ALLOCATE_POOL(
  337. PagedPool,
  338. nameLength + sizeof(WCHAR),
  339. UL_STRING_LOG_BUFFER_POOL_TAG
  340. );
  341. if(pSafeName == NULL)
  342. {
  343. status = STATUS_INSUFFICIENT_RESOURCES;
  344. goto complete;
  345. }
  346. RtlCopyMemory(pSafeName, pName, nameLength);
  347. pSafeName[nameLength/sizeof(WCHAR)] = L'\0';
  348. pName = pSafeName;
  349. if(createDisposition == FILE_CREATE)
  350. {
  351. //
  352. // Creation of named app-pools must be only for admins.
  353. //
  354. // The filter object is has FileAll for Admin/LocalSystem only
  355. // so, we'll piggy back on that security descriptor.
  356. //
  357. status = UlAccessCheck(
  358. g_pAdminAllSystemAll,
  359. pSecurityContext->AccessState,
  360. pSecurityContext->DesiredAccess,
  361. pIrp->RequestorMode,
  362. pName
  363. );
  364. if(!NT_SUCCESS(status))
  365. {
  366. goto complete;
  367. }
  368. }
  369. else if(createDisposition == FILE_OPEN)
  370. {
  371. // UlAttachProcessToAppPool will do the appropriate checks
  372. // to ensure that the security descriptors match.
  373. }
  374. else
  375. {
  376. // Neither FILE_CREATE nor FILE_OPEN.
  377. status = STATUS_INVALID_PARAMETER;
  378. goto complete;
  379. }
  380. UlTrace(OPEN_CLOSE, (
  381. "UlCreate: opening an AppPool: %p, %.*ls\n",
  382. pFileObject, nameLength / sizeof(WCHAR), pName
  383. ));
  384. }
  385. status = UlAttachProcessToAppPool(
  386. pName,
  387. nameLength,
  388. (BOOLEAN)(createDisposition == FILE_CREATE),
  389. pSecurityContext->AccessState,
  390. pSecurityContext->DesiredAccess,
  391. pIrp->RequestorMode,
  392. GET_PP_APP_POOL_PROCESS(pFileObject)
  393. );
  394. if (NT_SUCCESS(status))
  395. {
  396. ASSERT( GET_APP_POOL_PROCESS(pFileObject) != NULL );
  397. MARK_VALID_APP_POOL( pFileObject );
  398. }
  399. }
  400. else
  401. {
  402. ASSERT(pDeviceObject == g_pUcServerDeviceObject );
  403. ASSERT(g_HttpClientEnabled);
  404. //
  405. // It is mandatory for the application to pass in a valid version
  406. // and a valid URI. If either of this is missing, we bail.
  407. //
  408. //
  409. if(pOpenPacket->ServerNameLength == 0 ||
  410. pOpenPacket->pServerName == NULL ||
  411. pOpenPacket->pTransportAddress == NULL ||
  412. pOpenPacket->TransportAddressLength == 0 ||
  413. IS_NAMED_FILE_OBJECT(pFileObject)
  414. )
  415. {
  416. status = STATUS_INVALID_PARAMETER;
  417. goto complete;
  418. }
  419. if(createDisposition != FILE_CREATE)
  420. {
  421. status = STATUS_INVALID_PARAMETER;
  422. goto complete;
  423. }
  424. UlTrace(OPEN_CLOSE, (
  425. "UlCreate: opening a ServInfo: %p\n",
  426. pFileObject
  427. ));
  428. //
  429. // Create our context here and store it in
  430. // pIrpSp->FileObject->FsContext
  431. //
  432. status = UcCreateServerInformation(
  433. (PUC_PROCESS_SERVER_INFORMATION *)
  434. &pFileObject->FsContext,
  435. pOpenPacket->pServerName,
  436. pOpenPacket->ServerNameLength,
  437. pOpenPacket->pProxyName,
  438. pOpenPacket->ProxyNameLength,
  439. pOpenPacket->pTransportAddress,
  440. pOpenPacket->TransportAddressLength,
  441. pIrp->RequestorMode
  442. );
  443. //
  444. // UC_BUGBUG (INVESTIGATE)
  445. //
  446. // Setting this field to non-NULL value enable fast IO code path
  447. // for reads and writes.
  448. //
  449. // pIrpSp->FileObject->PrivateCacheMap = (PVOID)-1;
  450. MARK_VALID_SERVER( pFileObject );
  451. }
  452. //
  453. // Complete the request.
  454. //
  455. complete:
  456. if(pSafeName)
  457. {
  458. ASSERT(pSafeName == pName);
  459. UL_FREE_POOL(pSafeName, UL_STRING_LOG_BUFFER_POOL_TAG);
  460. }
  461. UlTrace(OPEN_CLOSE, (
  462. "UlCreate: %s file object = %p, %s\n",
  463. (NT_SUCCESS(status) ? "opened" : "did not open"),
  464. pFileObject,
  465. HttpStatusToString(status)
  466. ));
  467. pIrp->IoStatus.Status = status;
  468. UlCompleteRequest( pIrp, IO_NO_INCREMENT );
  469. UL_LEAVE_DRIVER( "UlCreate" );
  470. RETURN(status);
  471. } // UlCreate