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.

332 lines
8.8 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. dispatch.c
  5. Abstract:
  6. This module contains code for opening a handle to AFD.
  7. Author:
  8. David Treadwell (davidtr) 21-Feb-1992
  9. Revision History:
  10. --*/
  11. #include "afdp.h"
  12. BOOLEAN
  13. AfdPerformSecurityCheck (
  14. PIRP Irp,
  15. PIO_STACK_LOCATION IrpSp,
  16. PNTSTATUS Status
  17. );
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text( PAGE, AfdCreate )
  20. #pragma alloc_text( PAGE, AfdPerformSecurityCheck )
  21. #endif
  22. NTSTATUS
  23. FASTCALL
  24. AfdCreate (
  25. IN PIRP Irp,
  26. IN PIO_STACK_LOCATION IrpSp
  27. )
  28. /*++
  29. Routine Description:
  30. This is the routine that handles Create IRPs in AFD. If creates an
  31. AFD_ENDPOINT structure and fills it in with the information
  32. specified in the open packet.
  33. Arguments:
  34. Irp - Pointer to I/O request packet.
  35. IrpSp - pointer to the IO stack location to use for this request.
  36. Return Value:
  37. NTSTATUS -- Indicates whether the request was successfully queued.
  38. --*/
  39. {
  40. PAFD_ENDPOINT endpoint;
  41. PFILE_FULL_EA_INFORMATION eaBuffer;
  42. UNICODE_STRING transportDeviceName;
  43. NTSTATUS status;
  44. PAGED_CODE( );
  45. DEBUG endpoint = NULL;
  46. //
  47. // Find the open packet from the EA buffer in the system buffer of
  48. // the associated IRP. Fail the request if there was no EA
  49. // buffer specified.
  50. //
  51. eaBuffer = Irp->AssociatedIrp.SystemBuffer;
  52. if ( eaBuffer == NULL ) {
  53. //
  54. // Allocate an AFD "helper" endpoint.
  55. //
  56. status = AfdAllocateEndpoint(
  57. &endpoint,
  58. NULL,
  59. 0
  60. );
  61. if( !NT_SUCCESS(status) ) {
  62. return status;
  63. }
  64. } else {
  65. STRING EaName;
  66. STRING CString;
  67. EaName.MaximumLength = eaBuffer->EaNameLength+1;
  68. EaName.Length = eaBuffer->EaNameLength;
  69. EaName.Buffer = eaBuffer->EaName;
  70. if (RtlInitString (&CString, AfdOpenPacket),
  71. RtlEqualString(&CString, &EaName, FALSE)) {
  72. PAFD_OPEN_PACKET openPacket;
  73. openPacket = (PAFD_OPEN_PACKET)(eaBuffer->EaName +
  74. eaBuffer->EaNameLength + 1);
  75. //
  76. // Make sure that the transport address fits within the specified
  77. // EA buffer.
  78. //
  79. if ((eaBuffer->EaValueLength<sizeof (*openPacket)) ||
  80. //
  81. // Check for overflow
  82. //
  83. (FIELD_OFFSET(AFD_OPEN_PACKET,
  84. TransportDeviceName[openPacket->TransportDeviceNameLength/2+1])
  85. <FIELD_OFFSET(AFD_OPEN_PACKET, TransportDeviceName[1])) ||
  86. (eaBuffer->EaValueLength <
  87. FIELD_OFFSET(AFD_OPEN_PACKET,
  88. TransportDeviceName[openPacket->TransportDeviceNameLength/2+1])) ) {
  89. return STATUS_ACCESS_VIOLATION;
  90. }
  91. //
  92. // Validate parameters in the open packet.
  93. //
  94. if (openPacket->afdEndpointFlags&(~AFD_ENDPOINT_VALID_FLAGS)) {
  95. return STATUS_INVALID_PARAMETER;
  96. }
  97. //
  98. // Set up a string that describes the transport device name.
  99. //
  100. transportDeviceName.Buffer = openPacket->TransportDeviceName;
  101. transportDeviceName.Length = (USHORT)openPacket->TransportDeviceNameLength;
  102. transportDeviceName.MaximumLength =
  103. transportDeviceName.Length + sizeof(WCHAR);
  104. //
  105. // Allocate an AFD endpoint.
  106. //
  107. status = AfdAllocateEndpoint(
  108. &endpoint,
  109. &transportDeviceName,
  110. openPacket->GroupID
  111. );
  112. if( !NT_SUCCESS(status) ) {
  113. return status;
  114. }
  115. //
  116. // Store the flags.
  117. //
  118. endpoint->afdEndpointFlags = openPacket->afdEndpointFlags;
  119. //
  120. // Remember the type of endpoint that this is. If this is a datagram
  121. // endpoint, change the block type to reflect this.
  122. //
  123. if (openPacket->afdConnectionLess) {
  124. endpoint->Type = AfdBlockTypeDatagram;
  125. //
  126. // Initialize lists which exist only in datagram endpoints.
  127. //
  128. InitializeListHead( &endpoint->ReceiveDatagramIrpListHead );
  129. InitializeListHead( &endpoint->PeekDatagramIrpListHead );
  130. InitializeListHead( &endpoint->ReceiveDatagramBufferListHead );
  131. endpoint->Common.Datagram.MaxBufferredReceiveBytes = AfdReceiveWindowSize;
  132. endpoint->Common.Datagram.MaxBufferredSendBytes = AfdSendWindowSize;
  133. }
  134. }
  135. else if (RtlInitString (&CString, AfdSwitchOpenPacket),
  136. RtlEqualString(&CString, &EaName, FALSE)) {
  137. status = AfdSanCreateHelper (Irp, eaBuffer, &endpoint);
  138. if (!NT_SUCCESS (status))
  139. return status;
  140. }
  141. else {
  142. IF_DEBUG(OPEN_CLOSE) {
  143. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  144. "AfdCreate: Invalid ea name.\n"));
  145. }
  146. return STATUS_INVALID_PARAMETER;
  147. }
  148. }
  149. ASSERT( endpoint != NULL );
  150. //
  151. // Perform security check on caller.
  152. // We need this to know whether to allow exclusive
  153. // address use when allocating transport address in bind
  154. // as well as giving access to raw sockets.
  155. endpoint->AdminAccessGranted = AfdPerformSecurityCheck (Irp, IrpSp, &status);
  156. //
  157. // Set up a pointer to the endpoint in the file object so that we
  158. // can find the endpoint in future calls.
  159. //
  160. IrpSp->FileObject->FsContext = endpoint;
  161. //
  162. // Setting this field to non-NULL value enable fast IO code path
  163. // for reads and writes.
  164. //
  165. IrpSp->FileObject->PrivateCacheMap = (PVOID)-1;
  166. IF_DEBUG(OPEN_CLOSE) {
  167. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  168. "AfdCreate: opened file object = %p, endpoint = %p\n",
  169. IrpSp->FileObject, endpoint ));
  170. }
  171. //
  172. // The open worked. Dereference the endpoint and return success.
  173. //
  174. DEREFERENCE_ENDPOINT( endpoint );
  175. return STATUS_SUCCESS;
  176. } // AfdCreate
  177. BOOLEAN
  178. AfdPerformSecurityCheck (
  179. PIRP Irp,
  180. PIO_STACK_LOCATION IrpSp,
  181. PNTSTATUS Status
  182. )
  183. /*++
  184. Routine Description:
  185. Compares security context of the endpoint creator to that
  186. of the administrator and local system.
  187. Arguments:
  188. Irp - Pointer to I/O request packet.
  189. IrpSp - pointer to the IO stack location to use for this request.
  190. Status - returns status generated by access check on failure.
  191. Return Value:
  192. TRUE - the socket creator has admin or local system privilige
  193. FALSE - the socket creator is just a plain user
  194. --*/
  195. {
  196. BOOLEAN accessGranted;
  197. PACCESS_STATE accessState;
  198. PIO_SECURITY_CONTEXT securityContext;
  199. PPRIVILEGE_SET privileges = NULL;
  200. ACCESS_MASK grantedAccess;
  201. PGENERIC_MAPPING GenericMapping;
  202. ACCESS_MASK AccessMask = GENERIC_ALL;
  203. //
  204. // Enable access to all the globally defined SIDs
  205. //
  206. GenericMapping = IoGetFileObjectGenericMapping();
  207. RtlMapGenericMask( &AccessMask, GenericMapping );
  208. securityContext = IrpSp->Parameters.Create.SecurityContext;
  209. accessState = securityContext->AccessState;
  210. SeLockSubjectContext(&accessState->SubjectSecurityContext);
  211. accessGranted = SeAccessCheck(
  212. AfdAdminSecurityDescriptor,
  213. &accessState->SubjectSecurityContext,
  214. TRUE,
  215. AccessMask,
  216. 0,
  217. &privileges,
  218. IoGetFileObjectGenericMapping(),
  219. (KPROCESSOR_MODE)((IrpSp->Flags & SL_FORCE_ACCESS_CHECK)
  220. ? UserMode
  221. : Irp->RequestorMode),
  222. &grantedAccess,
  223. Status
  224. );
  225. if (privileges) {
  226. (VOID) SeAppendPrivileges(
  227. accessState,
  228. privileges
  229. );
  230. SeFreePrivileges(privileges);
  231. }
  232. if (accessGranted) {
  233. accessState->PreviouslyGrantedAccess |= grantedAccess;
  234. accessState->RemainingDesiredAccess &= ~( grantedAccess | MAXIMUM_ALLOWED );
  235. ASSERT (NT_SUCCESS (*Status));
  236. }
  237. else {
  238. ASSERT (!NT_SUCCESS (*Status));
  239. }
  240. SeUnlockSubjectContext(&accessState->SubjectSecurityContext);
  241. return accessGranted;
  242. }