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.

508 lines
11 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. fsctl.c
  5. Abstract:
  6. This module implements the NtDeviceIoControlFile API's for the NT datagram
  7. receiver (bowser).
  8. Author:
  9. Eyal Schwartz (EyalS) Dec-9-1998
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. //
  15. // Extern defined from #include <ob.h>.
  16. // Couldn't include ob.h due to redefinition conflicts. We had attempted to change ntos\makefil0
  17. // so as to include it in ntsrv.h, but decided we shouldn't expose it. This does the job.
  18. //
  19. NTSTATUS
  20. ObGetObjectSecurity(
  21. IN PVOID Object,
  22. OUT PSECURITY_DESCRIPTOR *SecurityDescriptor,
  23. OUT PBOOLEAN MemoryAllocated
  24. );
  25. VOID
  26. ObReleaseObjectSecurity(
  27. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  28. IN BOOLEAN MemoryAllocated
  29. );
  30. // defines //
  31. // pool tag
  32. #define BOW_SECURITY_POOL_TAG ( (ULONG)'seLB' )
  33. // local prototypes //
  34. NTSTATUS
  35. BowserBuildDeviceAcl(
  36. OUT PACL *DeviceAcl
  37. );
  38. NTSTATUS
  39. BowserCreateAdminSecurityDescriptor(
  40. IN PDEVICE_OBJECT pDevice
  41. );
  42. #ifdef ALLOC_PRAGMA
  43. #pragma alloc_text(SECUR, BowserBuildDeviceAcl)
  44. #pragma alloc_text(SECUR, BowserCreateAdminSecurityDescriptor)
  45. #pragma alloc_text(SECUR, BowserInitializeSecurity)
  46. #pragma alloc_text(SECUR, BowserSecurityCheck )
  47. #endif
  48. SECURITY_DESCRIPTOR
  49. *g_pBowSecurityDescriptor = NULL;
  50. // function implementation //
  51. NTSTATUS
  52. BowserBuildDeviceAcl(
  53. OUT PACL *DeviceAcl
  54. )
  55. /*++
  56. Routine Description:
  57. This routine builds an ACL which gives Administrators and LocalSystem
  58. principals full access. All other principals have no access.
  59. Lifted form \nt\private\ntos\afd\init.c!AfdBuildDeviceAcl()
  60. Arguments:
  61. DeviceAcl - Output pointer to the new ACL.
  62. Return Value:
  63. STATUS_SUCCESS or an appropriate error code.
  64. --*/
  65. {
  66. PGENERIC_MAPPING GenericMapping;
  67. PSID AdminsSid;
  68. PSID SystemSid;
  69. ULONG AclLength;
  70. NTSTATUS Status;
  71. ACCESS_MASK AccessMask = GENERIC_ALL;
  72. PACL NewAcl;
  73. //
  74. // Enable access to all the globally defined SIDs
  75. //
  76. GenericMapping = IoGetFileObjectGenericMapping();
  77. RtlMapGenericMask( &AccessMask, GenericMapping );
  78. // SeEnableAccessToExports();
  79. AdminsSid = SeExports->SeAliasAdminsSid;
  80. SystemSid = SeExports->SeLocalSystemSid;
  81. AclLength = sizeof( ACL ) +
  82. 2 * sizeof( ACCESS_ALLOWED_ACE ) +
  83. RtlLengthSid( AdminsSid ) +
  84. RtlLengthSid( SystemSid ) -
  85. 2 * sizeof( ULONG );
  86. NewAcl = ExAllocatePoolWithTag(
  87. PagedPool,
  88. AclLength,
  89. BOW_SECURITY_POOL_TAG
  90. );
  91. if (NewAcl == NULL) {
  92. return( STATUS_INSUFFICIENT_RESOURCES );
  93. }
  94. Status = RtlCreateAcl (NewAcl, AclLength, ACL_REVISION );
  95. if (!NT_SUCCESS( Status )) {
  96. ExFreePool(
  97. NewAcl
  98. );
  99. return( Status );
  100. }
  101. Status = RtlAddAccessAllowedAce (
  102. NewAcl,
  103. ACL_REVISION,
  104. AccessMask,
  105. AdminsSid
  106. );
  107. ASSERT( NT_SUCCESS( Status ));
  108. Status = RtlAddAccessAllowedAce (
  109. NewAcl,
  110. ACL_REVISION,
  111. AccessMask,
  112. SystemSid
  113. );
  114. ASSERT( NT_SUCCESS( Status ));
  115. *DeviceAcl = NewAcl;
  116. return( STATUS_SUCCESS );
  117. } // BowBuildDeviceAcl
  118. NTSTATUS
  119. BowserCreateAdminSecurityDescriptor(
  120. IN PDEVICE_OBJECT pDevice
  121. )
  122. /*++
  123. Routine Description:
  124. This routine creates a security descriptor which gives access
  125. only to Administrtors and LocalSystem. This descriptor is used
  126. to access check raw endpoint opens and exclisive access to transport
  127. addresses.
  128. LIfted form \nt\private\ntos\afd\init.c!AfdCreateAdminSecurityDescriptor()
  129. Arguments:
  130. None.
  131. Return Value:
  132. STATUS_SUCCESS or an appropriate error code.
  133. --*/
  134. {
  135. PACL rawAcl = NULL;
  136. NTSTATUS status;
  137. BOOLEAN memoryAllocated = FALSE;
  138. PSECURITY_DESCRIPTOR BowSecurityDescriptor;
  139. ULONG BowSecurityDescriptorLength;
  140. CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
  141. PSECURITY_DESCRIPTOR localSecurityDescriptor =
  142. (PSECURITY_DESCRIPTOR) &buffer;
  143. PSECURITY_DESCRIPTOR localBowAdminSecurityDescriptor;
  144. SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION;
  145. #if 1
  146. //
  147. // this is the way AFD gets the object SD (the preferred way).
  148. //
  149. status = ObGetObjectSecurity(
  150. pDevice,
  151. &BowSecurityDescriptor,
  152. &memoryAllocated
  153. );
  154. if (!NT_SUCCESS(status)) {
  155. KdPrint((
  156. "Bowser: Unable to get security descriptor, error: %x\n",
  157. status
  158. ));
  159. ASSERT(memoryAllocated == FALSE);
  160. return(status);
  161. }
  162. #else
  163. //
  164. // Get a pointer to the security descriptor from the our device object.
  165. // If we can't access ob api's due to include dependencies, we'll use it directly.
  166. // ** Need to verify it is legal (I doubt it)**
  167. // Need to dump this as soon as we can fix ntos\makefil0 to include ob.h in
  168. // the generated ntsrv.h
  169. //
  170. BowSecurityDescriptor = pDevice->SecurityDescriptor;
  171. if ( !BowSecurityDescriptor )
  172. {
  173. KdPrint((
  174. "Bowser: Unable to get security descriptor, error: %x\n",
  175. status
  176. ));
  177. return STATUS_INVALID_SECURITY_DESCR;
  178. }
  179. #endif
  180. //
  181. // Build a local security descriptor with an ACL giving only
  182. // administrators and system access.
  183. //
  184. status = BowserBuildDeviceAcl(&rawAcl);
  185. if (!NT_SUCCESS(status)) {
  186. KdPrint(("Bowser: Unable to create Raw ACL, error: %x\n", status));
  187. goto error_exit;
  188. }
  189. (VOID) RtlCreateSecurityDescriptor(
  190. localSecurityDescriptor,
  191. SECURITY_DESCRIPTOR_REVISION
  192. );
  193. (VOID) RtlSetDaclSecurityDescriptor(
  194. localSecurityDescriptor,
  195. TRUE,
  196. rawAcl,
  197. FALSE
  198. );
  199. //
  200. // Make a copy of the Bow descriptor. This copy will be the raw descriptor.
  201. //
  202. BowSecurityDescriptorLength = RtlLengthSecurityDescriptor(
  203. BowSecurityDescriptor
  204. );
  205. localBowAdminSecurityDescriptor = ExAllocatePoolWithTag (
  206. PagedPool,
  207. BowSecurityDescriptorLength,
  208. BOW_SECURITY_POOL_TAG
  209. );
  210. if (localBowAdminSecurityDescriptor == NULL) {
  211. KdPrint(("Bowser: couldn't allocate security descriptor\n"));
  212. goto error_exit;
  213. }
  214. RtlMoveMemory(
  215. localBowAdminSecurityDescriptor,
  216. BowSecurityDescriptor,
  217. BowSecurityDescriptorLength
  218. );
  219. g_pBowSecurityDescriptor = localBowAdminSecurityDescriptor;
  220. //
  221. // Now apply the local descriptor to the raw descriptor.
  222. //
  223. status = SeSetSecurityDescriptorInfo(
  224. NULL,
  225. &securityInformation,
  226. localSecurityDescriptor,
  227. &g_pBowSecurityDescriptor,
  228. PagedPool,
  229. IoGetFileObjectGenericMapping()
  230. );
  231. if (!NT_SUCCESS(status)) {
  232. KdPrint(("Bowser: SeSetSecurity failed, %lx\n", status));
  233. ASSERT (g_pBowSecurityDescriptor==localBowAdminSecurityDescriptor);
  234. ExFreePool (g_pBowSecurityDescriptor);
  235. g_pBowSecurityDescriptor = NULL;
  236. goto error_exit;
  237. }
  238. if (g_pBowSecurityDescriptor!=localBowAdminSecurityDescriptor) {
  239. ExFreePool (localBowAdminSecurityDescriptor);
  240. }
  241. status = STATUS_SUCCESS;
  242. error_exit:
  243. #if 1
  244. //
  245. // see remark above
  246. //
  247. ObReleaseObjectSecurity(
  248. BowSecurityDescriptor,
  249. memoryAllocated
  250. );
  251. #endif
  252. if (rawAcl!=NULL) {
  253. ExFreePool(
  254. rawAcl
  255. );
  256. }
  257. return(status);
  258. }
  259. NTSTATUS
  260. BowserInitializeSecurity(
  261. IN PDEVICE_OBJECT pDevice
  262. )
  263. /*++
  264. Routine Description (BowserInitializeSecurity):
  265. Initialize Bowser security.
  266. - Create default bowser security descriptor based on device sercurity
  267. Arguments:
  268. device: opened device
  269. Return Value:
  270. Remarks:
  271. None.
  272. --*/
  273. {
  274. NTSTATUS Status;
  275. if ( g_pBowSecurityDescriptor )
  276. {
  277. return STATUS_SUCCESS;
  278. }
  279. ASSERT(pDevice);
  280. Status = BowserCreateAdminSecurityDescriptor ( pDevice );
  281. return Status;
  282. }
  283. BOOLEAN
  284. BowserSecurityCheck (
  285. PIRP Irp,
  286. PIO_STACK_LOCATION IrpSp,
  287. PNTSTATUS Status
  288. )
  289. /*++
  290. Routine Description:
  291. Lifted as is from \\index1\src\nt\private\ntos\afd\create.c!AfdPerformSecurityCheck
  292. Compares security context of the endpoint creator to that
  293. of the administrator and local system.
  294. Note: This is currently called only on IOCTL Irps. IOCRTLs don't have a create security
  295. context (only creates...), thus we should always capture the security context rather
  296. then attempting to extract it from the IrpSp.
  297. Arguments:
  298. Irp - Pointer to I/O request packet.
  299. IrpSp - pointer to the IO stack location to use for this request.
  300. Status - returns status generated by access check on failure.
  301. Return Value:
  302. TRUE - the socket creator has admin or local system privilige
  303. FALSE - the socket creator is just a plain user
  304. --*/
  305. {
  306. BOOLEAN accessGranted;
  307. PACCESS_STATE accessState;
  308. PIO_SECURITY_CONTEXT securityContext;
  309. SECURITY_SUBJECT_CONTEXT SubjectContext;
  310. PSECURITY_SUBJECT_CONTEXT pSubjectContext = &SubjectContext;
  311. ACCESS_MASK grantedAccess;
  312. PGENERIC_MAPPING GenericMapping;
  313. ACCESS_MASK AccessMask = GENERIC_ALL;
  314. PAGED_CODE();
  315. ASSERT (g_pBowSecurityDescriptor);
  316. //
  317. // Get security context from process.
  318. //
  319. SeCaptureSubjectContext(&SubjectContext);
  320. SeLockSubjectContext(pSubjectContext);
  321. //
  322. // Build access evaluation:
  323. // Enable access to all the globally defined SIDs
  324. //
  325. GenericMapping = IoGetFileObjectGenericMapping();
  326. RtlMapGenericMask( &AccessMask, GenericMapping );
  327. //
  328. // AccessCheck test
  329. //
  330. accessGranted = SeAccessCheck(
  331. g_pBowSecurityDescriptor,
  332. pSubjectContext,
  333. TRUE,
  334. AccessMask,
  335. 0,
  336. NULL,
  337. IoGetFileObjectGenericMapping(),
  338. (KPROCESSOR_MODE)((IrpSp->Flags & SL_FORCE_ACCESS_CHECK)
  339. ? UserMode
  340. : Irp->RequestorMode),
  341. &grantedAccess,
  342. Status
  343. );
  344. //
  345. // Verify consistency.
  346. //
  347. #if DBG
  348. if (accessGranted) {
  349. ASSERT (NT_SUCCESS (*Status));
  350. }
  351. else {
  352. ASSERT (!NT_SUCCESS (*Status));
  353. }
  354. #endif
  355. //
  356. // Unlock & Release security subject context
  357. //
  358. SeUnlockSubjectContext(pSubjectContext);
  359. SeReleaseSubjectContext(pSubjectContext);
  360. return accessGranted;
  361. }