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.

348 lines
9.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. ULONG length;
  74. openPacket = (PAFD_OPEN_PACKET)(eaBuffer->EaName +
  75. eaBuffer->EaNameLength + 1);
  76. //
  77. // Make sure that the transport address fits within the specified
  78. // EA buffer.
  79. //
  80. if ((eaBuffer->EaValueLength<sizeof (*openPacket)) ||
  81. //
  82. // Make sure the cast to USHORT below is valid
  83. //
  84. (length = openPacket->TransportDeviceNameLength +
  85. sizeof (UNICODE_NULL)) > MAXUSHORT ||
  86. //
  87. // Check for overflow
  88. //
  89. length < openPacket->TransportDeviceNameLength ||
  90. FIELD_OFFSET(AFD_OPEN_PACKET,
  91. TransportDeviceName[length/sizeof (WCHAR)]) <
  92. FIELD_OFFSET(AFD_OPEN_PACKET, TransportDeviceName[1]) ||
  93. //
  94. // Check if string + NULL fits into the buffer
  95. //
  96. eaBuffer->EaValueLength <
  97. FIELD_OFFSET(AFD_OPEN_PACKET,
  98. TransportDeviceName[length/sizeof(WCHAR)]) ) {
  99. return STATUS_ACCESS_VIOLATION;
  100. }
  101. //
  102. // Validate parameters in the open packet.
  103. //
  104. if ( (openPacket->afdEndpointFlags&(~AFD_ENDPOINT_VALID_FLAGS)) ||
  105. ( (length / sizeof(WCHAR))*sizeof(WCHAR) != length) // odd-value length
  106. ) {
  107. return STATUS_INVALID_PARAMETER;
  108. }
  109. //
  110. // Set up a string that describes the transport device name.
  111. //
  112. transportDeviceName.Buffer = openPacket->TransportDeviceName;
  113. transportDeviceName.Length = (USHORT)openPacket->TransportDeviceNameLength;
  114. transportDeviceName.MaximumLength = (USHORT)length;
  115. //
  116. // Allocate an AFD endpoint.
  117. //
  118. status = AfdAllocateEndpoint(
  119. &endpoint,
  120. &transportDeviceName,
  121. openPacket->GroupID
  122. );
  123. if( !NT_SUCCESS(status) ) {
  124. return status;
  125. }
  126. //
  127. // Store the flags.
  128. //
  129. endpoint->afdEndpointFlags = openPacket->afdEndpointFlags;
  130. //
  131. // Remember the type of endpoint that this is. If this is a datagram
  132. // endpoint, change the block type to reflect this.
  133. //
  134. if (openPacket->afdConnectionLess) {
  135. endpoint->Type = AfdBlockTypeDatagram;
  136. //
  137. // Initialize lists which exist only in datagram endpoints.
  138. //
  139. InitializeListHead( &endpoint->ReceiveDatagramIrpListHead );
  140. InitializeListHead( &endpoint->PeekDatagramIrpListHead );
  141. InitializeListHead( &endpoint->ReceiveDatagramBufferListHead );
  142. endpoint->Common.Datagram.MaxBufferredReceiveBytes = AfdReceiveWindowSize;
  143. endpoint->Common.Datagram.MaxBufferredSendBytes = AfdSendWindowSize;
  144. }
  145. }
  146. else if (RtlInitString (&CString, AfdSwitchOpenPacket),
  147. RtlEqualString(&CString, &EaName, FALSE)) {
  148. status = AfdSanCreateHelper (Irp, eaBuffer, &endpoint);
  149. if (!NT_SUCCESS (status))
  150. return status;
  151. }
  152. else {
  153. IF_DEBUG(OPEN_CLOSE) {
  154. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  155. "AfdCreate: Invalid ea name.\n"));
  156. }
  157. return STATUS_INVALID_PARAMETER;
  158. }
  159. }
  160. ASSERT( endpoint != NULL );
  161. //
  162. // Perform security check on caller.
  163. // We need this for giving access to raw sockets (for transports
  164. // that do not support access checks) and SAN helpers.
  165. if (IS_SAN_HELPER(endpoint) ||
  166. (endpoint->afdRaw &&
  167. (!endpoint->TransportInfo->InfoValid ||
  168. !IS_TDI_FORCE_ACCESS_CHECK(endpoint)) ) ) {
  169. endpoint->AdminAccessGranted = AfdPerformSecurityCheck (Irp, IrpSp, &status);
  170. }
  171. //
  172. // Set up a pointer to the endpoint in the file object so that we
  173. // can find the endpoint in future calls.
  174. //
  175. IrpSp->FileObject->FsContext = endpoint;
  176. //
  177. // Setting this field to non-NULL value enable fast IO code path
  178. // for reads and writes.
  179. //
  180. IrpSp->FileObject->PrivateCacheMap = (PVOID)-1;
  181. IF_DEBUG(OPEN_CLOSE) {
  182. KdPrintEx(( DPFLTR_WSOCKTRANSPORT_ID, DPFLTR_TRACE_LEVEL,
  183. "AfdCreate: opened file object = %p, endpoint = %p\n",
  184. IrpSp->FileObject, endpoint ));
  185. }
  186. //
  187. // The open worked. Dereference the endpoint and return success.
  188. //
  189. DEREFERENCE_ENDPOINT( endpoint );
  190. return STATUS_SUCCESS;
  191. } // AfdCreate
  192. BOOLEAN
  193. AfdPerformSecurityCheck (
  194. PIRP Irp,
  195. PIO_STACK_LOCATION IrpSp,
  196. PNTSTATUS Status
  197. )
  198. /*++
  199. Routine Description:
  200. Compares security context of the endpoint creator to that
  201. of the administrator and local system.
  202. Arguments:
  203. Irp - Pointer to I/O request packet.
  204. IrpSp - pointer to the IO stack location to use for this request.
  205. Status - returns status generated by access check on failure.
  206. Return Value:
  207. TRUE - the socket creator has admin or local system privilige
  208. FALSE - the socket creator is just a plain user
  209. --*/
  210. {
  211. BOOLEAN accessGranted;
  212. PACCESS_STATE accessState;
  213. PIO_SECURITY_CONTEXT securityContext;
  214. PPRIVILEGE_SET privileges = NULL;
  215. ACCESS_MASK grantedAccess;
  216. PGENERIC_MAPPING GenericMapping;
  217. ACCESS_MASK AccessMask = GENERIC_ALL;
  218. //
  219. // Enable access to all the globally defined SIDs
  220. //
  221. GenericMapping = IoGetFileObjectGenericMapping();
  222. RtlMapGenericMask( &AccessMask, GenericMapping );
  223. securityContext = IrpSp->Parameters.Create.SecurityContext;
  224. accessState = securityContext->AccessState;
  225. SeLockSubjectContext(&accessState->SubjectSecurityContext);
  226. accessGranted = SeAccessCheck(
  227. AfdAdminSecurityDescriptor,
  228. &accessState->SubjectSecurityContext,
  229. TRUE,
  230. AccessMask,
  231. 0,
  232. &privileges,
  233. IoGetFileObjectGenericMapping(),
  234. (KPROCESSOR_MODE)((IrpSp->Flags & SL_FORCE_ACCESS_CHECK)
  235. ? UserMode
  236. : Irp->RequestorMode),
  237. &grantedAccess,
  238. Status
  239. );
  240. if (privileges) {
  241. (VOID) SeAppendPrivileges(
  242. accessState,
  243. privileges
  244. );
  245. SeFreePrivileges(privileges);
  246. }
  247. if (accessGranted) {
  248. accessState->PreviouslyGrantedAccess |= grantedAccess;
  249. accessState->RemainingDesiredAccess &= ~( grantedAccess | MAXIMUM_ALLOWED );
  250. ASSERT (NT_SUCCESS (*Status));
  251. }
  252. else {
  253. ASSERT (!NT_SUCCESS (*Status));
  254. }
  255. SeUnlockSubjectContext(&accessState->SubjectSecurityContext);
  256. return accessGranted;
  257. }