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.

2761 lines
77 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. ea.c
  5. Abstract:
  6. This module implements the mini redirector call down routines pertaining to query/set ea/security.
  7. Author:
  8. joelinn [joelinn] 12-jul-95
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. //
  14. // Forward declarations.
  15. //
  16. #if defined(REMOTE_BOOT)
  17. VOID
  18. MRxSmbInitializeExtraAceArray(
  19. VOID
  20. );
  21. BOOLEAN
  22. MRxSmbAclHasExtraAces(
  23. IN PACL Acl
  24. );
  25. NTSTATUS
  26. MRxSmbRemoveExtraAcesFromSelfRelativeSD(
  27. IN PSECURITY_DESCRIPTOR OriginalSecurityDescriptor,
  28. OUT PSECURITY_DESCRIPTOR * NewSecurityDescriptor,
  29. OUT PBOOLEAN WereRemoved
  30. );
  31. NTSTATUS
  32. MRxSmbAddExtraAcesToSelfRelativeSD(
  33. IN PSECURITY_DESCRIPTOR OriginalSecurityDescriptor,
  34. IN BOOLEAN InheritableAces,
  35. OUT PSECURITY_DESCRIPTOR * NewSecurityDescriptor
  36. );
  37. NTSTATUS
  38. MRxSmbCreateExtraAcesSelfRelativeSD(
  39. IN BOOLEAN InheritableAces,
  40. OUT PSECURITY_DESCRIPTOR * NewSecurityDescriptor
  41. );
  42. NTSTATUS
  43. MRxSmbSelfRelativeToAbsoluteSD(
  44. IN PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
  45. OUT PSECURITY_DESCRIPTOR * AbsoluteSecurityDescriptor,
  46. OUT PACL * Dacl,
  47. OUT PACL * Sacl,
  48. OUT PSID * Owner,
  49. OUT PSID * Group
  50. );
  51. NTSTATUS
  52. MRxSmbAbsoluteToSelfRelativeSD(
  53. PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
  54. PSECURITY_DESCRIPTOR * SelfRelativeSecurityDescriptor
  55. );
  56. //
  57. // Definitions from ntrtl.h
  58. //
  59. NTSYSAPI
  60. NTSTATUS
  61. NTAPI
  62. RtlAbsoluteToSelfRelativeSD(
  63. PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
  64. PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
  65. PULONG BufferLength
  66. );
  67. NTSYSAPI
  68. NTSTATUS
  69. NTAPI
  70. RtlSelfRelativeToAbsoluteSD(
  71. PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
  72. PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
  73. PULONG AbsoluteSecurityDescriptorSize,
  74. PACL Dacl,
  75. PULONG DaclSize,
  76. PACL Sacl,
  77. PULONG SaclSize,
  78. PSID Owner,
  79. PULONG OwnerSize,
  80. PSID PrimaryGroup,
  81. PULONG PrimaryGroupSize
  82. );
  83. NTSYSAPI
  84. NTSTATUS
  85. NTAPI
  86. RtlAddAce (
  87. PACL Acl,
  88. ULONG AceRevision,
  89. ULONG StartingAceIndex,
  90. PVOID AceList,
  91. ULONG AceListLength
  92. );
  93. NTSYSAPI
  94. NTSTATUS
  95. NTAPI
  96. RtlDeleteAce (
  97. PACL Acl,
  98. ULONG AceIndex
  99. );
  100. NTSYSAPI
  101. NTSTATUS
  102. NTAPI
  103. RtlGetAce (
  104. PACL Acl,
  105. ULONG AceIndex,
  106. PVOID *Ace
  107. );
  108. #endif // defined(REMOTE_BOOT)
  109. #ifdef ALLOC_PRAGMA
  110. #pragma alloc_text(PAGE, MRxSmbQueryEaInformation)
  111. #pragma alloc_text(PAGE, MRxSmbSetEaInformation)
  112. #if defined(REMOTE_BOOT)
  113. #pragma alloc_text(PAGE, MRxSmbInitializeExtraAceArray)
  114. #pragma alloc_text(PAGE, MRxSmbAclHasExtraAces)
  115. #pragma alloc_text(PAGE, MRxSmbRemoveExtraAcesFromSelfRelativeSD)
  116. #pragma alloc_text(PAGE, MRxSmbAddExtraAcesToSelfRelativeSD)
  117. #pragma alloc_text(PAGE, MRxSmbSelfRelativeToAbsoluteSD)
  118. #pragma alloc_text(PAGE, MRxSmbAbsoluteToSelfRelativeSD)
  119. #endif // defined(REMOTE_BOOT)
  120. #pragma alloc_text(PAGE, MRxSmbQuerySecurityInformation)
  121. #pragma alloc_text(PAGE, MRxSmbSetSecurityInformation)
  122. #pragma alloc_text(PAGE, MRxSmbLoadEaList)
  123. #pragma alloc_text(PAGE, MRxSmbNtGeaListToOs2)
  124. #pragma alloc_text(PAGE, MRxSmbNtGetEaToOs2)
  125. #pragma alloc_text(PAGE, MRxSmbQueryEasFromServer)
  126. #pragma alloc_text(PAGE, MRxSmbNtFullEaSizeToOs2)
  127. #pragma alloc_text(PAGE, MRxSmbNtFullListToOs2)
  128. #pragma alloc_text(PAGE, MRxSmbNtFullEaToOs2)
  129. #pragma alloc_text(PAGE, MRxSmbSetEaList)
  130. #endif
  131. ////
  132. //// The Bug check file id for this module
  133. ////
  134. //
  135. //#define BugCheckFileId (RDBSS_BUG_CHECK_LOCAL_CREATE)
  136. //
  137. // The local debug trace level
  138. //
  139. #define Dbg (DEBUG_TRACE_EA)
  140. //this is the largest EAs that could ever be returned! oh my god!
  141. //this is used to simulate the nt resumable queryEA using the downlevel call
  142. //sigh!
  143. #define EA_QUERY_SIZE 0x0000ffff
  144. #if defined(REMOTE_BOOT)
  145. //
  146. // ACEs that are added to the front of server ACLs. The array is
  147. // initialized by MRxSmbInitializeExtraAceArray.
  148. //
  149. typedef struct _EXTRA_ACE_INFO {
  150. UCHAR AceType;
  151. UCHAR AceFlags;
  152. USHORT AceSize;
  153. ACCESS_MASK Mask;
  154. PVOID Sid;
  155. } EXTRA_ACE_INFO, *PEXTRA_ACE_INFO;
  156. #define EXTRA_ACE_INFO_COUNT 4
  157. EXTRA_ACE_INFO ExtraAceInfo[EXTRA_ACE_INFO_COUNT];
  158. ULONG ExtraAceInfoCount;
  159. #endif // defined(REMOTE_BOOT)
  160. //for QueryEA
  161. NTSTATUS
  162. MRxSmbLoadEaList(
  163. IN PRX_CONTEXT RxContext,
  164. IN PUCHAR UserEaList,
  165. IN ULONG UserEaListLength,
  166. OUT PFEALIST *ServerEaList
  167. );
  168. NTSTATUS
  169. MRxSmbQueryEasFromServer(
  170. IN PRX_CONTEXT RxContext,
  171. IN PFEALIST ServerEaList,
  172. IN PVOID Buffer,
  173. IN OUT PULONG BufferLengthRemaining,
  174. IN BOOLEAN ReturnSingleEntry,
  175. IN BOOLEAN UserEaListSupplied
  176. );
  177. //for SetEA
  178. NTSTATUS
  179. MRxSmbSetEaList(
  180. // IN PICB Icb,
  181. // IN PIRP Irp,
  182. IN PRX_CONTEXT RxContext,
  183. IN PFEALIST ServerEaList
  184. );
  185. VOID MRxSmbExtraEaRoutine(LONG i){
  186. RxDbgTrace( 0, Dbg, ("MRxSmbExtraEaRoutine i=%08lx\n", i ));
  187. }
  188. NTSTATUS
  189. MRxSmbQueryEaInformation (
  190. IN OUT PRX_CONTEXT RxContext
  191. )
  192. {
  193. NTSTATUS Status;
  194. RxCaptureFcb;
  195. RxCaptureFobx;
  196. PSMBCEDB_SERVER_ENTRY pServerEntry;
  197. PVOID Buffer = RxContext->Info.Buffer;
  198. PLONG pLengthRemaining = &RxContext->Info.LengthRemaining;
  199. PUCHAR UserEaList = RxContext->QueryEa.UserEaList;
  200. ULONG UserEaListLength = RxContext->QueryEa.UserEaListLength;
  201. ULONG UserEaIndex = RxContext->QueryEa.UserEaIndex;
  202. BOOLEAN RestartScan = RxContext->QueryEa.RestartScan;
  203. BOOLEAN ReturnSingleEntry = RxContext->QueryEa.ReturnSingleEntry;
  204. BOOLEAN IndexSpecified = RxContext->QueryEa.IndexSpecified;
  205. PFEALIST ServerEaList = NULL;
  206. PAGED_CODE();
  207. RxDbgTrace(+1, Dbg, ("MRxSmbQueryEaInformation\n"));
  208. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  209. //get rid of nonEA guys right now
  210. if (!FlagOn(pServerEntry->Server.DialectFlags,DF_SUPPORTEA)) {
  211. RxDbgTrace(-1, Dbg, ("EAs w/o EA support!\n"));
  212. return((STATUS_NOT_SUPPORTED));
  213. }
  214. if (MRxSmbIsThisADisconnectedOpen(capFobx->pSrvOpen)) {
  215. return STATUS_ONLY_IF_CONNECTED;
  216. }
  217. Status = MRxSmbDeferredCreate(RxContext);
  218. if (Status!=STATUS_SUCCESS) {
  219. goto FINALLY;
  220. }
  221. Status = MRxSmbLoadEaList( RxContext, UserEaList, UserEaListLength, &ServerEaList );
  222. if (( !NT_SUCCESS( Status ) )||
  223. ( ServerEaList == NULL )) {
  224. goto FINALLY;
  225. }
  226. if (IndexSpecified) {
  227. //CODE.IMPROVEMENT this name is poor....it owes back to the fastfat heritage and is not so meaningful
  228. // for a rdr
  229. capFobx->OffsetOfNextEaToReturn = UserEaIndex;
  230. Status = MRxSmbQueryEasFromServer(
  231. RxContext,
  232. ServerEaList,
  233. Buffer,
  234. pLengthRemaining,
  235. ReturnSingleEntry,
  236. (BOOLEAN)(UserEaList != NULL) );
  237. //
  238. // if there are no Ea's on the file, and the user supplied an EA
  239. // index, we want to map the error to STATUS_NONEXISTANT_EA_ENTRY.
  240. //
  241. if ( Status == STATUS_NO_EAS_ON_FILE ) {
  242. Status = STATUS_NONEXISTENT_EA_ENTRY;
  243. }
  244. } else {
  245. if ( ( RestartScan == TRUE ) || (UserEaList != NULL) ){
  246. //
  247. // Ea Indices start at 1, not 0....
  248. //
  249. capFobx->OffsetOfNextEaToReturn = 1;
  250. }
  251. Status = MRxSmbQueryEasFromServer( //it is offensive to have two identical calls but oh, well.....
  252. RxContext,
  253. ServerEaList,
  254. Buffer,
  255. pLengthRemaining,
  256. ReturnSingleEntry,
  257. (BOOLEAN)(UserEaList != NULL) );
  258. }
  259. FINALLY:
  260. if ( ServerEaList != NULL) {
  261. RxFreePool(ServerEaList);
  262. }
  263. RxDbgTrace(-1, Dbg, ("MRxSmbQueryEaInformation st=%08lx\n",Status));
  264. return Status;
  265. }
  266. NTSTATUS
  267. MRxSmbSetEaInformation (
  268. IN OUT struct _RX_CONTEXT * RxContext
  269. )
  270. {
  271. NTSTATUS Status;
  272. RxCaptureFcb; RxCaptureFobx;
  273. PSMBCEDB_SERVER_ENTRY pServerEntry;
  274. PVOID Buffer = RxContext->Info.Buffer;
  275. ULONG Length = RxContext->Info.Length;
  276. PFEALIST ServerEaList = NULL;
  277. ULONG Size;
  278. PAGED_CODE();
  279. RxDbgTrace(+1, Dbg, ("MRxSmbSetEaInformation\n"));
  280. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  281. //get rid of nonEA guys right now
  282. if (!FlagOn(pServerEntry->Server.DialectFlags,DF_SUPPORTEA)) {
  283. RxDbgTrace(-1, Dbg, ("EAs w/o EA support!\n"));
  284. return((STATUS_NOT_SUPPORTED));
  285. }
  286. if (MRxSmbIsThisADisconnectedOpen(capFobx->pSrvOpen)) {
  287. return STATUS_ONLY_IF_CONNECTED;
  288. }
  289. Status = MRxSmbDeferredCreate(RxContext);
  290. if (Status!=STATUS_SUCCESS) {
  291. goto FINALLY;
  292. }
  293. //
  294. // Convert Nt format FEALIST to OS/2 format
  295. //
  296. Size = MRxSmbNtFullEaSizeToOs2 (Buffer);
  297. if ( Size > 0x0000ffff ) {
  298. Status = STATUS_EA_TOO_LARGE;
  299. goto FINALLY;
  300. }
  301. //CODE.IMPROVEMENT since |os2eas|<=|nteas| we really don't need a maximum buffer
  302. ServerEaList = RxAllocatePool ( PagedPool, EA_QUERY_SIZE );
  303. if ( ServerEaList == NULL ) {
  304. Status = STATUS_INSUFFICIENT_RESOURCES;
  305. goto FINALLY;
  306. }
  307. MRxSmbNtFullListToOs2 ( Buffer, ServerEaList );
  308. //
  309. // Set EAs on the file/directory; if the error is EA_ERROR then SetEaList
  310. // sets iostatus.information to the offset of the offender
  311. //
  312. Status = MRxSmbSetEaList( RxContext, ServerEaList);
  313. FINALLY:
  314. if ( ServerEaList != NULL) {
  315. RxFreePool(ServerEaList);
  316. }
  317. if (Status == STATUS_SUCCESS) {
  318. // invalidate the name based file info cache since the attributes of the file on
  319. // the server have been changed
  320. MRxSmbInvalidateFileInfoCache(RxContext);
  321. // Mark FullDir Cache, weak for bdi : Current Invalidate for correctness
  322. MRxSmbInvalidateFullDirectoryCacheParent(RxContext, TRUE);
  323. SmbLog(LOG,MRxSmbInvalidateFullDirCacheFromEa,LOGNOTHING);
  324. }
  325. RxDbgTrace(-1, Dbg, ("MRxSmbSetEaInformation st=%08lx\n",Status));
  326. return Status;
  327. }
  328. #if DBG
  329. VOID
  330. MRxSmbDumpSecurityDescriptor(
  331. IN PSECURITY_DESCRIPTOR SecurityDescriptor
  332. )
  333. {
  334. PISECURITY_DESCRIPTOR sd = (PISECURITY_DESCRIPTOR)SecurityDescriptor;
  335. ULONG sdLength = RtlLengthSecurityDescriptor(sd);
  336. PACL dacl;
  337. PACCESS_ALLOWED_ACE ace;
  338. ULONG i, j;
  339. PUCHAR p;
  340. PISID sid;
  341. BOOLEAN selfRelative;
  342. selfRelative = (BOOLEAN)((sd->Control & SE_SELF_RELATIVE) != 0);
  343. DbgPrint( " SD:\n" );
  344. DbgPrint( " Revision = %x, Control = %x\n", sd->Revision, sd->Control );
  345. DbgPrint( " Owner = %x, Group = %x\n", sd->Owner, sd->Group );
  346. DbgPrint( " Sacl = %x, Dacl = %x\n", sd->Sacl, sd->Dacl );
  347. if ( (sd->Control & SE_DACL_PRESENT) != 0 ) {
  348. dacl = sd->Dacl;
  349. if ( selfRelative ) {
  350. dacl = (PACL)((PUCHAR)sd + (ULONG_PTR)dacl);
  351. }
  352. DbgPrint( " DACL:\n" );
  353. DbgPrint( " AclRevision = %x, AclSize = %x, AceCount = %x\n",
  354. dacl->AclRevision, dacl->AclSize, dacl->AceCount );
  355. ace = (PACCESS_ALLOWED_ACE)(dacl + 1);
  356. for ( i = 0; i < dacl->AceCount; i++ ) {
  357. DbgPrint( " ACE %d:\n", i );
  358. DbgPrint( " AceType = %x, AceFlags = %x, AceSize = %x\n",
  359. ace->Header.AceType, ace->Header.AceFlags, ace->Header.AceSize );
  360. if ( ace->Header.AceType < ACCESS_MAX_MS_V2_ACE_TYPE ) {
  361. DbgPrint(" Mask = %08x, Sid = ", ace->Mask );
  362. for ( j = FIELD_OFFSET(ACCESS_ALLOWED_ACE,SidStart), p = (PUCHAR)&ace->SidStart;
  363. j < ace->Header.AceSize;
  364. j++, p++ ) {
  365. DbgPrint( "%02x ", *p );
  366. }
  367. DbgPrint( "\n" );
  368. }
  369. ace = (PACCESS_ALLOWED_ACE)((PUCHAR)ace + ace->Header.AceSize );
  370. }
  371. }
  372. if ( sd->Owner != 0 ) {
  373. sid = sd->Owner;
  374. if ( selfRelative ) {
  375. sid = (PISID)((PUCHAR)sd + (ULONG_PTR)sid);
  376. }
  377. DbgPrint( " Owner SID:\n" );
  378. DbgPrint( " Revision = %x, SubAuthorityCount = %x\n",
  379. sid->Revision, sid->SubAuthorityCount );
  380. DbgPrint( " IdentifierAuthority = " );
  381. for ( j = 0; j < 6; j++ ) {
  382. DbgPrint( "%02x ", sid->IdentifierAuthority.Value[j] );
  383. }
  384. DbgPrint( "\n" );
  385. for ( i = 0; i < sid->SubAuthorityCount; i++ ) {
  386. DbgPrint(" SubAuthority %d = ", i );
  387. for ( j = 0, p = (PUCHAR)&sid->SubAuthority[i]; j < 4; j++, p++ ) {
  388. DbgPrint( "%02x ", *p );
  389. }
  390. DbgPrint( "\n" );
  391. }
  392. }
  393. }
  394. #endif
  395. #if defined(REMOTE_BOOT)
  396. VOID
  397. MRxSmbInitializeExtraAceArray(
  398. VOID
  399. )
  400. /*++
  401. Routine Description:
  402. This routine initializes the array of extra ACEs that we add to
  403. the front of ACLs for files on the server. It must be called
  404. *after* SeEnableAccessToExports has been called.
  405. Arguments:
  406. None.
  407. Return Value:
  408. None.
  409. --*/
  410. {
  411. ULONG i;
  412. PAGED_CODE();
  413. //
  414. // Our code assumes the ACEs we use have the same structure.
  415. //
  416. ASSERT(FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) ==
  417. FIELD_OFFSET(ACCESS_DENIED_ACE, SidStart));
  418. ASSERT((sizeof(ExtraAceInfo) / sizeof(EXTRA_ACE_INFO)) == EXTRA_ACE_INFO_COUNT);
  419. ExtraAceInfoCount = EXTRA_ACE_INFO_COUNT;
  420. ExtraAceInfo[0].AceType = ACCESS_ALLOWED_ACE_TYPE;
  421. ExtraAceInfo[0].AceFlags = 0;
  422. ExtraAceInfo[0].Mask = FILE_ALL_ACCESS;
  423. ExtraAceInfo[0].Sid = MRxSmbRemoteBootMachineSid;
  424. ExtraAceInfo[1].AceType = ACCESS_ALLOWED_ACE_TYPE;
  425. ExtraAceInfo[1].AceFlags = 0;
  426. ExtraAceInfo[1].Mask = FILE_ALL_ACCESS;
  427. ExtraAceInfo[1].Sid = SeExports->SeLocalSystemSid;
  428. ExtraAceInfo[2].AceType = ACCESS_ALLOWED_ACE_TYPE;
  429. ExtraAceInfo[2].AceFlags = 0;
  430. ExtraAceInfo[2].Mask = FILE_ALL_ACCESS;
  431. ExtraAceInfo[2].Sid = SeExports->SeAliasAdminsSid;
  432. ExtraAceInfo[3].AceType = ACCESS_DENIED_ACE_TYPE;
  433. ExtraAceInfo[3].AceFlags = 0;
  434. ExtraAceInfo[3].Mask = FILE_ALL_ACCESS;
  435. ExtraAceInfo[3].Sid = SeExports->SeWorldSid;
  436. for (i = 0; i < ExtraAceInfoCount; i++) {
  437. ExtraAceInfo[i].AceSize = (USHORT)(FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart) +
  438. RtlLengthSid((PSID)(ExtraAceInfo[i].Sid)));
  439. }
  440. }
  441. BOOLEAN
  442. MRxSmbAclHasExtraAces(
  443. IN PACL Acl
  444. )
  445. /*++
  446. Routine Description:
  447. This routine determines if an ACL has the special ACEs that we
  448. put on the front for remote boot server files.
  449. Arguments:
  450. Acl - The ACL to check.
  451. Return Value:
  452. TRUE if the ACEs are there, FALSE otherwise (including if there
  453. are any errors while checking).
  454. --*/
  455. {
  456. PACCESS_ALLOWED_ACE Ace;
  457. ULONG KnownSidLength;
  458. ULONG i;
  459. NTSTATUS Status;
  460. PAGED_CODE();
  461. //
  462. // Make sure the first n ACEs in this ACL match those in our
  463. // array.
  464. //
  465. for (i = 0; i < ExtraAceInfoCount; i++) {
  466. Status = RtlGetAce(Acl, i, &Ace);
  467. if (!NT_SUCCESS(Status)) {
  468. return FALSE;
  469. }
  470. KnownSidLength = ExtraAceInfo[i].AceSize - FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
  471. //
  472. // Don't compare the flags to avoid worrying about inherited
  473. // flags.
  474. //
  475. if ((Ace->Header.AceType != ExtraAceInfo[i].AceType) ||
  476. // TMP: my server doesn't store 0x200 bit // (Ace->Mask != ExtraAceInfo[i].Mask) ||
  477. (RtlLengthSid((PSID)(&Ace->SidStart)) != KnownSidLength) ||
  478. (memcmp(&Ace->SidStart, ExtraAceInfo[i].Sid, KnownSidLength) != 0)) {
  479. return FALSE;
  480. }
  481. }
  482. //
  483. // Everything matched, so it does have the extra ACEs.
  484. //
  485. return TRUE;
  486. }
  487. NTSTATUS
  488. MRxSmbSelfRelativeToAbsoluteSD(
  489. IN PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
  490. OUT PSECURITY_DESCRIPTOR * AbsoluteSecurityDescriptor,
  491. OUT PACL * Dacl,
  492. OUT PACL * Sacl,
  493. OUT PSID * Owner,
  494. OUT PSID * Group
  495. )
  496. /*++
  497. Routine Description:
  498. This routine converts a self-relative security descriptor to
  499. absolute form, allocating all the entries needed.
  500. Arguments:
  501. Return Value:
  502. Status - Result of the operation.
  503. --*/
  504. {
  505. NTSTATUS Status;
  506. ULONG AbsoluteSecurityDescriptorSize = 0;
  507. ULONG GroupSize = 0;
  508. ULONG OwnerSize = 0;
  509. ULONG SaclSize = 0;
  510. ULONG DaclSize = 0;
  511. PUCHAR AllocatedBuffer;
  512. ULONG AllocatedBufferSize;
  513. PAGED_CODE();
  514. *AbsoluteSecurityDescriptor = NULL;
  515. *Owner = NULL;
  516. *Group = NULL;
  517. *Dacl = NULL;
  518. *Sacl = NULL;
  519. //
  520. // First determine how much storage is needed by the SD.
  521. //
  522. Status = RtlSelfRelativeToAbsoluteSD(
  523. SelfRelativeSecurityDescriptor,
  524. NULL,
  525. &AbsoluteSecurityDescriptorSize,
  526. NULL,
  527. &DaclSize,
  528. NULL,
  529. &SaclSize,
  530. NULL,
  531. &OwnerSize,
  532. NULL,
  533. &GroupSize);
  534. //
  535. // We expect to get this error since at least the core of the SD
  536. // has some non-zero size.
  537. //
  538. if (Status == STATUS_BUFFER_TOO_SMALL) {
  539. AllocatedBufferSize =
  540. AbsoluteSecurityDescriptorSize +
  541. OwnerSize +
  542. GroupSize +
  543. SaclSize +
  544. DaclSize;
  545. ASSERT(AllocatedBufferSize > 0);
  546. AllocatedBuffer = RxAllocatePoolWithTag(PagedPool, AllocatedBufferSize, MRXSMB_REMOTEBOOT_POOLTAG);
  547. if (AllocatedBuffer == NULL) {
  548. return STATUS_INSUFFICIENT_RESOURCES;
  549. }
  550. //
  551. // Walk through each piece of memory we need and take a chunk
  552. // of AllocatedBuffer. The caller assumes that AbsoluteSecurityDescriptor
  553. // will be the address of the buffer they need to free, so we always
  554. // set that even if the size needed is 0 (which should never happen!).
  555. // For the others we set them if the size needed is not NULL.
  556. //
  557. ASSERT(AbsoluteSecurityDescriptorSize > 0);
  558. *AbsoluteSecurityDescriptor = (PSECURITY_DESCRIPTOR)AllocatedBuffer;
  559. AllocatedBuffer += AbsoluteSecurityDescriptorSize;
  560. if (OwnerSize > 0) {
  561. *Owner = (PSID)AllocatedBuffer;
  562. AllocatedBuffer += OwnerSize;
  563. }
  564. if (GroupSize > 0) {
  565. *Group = (PSID)AllocatedBuffer;
  566. AllocatedBuffer += GroupSize;
  567. }
  568. if (SaclSize > 0) {
  569. *Sacl = (PACL)AllocatedBuffer;
  570. AllocatedBuffer += SaclSize;
  571. }
  572. if (DaclSize > 0) {
  573. *Dacl = (PACL)AllocatedBuffer;
  574. }
  575. //
  576. // Now make the call again to really do the conversion.
  577. //
  578. Status = RtlSelfRelativeToAbsoluteSD(
  579. SelfRelativeSecurityDescriptor,
  580. *AbsoluteSecurityDescriptor,
  581. &AbsoluteSecurityDescriptorSize,
  582. *Dacl,
  583. &DaclSize,
  584. *Sacl,
  585. &SaclSize,
  586. *Owner,
  587. &OwnerSize,
  588. *Group,
  589. &GroupSize);
  590. } else {
  591. Status = STATUS_INVALID_PARAMETER;
  592. }
  593. if (!NT_SUCCESS(Status) && (*AbsoluteSecurityDescriptor != NULL)) {
  594. RxFreePool(*AbsoluteSecurityDescriptor);
  595. *AbsoluteSecurityDescriptor = NULL;
  596. }
  597. return Status;
  598. }
  599. NTSTATUS
  600. MRxSmbAbsoluteToSelfRelativeSD(
  601. PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
  602. PSECURITY_DESCRIPTOR * SelfRelativeSecurityDescriptor
  603. )
  604. /*++
  605. Routine Description:
  606. This routine converts an absolute security descriptor to
  607. self-relative form, allocating all the entries needed.
  608. Arguments:
  609. Return Value:
  610. Status - Result of the operation.
  611. --*/
  612. {
  613. NTSTATUS Status;
  614. ULONG SelfRelativeSdSize = 0;
  615. PAGED_CODE();
  616. *SelfRelativeSecurityDescriptor = NULL;
  617. Status = RtlAbsoluteToSelfRelativeSD(
  618. AbsoluteSecurityDescriptor,
  619. NULL,
  620. &SelfRelativeSdSize);
  621. ASSERT(Status == STATUS_BUFFER_TOO_SMALL);
  622. *SelfRelativeSecurityDescriptor = RxAllocatePoolWithTag(NonPagedPool, SelfRelativeSdSize, MRXSMB_REMOTEBOOT_POOLTAG);
  623. if (*SelfRelativeSecurityDescriptor == NULL) {
  624. return STATUS_INSUFFICIENT_RESOURCES;
  625. }
  626. //
  627. // Now do the real conversion.
  628. //
  629. Status = RtlAbsoluteToSelfRelativeSD(
  630. AbsoluteSecurityDescriptor,
  631. *SelfRelativeSecurityDescriptor,
  632. &SelfRelativeSdSize);
  633. if (!NT_SUCCESS(Status) && (*SelfRelativeSecurityDescriptor != NULL)) {
  634. RxFreePool(*SelfRelativeSecurityDescriptor);
  635. *SelfRelativeSecurityDescriptor = NULL;
  636. }
  637. return Status;
  638. }
  639. NTSTATUS
  640. MRxSmbRemoveExtraAcesFromSelfRelativeSD(
  641. IN PSECURITY_DESCRIPTOR OriginalSecurityDescriptor,
  642. OUT PSECURITY_DESCRIPTOR * NewSecurityDescriptor,
  643. OUT PBOOLEAN WereRemoved
  644. )
  645. /*++
  646. Routine Description:
  647. This routine takes an existing self-relative security descriptor
  648. and produces a new self-relative security descriptor with our
  649. extra ACEs removed. It returns S_FALSE if they did not need to
  650. be removed.
  651. Arguments:
  652. Return Value:
  653. Status - Result of the operation.
  654. --*/
  655. {
  656. NTSTATUS Status;
  657. PSECURITY_DESCRIPTOR AbsoluteSd = NULL;
  658. PSID Owner;
  659. PSID Group;
  660. PACL Dacl;
  661. PACL Sacl;
  662. PACL NewDacl = NULL;
  663. ULONG NewDaclSize;
  664. BOOLEAN DaclPresent, DaclDefaulted;
  665. *NewSecurityDescriptor = NULL;
  666. *WereRemoved = FALSE;
  667. //
  668. // Check if we need to strip off any ACEs in the DACL
  669. // that SetSecurityInformation may have added.
  670. //
  671. Status = RtlGetDaclSecurityDescriptor(
  672. OriginalSecurityDescriptor,
  673. &DaclPresent,
  674. &Dacl,
  675. &DaclDefaulted);
  676. if (!NT_SUCCESS(Status)) {
  677. goto CLEANUP;
  678. }
  679. if (DaclPresent &&
  680. (Dacl != NULL) &&
  681. MRxSmbAclHasExtraAces(Dacl)) {
  682. ULONG i;
  683. //
  684. // Need to strip the extra ACEs off.
  685. //
  686. // First convert the SD to absolute.
  687. //
  688. Status = MRxSmbSelfRelativeToAbsoluteSD(
  689. OriginalSecurityDescriptor,
  690. &AbsoluteSd,
  691. &Dacl,
  692. &Sacl,
  693. &Owner,
  694. &Group);
  695. if (!NT_SUCCESS(Status)) {
  696. goto CLEANUP;
  697. }
  698. //
  699. // Now modify the DACL. Each delete moves
  700. // the other ACEs down, so we just delete
  701. // ACE 0 as many times as needed.
  702. //
  703. for (i = 0; i < ExtraAceInfoCount; i++) {
  704. Status = RtlDeleteAce(
  705. Dacl,
  706. 0);
  707. if (!NT_SUCCESS(Status)) {
  708. goto CLEANUP;
  709. }
  710. }
  711. //
  712. // If the resulting Dacl has no ACEs, then remove it
  713. // since a DACL with no ACEs implies no access.
  714. //
  715. if (Dacl->AceCount == 0) {
  716. Status = RtlSetDaclSecurityDescriptor(
  717. AbsoluteSd,
  718. FALSE,
  719. NULL,
  720. FALSE);
  721. }
  722. //
  723. // Allocate and convert back to self-relative.
  724. //
  725. Status = MRxSmbAbsoluteToSelfRelativeSD(
  726. AbsoluteSd,
  727. NewSecurityDescriptor);
  728. if (!NT_SUCCESS(Status)) {
  729. goto CLEANUP;
  730. }
  731. *WereRemoved = TRUE;
  732. }
  733. CLEANUP:
  734. if (AbsoluteSd != NULL) {
  735. RxFreePool(AbsoluteSd);
  736. }
  737. if (!NT_SUCCESS(Status) && (*NewSecurityDescriptor != NULL)) {
  738. RxFreePool(*NewSecurityDescriptor);
  739. *NewSecurityDescriptor = NULL;
  740. }
  741. return Status;
  742. }
  743. NTSTATUS
  744. MRxSmbAddExtraAcesToSelfRelativeSD(
  745. IN PSECURITY_DESCRIPTOR OriginalSecurityDescriptor,
  746. IN BOOLEAN InheritableAces,
  747. OUT PSECURITY_DESCRIPTOR * NewSecurityDescriptor
  748. )
  749. /*++
  750. Routine Description:
  751. This routine takes an existing self-relative security descriptor
  752. and produces a new self-relative security descriptor with our
  753. extra ACEs added.
  754. Arguments:
  755. Return Value:
  756. Status - Result of the operation.
  757. --*/
  758. {
  759. NTSTATUS Status;
  760. PSECURITY_DESCRIPTOR AbsoluteSd = NULL;
  761. PSID Owner;
  762. PSID Group;
  763. PACL Dacl;
  764. PACL Sacl;
  765. PUCHAR NewAceList = NULL;
  766. PACL NewDacl = NULL;
  767. ULONG NewAceListSize;
  768. ULONG NewDaclSize;
  769. PACCESS_ALLOWED_ACE CurrentAce;
  770. ULONG i;
  771. *NewSecurityDescriptor = NULL;
  772. //
  773. // Allocate and convert the SD to absolute.
  774. //
  775. Status = MRxSmbSelfRelativeToAbsoluteSD(
  776. OriginalSecurityDescriptor,
  777. &AbsoluteSd,
  778. &Dacl,
  779. &Sacl,
  780. &Owner,
  781. &Group);
  782. //
  783. // If the SD is already absolute this call will have returned
  784. // STATUS_BAD_DESCRIPTOR_FORMAT -- we don't expect that.
  785. //
  786. if (!NT_SUCCESS(Status)) {
  787. goto CLEANUP;
  788. }
  789. //
  790. // The server requires that the SD we pass to it has an owner -- so
  791. // set one if there isn't one.
  792. //
  793. if (Owner == NULL) {
  794. Status = RtlSetOwnerSecurityDescriptor(
  795. AbsoluteSd,
  796. MRxSmbRemoteBootMachineSid,
  797. FALSE);
  798. if (!NT_SUCCESS(Status)) {
  799. goto CLEANUP;
  800. }
  801. }
  802. //
  803. // AbsoluteSd is now an absolute version of the passed-in
  804. // security descriptor. We replace the DACL with our
  805. // modified one.
  806. //
  807. //
  808. // First create the ACEs we want to add to the ACL.
  809. //
  810. NewAceListSize = 0;
  811. for (i = 0; i < ExtraAceInfoCount; i++) {
  812. NewAceListSize += ExtraAceInfo[i].AceSize;
  813. }
  814. NewAceList = RxAllocatePoolWithTag(PagedPool, NewAceListSize, MRXSMB_REMOTEBOOT_POOLTAG);
  815. if (NewAceList == NULL) {
  816. Status = STATUS_INSUFFICIENT_RESOURCES;
  817. goto CLEANUP;
  818. }
  819. CurrentAce = (PACCESS_ALLOWED_ACE)NewAceList;
  820. for (i = 0; i < ExtraAceInfoCount; i++) {
  821. CurrentAce->Header.AceType = ExtraAceInfo[i].AceType;
  822. CurrentAce->Header.AceFlags = ExtraAceInfo[i].AceFlags;
  823. if (InheritableAces) {
  824. CurrentAce->Header.AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
  825. }
  826. CurrentAce->Header.AceSize = ExtraAceInfo[i].AceSize;
  827. CurrentAce->Mask = ExtraAceInfo[i].Mask;
  828. RtlCopyMemory(&CurrentAce->SidStart,
  829. ExtraAceInfo[i].Sid,
  830. ExtraAceInfo[i].AceSize - FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart));
  831. CurrentAce = (PACCESS_ALLOWED_ACE)(((PUCHAR)CurrentAce) + ExtraAceInfo[i].AceSize);
  832. }
  833. //
  834. // Allocate the new DACL.
  835. //
  836. if (Dacl != NULL) {
  837. NewDaclSize = Dacl->AclSize + NewAceListSize;
  838. } else {
  839. NewDaclSize = sizeof(ACL) + NewAceListSize;
  840. }
  841. NewDacl = RxAllocatePoolWithTag(NonPagedPool, NewDaclSize, MRXSMB_REMOTEBOOT_POOLTAG);
  842. if (NewDacl == NULL) {
  843. Status = STATUS_INSUFFICIENT_RESOURCES;
  844. goto CLEANUP;
  845. }
  846. if (Dacl != NULL) {
  847. RtlCopyMemory(NewDacl, Dacl, Dacl->AclSize);
  848. NewDacl->AclSize = (USHORT)NewDaclSize;
  849. } else {
  850. Status = RtlCreateAcl(NewDacl, NewDaclSize, ACL_REVISION);
  851. if (!NT_SUCCESS(Status)) {
  852. goto CLEANUP;
  853. }
  854. }
  855. //
  856. // Put our ACEs in the front.
  857. //
  858. Status = RtlAddAce(
  859. NewDacl,
  860. ACL_REVISION,
  861. 0, // StartingAceIndex
  862. NewAceList,
  863. NewAceListSize);
  864. if (!NT_SUCCESS(Status)) {
  865. goto CLEANUP;
  866. }
  867. //
  868. // Replace the existing DACL with ours.
  869. //
  870. Status = RtlSetDaclSecurityDescriptor(
  871. AbsoluteSd,
  872. TRUE,
  873. NewDacl,
  874. FALSE);
  875. if (!NT_SUCCESS(Status)) {
  876. goto CLEANUP;
  877. }
  878. //
  879. // Allocate and convert back to self-relative.
  880. //
  881. Status = MRxSmbAbsoluteToSelfRelativeSD(
  882. AbsoluteSd,
  883. NewSecurityDescriptor);
  884. if (!NT_SUCCESS(Status)) {
  885. goto CLEANUP;
  886. }
  887. CLEANUP:
  888. //
  889. // Free the temporary things we allocated.
  890. //
  891. if (AbsoluteSd != NULL) {
  892. RxFreePool(AbsoluteSd);
  893. }
  894. if (NewAceList != NULL) {
  895. RxFreePool(NewAceList);
  896. }
  897. if (NewDacl != NULL) {
  898. RxFreePool(NewDacl);
  899. }
  900. if (!NT_SUCCESS(Status) && (*NewSecurityDescriptor != NULL)) {
  901. RxFreePool(*NewSecurityDescriptor);
  902. *NewSecurityDescriptor = NULL;
  903. }
  904. return Status;
  905. }
  906. NTSTATUS
  907. MRxSmbCreateExtraAcesSelfRelativeSD(
  908. IN BOOLEAN InheritableAces,
  909. OUT PSECURITY_DESCRIPTOR * NewSecurityDescriptor
  910. )
  911. /*++
  912. Routine Description:
  913. This routine takes an existing self-relative security descriptor
  914. and produces a new self-relative security descriptor with our
  915. extra ACEs added.
  916. Arguments:
  917. Return Value:
  918. Status - Result of the operation.
  919. --*/
  920. {
  921. NTSTATUS Status;
  922. PSECURITY_DESCRIPTOR AbsoluteSd = NULL;
  923. PUCHAR NewAceList = NULL;
  924. PACL NewDacl = NULL;
  925. ULONG NewAceListSize;
  926. ULONG NewDaclSize;
  927. PACCESS_ALLOWED_ACE CurrentAce;
  928. ULONG i;
  929. AbsoluteSd = RxAllocatePoolWithTag(PagedPool, SECURITY_DESCRIPTOR_MIN_LENGTH, MRXSMB_REMOTEBOOT_POOLTAG);
  930. if (AbsoluteSd == NULL) {
  931. Status = STATUS_INSUFFICIENT_RESOURCES;
  932. goto CLEANUP;
  933. }
  934. Status = RtlCreateSecurityDescriptor(
  935. AbsoluteSd,
  936. SECURITY_DESCRIPTOR_REVISION);
  937. if (!NT_SUCCESS(Status)) {
  938. goto CLEANUP;
  939. }
  940. //
  941. // First create the ACEs we want to add to the ACL.
  942. //
  943. NewAceListSize = 0;
  944. for (i = 0; i < ExtraAceInfoCount; i++) {
  945. NewAceListSize += ExtraAceInfo[i].AceSize;
  946. }
  947. NewAceList = RxAllocatePoolWithTag(PagedPool, NewAceListSize, MRXSMB_REMOTEBOOT_POOLTAG);
  948. if (NewAceList == NULL) {
  949. Status = STATUS_INSUFFICIENT_RESOURCES;
  950. goto CLEANUP;
  951. }
  952. CurrentAce = (PACCESS_ALLOWED_ACE)NewAceList;
  953. for (i = 0; i < ExtraAceInfoCount; i++) {
  954. CurrentAce->Header.AceType = ExtraAceInfo[i].AceType;
  955. CurrentAce->Header.AceFlags = ExtraAceInfo[i].AceFlags;
  956. if (InheritableAces) {
  957. CurrentAce->Header.AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
  958. }
  959. CurrentAce->Header.AceSize = ExtraAceInfo[i].AceSize;
  960. CurrentAce->Mask = ExtraAceInfo[i].Mask;
  961. RtlCopyMemory(&CurrentAce->SidStart,
  962. ExtraAceInfo[i].Sid,
  963. ExtraAceInfo[i].AceSize - FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart));
  964. CurrentAce = (PACCESS_ALLOWED_ACE)(((PUCHAR)CurrentAce) + ExtraAceInfo[i].AceSize);
  965. }
  966. //
  967. // Allocate the new DACL.
  968. //
  969. NewDaclSize = sizeof(ACL) + NewAceListSize;
  970. NewDacl = RxAllocatePoolWithTag(NonPagedPool, NewDaclSize, MRXSMB_REMOTEBOOT_POOLTAG);
  971. if (NewDacl == NULL) {
  972. Status = STATUS_INSUFFICIENT_RESOURCES;
  973. goto CLEANUP;
  974. }
  975. RtlCreateAcl(NewDacl, NewDaclSize, ACL_REVISION);
  976. //
  977. // Put our ACEs in the front.
  978. //
  979. Status = RtlAddAce(
  980. NewDacl,
  981. ACL_REVISION,
  982. 0, // StartingAceIndex
  983. NewAceList,
  984. NewAceListSize);
  985. if (!NT_SUCCESS(Status)) {
  986. goto CLEANUP;
  987. }
  988. //
  989. // Set the DACL on the SD.
  990. //
  991. Status = RtlSetDaclSecurityDescriptor(
  992. AbsoluteSd,
  993. TRUE,
  994. NewDacl,
  995. FALSE);
  996. if (!NT_SUCCESS(Status)) {
  997. goto CLEANUP;
  998. }
  999. //
  1000. // Set the owner on the SD.
  1001. //
  1002. Status = RtlSetOwnerSecurityDescriptor(
  1003. AbsoluteSd,
  1004. MRxSmbRemoteBootMachineSid,
  1005. FALSE);
  1006. if (!NT_SUCCESS(Status)) {
  1007. goto CLEANUP;
  1008. }
  1009. //
  1010. // Allocate and convert back to self-relative.
  1011. //
  1012. Status = MRxSmbAbsoluteToSelfRelativeSD(
  1013. AbsoluteSd,
  1014. NewSecurityDescriptor);
  1015. if (!NT_SUCCESS(Status)) {
  1016. goto CLEANUP;
  1017. }
  1018. CLEANUP:
  1019. if (AbsoluteSd != NULL) {
  1020. RxFreePool(AbsoluteSd);
  1021. }
  1022. if (NewAceList != NULL) {
  1023. RxFreePool(NewAceList);
  1024. }
  1025. if (NewDacl != NULL) {
  1026. RxFreePool(NewDacl);
  1027. }
  1028. if (!NT_SUCCESS(Status) && (*NewSecurityDescriptor != NULL)) {
  1029. RxFreePool(*NewSecurityDescriptor);
  1030. *NewSecurityDescriptor = NULL;
  1031. }
  1032. return Status;
  1033. }
  1034. #endif // defined(REMOTE_BOOT)
  1035. NTSTATUS
  1036. MRxSmbQuerySecurityInformation (
  1037. IN OUT PRX_CONTEXT RxContext
  1038. )
  1039. /*++
  1040. Routine Description:
  1041. This routine implements the NtQuerySecurityFile api.
  1042. Arguments:
  1043. Return Value:
  1044. Status - Result of the operation.
  1045. --*/
  1046. {
  1047. RxCaptureFcb;
  1048. RxCaptureFobx;
  1049. PVOID Buffer = RxContext->Info.Buffer;
  1050. PLONG pLengthRemaining = &RxContext->Info.LengthRemaining;
  1051. PMRX_SMB_SRV_OPEN smbSrvOpen;
  1052. PSMBCEDB_SERVER_ENTRY pServerEntry;
  1053. #if defined(REMOTE_BOOT)
  1054. PSECURITY_DESCRIPTOR SelfRelativeSd;
  1055. BOOLEAN ConvertedAcl = FALSE;
  1056. #endif // defined(REMOTE_BOOT)
  1057. NTSTATUS Status;
  1058. REQ_QUERY_SECURITY_DESCRIPTOR QuerySecurityRequest;
  1059. RESP_QUERY_SECURITY_DESCRIPTOR QuerySecurityResponse;
  1060. PBYTE pInputParamBuffer = NULL;
  1061. PBYTE pOutputParamBuffer = NULL;
  1062. PBYTE pInputDataBuffer = NULL;
  1063. PBYTE pOutputDataBuffer = NULL;
  1064. ULONG InputParamBufferLength = 0;
  1065. ULONG OutputParamBufferLength = 0;
  1066. ULONG InputDataBufferLength = 0;
  1067. ULONG OutputDataBufferLength = 0;
  1068. PAGED_CODE();
  1069. RxDbgTrace(+1, Dbg, ("MRxSmbQuerySecurityInformation...\n"));
  1070. //Moved this check above the check for server dialect
  1071. //Changed the error code to STATUS_INVALID_DEVICE_REQUEST - navjotv
  1072. if (MRxSmbIsThisADisconnectedOpen(capFobx->pSrvOpen)) {
  1073. return STATUS_INVALID_DEVICE_REQUEST;
  1074. }
  1075. // Turn away this call from those servers which do not support the NT SMBs
  1076. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  1077. if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS)) {
  1078. RxDbgTrace(-1, Dbg, ("QuerySecurityDescriptor not supported!\n"));
  1079. return((STATUS_NOT_SUPPORTED));
  1080. }
  1081. Status = MRxSmbDeferredCreate(RxContext);
  1082. if (Status!=STATUS_SUCCESS) {
  1083. goto FINALLY;
  1084. }
  1085. Status = STATUS_MORE_PROCESSING_REQUIRED;
  1086. smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  1087. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  1088. SMB_TRANSACTION_OPTIONS TransactionOptions = RxDefaultTransactionOptions;
  1089. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  1090. //BOOLEAN printflag;
  1091. TransactionOptions.NtTransactFunction = NT_TRANSACT_QUERY_SECURITY_DESC;
  1092. //TransactionOptions.Flags |= SMB_XACT_FLAGS_COPY_ON_ERROR;
  1093. QuerySecurityRequest.Fid = smbSrvOpen->Fid;
  1094. QuerySecurityRequest.Reserved = 0;
  1095. QuerySecurityRequest.SecurityInformation = RxContext->QuerySecurity.SecurityInformation;
  1096. QuerySecurityResponse.LengthNeeded = 0xbaadbaad;
  1097. //printflag = RxDbgTraceDisableGlobally();//this is debug code anyway!
  1098. //RxDbgTraceEnableGlobally(FALSE);
  1099. Status = SmbCeTransact(
  1100. RxContext, // the RXContext for the transaction
  1101. &TransactionOptions, // transaction options
  1102. NULL, // the setup buffer
  1103. 0, // input setup buffer length
  1104. NULL, // output setup buffer
  1105. 0, // output setup buffer length
  1106. &QuerySecurityRequest, // Input Param Buffer
  1107. sizeof(QuerySecurityRequest), // Input param buffer length
  1108. &QuerySecurityResponse, // Output param buffer
  1109. sizeof(QuerySecurityResponse),// output param buffer length
  1110. NULL, // Input data buffer
  1111. 0, // Input data buffer length
  1112. Buffer, // output data buffer
  1113. *pLengthRemaining, // output data buffer length
  1114. &ResumptionContext // the resumption context
  1115. );
  1116. //DbgPrint("QSR.len=%x\n", QuerySecurityResponse.LengthNeeded);
  1117. if (NT_SUCCESS(Status) || (Status == STATUS_BUFFER_TOO_SMALL)) {
  1118. ULONG ReturnedDataCount = ResumptionContext.DataBytesReceived;
  1119. RxContext->InformationToReturn = QuerySecurityResponse.LengthNeeded;
  1120. RxDbgTrace(0, Dbg, ("MRxSmbQuerySecurityInformation...ReturnedDataCount=%08lx\n",ReturnedDataCount));
  1121. ASSERT(ResumptionContext.ParameterBytesReceived == sizeof(RESP_QUERY_SECURITY_DESCRIPTOR));
  1122. if (((LONG)(QuerySecurityResponse.LengthNeeded)) > *pLengthRemaining) {
  1123. Status = STATUS_BUFFER_OVERFLOW;
  1124. }
  1125. #if defined(REMOTE_BOOT)
  1126. if (MRxSmbBootedRemotely &&
  1127. MRxSmbRemoteBootDoMachineLogon) {
  1128. PSMBCE_SESSION pSession;
  1129. pSession = &SmbCeGetAssociatedVNetRootContext(
  1130. capFobx->pSrvOpen->pVNetRoot)->pSessionEntry->Session;
  1131. if (FlagOn(pSession->Flags,SMBCE_SESSION_FLAGS_REMOTE_BOOT_SESSION)) {
  1132. //
  1133. // if the user supplied a zero-length buffer, I.e. they were querying
  1134. // to see how big a buffer was needed, they will wind up with less
  1135. // data than expected because on the subsequent call with a real buffer,
  1136. // we may remove the extra ACEs.
  1137. //
  1138. if (NT_SUCCESS(Status) && (Buffer != NULL) && (ReturnedDataCount > 0)) {
  1139. BOOLEAN DaclPresent, DaclDefaulted;
  1140. // DbgPrint( ">>> Querying SD on %wZ\n", &capFcb->AlreadyPrefixedName);
  1141. //
  1142. // Remove any any ACEs in the DACL
  1143. // that SetSecurityInformation may have added.
  1144. //
  1145. Status = MRxSmbRemoveExtraAcesFromSelfRelativeSD(
  1146. (PSECURITY_DESCRIPTOR)Buffer,
  1147. &SelfRelativeSd,
  1148. &ConvertedAcl);
  1149. if (!NT_SUCCESS(Status)) {
  1150. goto FINALLY;
  1151. }
  1152. if (ConvertedAcl) {
  1153. //
  1154. // Copy the new security descriptor and
  1155. // modify the data length.
  1156. //
  1157. RtlCopyMemory(
  1158. Buffer,
  1159. SelfRelativeSd,
  1160. RtlLengthSecurityDescriptor(SelfRelativeSd));
  1161. }
  1162. }
  1163. }
  1164. }
  1165. #endif // defined(REMOTE_BOOT)
  1166. }
  1167. //RxDbgTraceEnableGlobally(printflag);
  1168. }
  1169. FINALLY:
  1170. #if defined(REMOTE_BOOT)
  1171. //
  1172. // If we modified the security descriptor for a remote boot server,
  1173. // clean it up.
  1174. //
  1175. if (ConvertedAcl) {
  1176. //
  1177. // Free the self-relative SD that was allocated.
  1178. //
  1179. if (SelfRelativeSd != NULL) {
  1180. RxFreePool(SelfRelativeSd);
  1181. }
  1182. }
  1183. #endif // defined(REMOTE_BOOT)
  1184. RxDbgTrace(-1, Dbg, ("MRxSmbQuerySecurityInformation...exit, st=%08lx,info=%08lx\n",
  1185. Status, RxContext->InformationToReturn));
  1186. return Status;
  1187. }
  1188. NTSTATUS
  1189. MRxSmbSetSecurityInformation (
  1190. IN OUT struct _RX_CONTEXT * RxContext
  1191. )
  1192. {
  1193. RxCaptureFcb;
  1194. RxCaptureFobx;
  1195. PMRX_SMB_SRV_OPEN smbSrvOpen;
  1196. PSMBCEDB_SERVER_ENTRY pServerEntry;
  1197. NTSTATUS Status;
  1198. REQ_SET_SECURITY_DESCRIPTOR SetSecurityRequest;
  1199. #if defined(REMOTE_BOOT)
  1200. PSECURITY_DESCRIPTOR OriginalSd;
  1201. PSECURITY_DESCRIPTOR SelfRelativeSd;
  1202. BOOLEAN DidRemoteBootProcessing = FALSE;
  1203. #endif // defined(REMOTE_BOOT)
  1204. PAGED_CODE();
  1205. RxDbgTrace(+1, Dbg, ("MRxSmbSetSecurityInformation...\n"));
  1206. pServerEntry = SmbCeGetAssociatedServerEntry(capFcb->pNetRoot->pSrvCall);
  1207. if (!FlagOn(pServerEntry->Server.DialectFlags,DF_NT_SMBS)) {
  1208. RxDbgTrace(-1, Dbg, ("Set Security Descriptor not supported!\n"));
  1209. return((STATUS_NOT_SUPPORTED));
  1210. } else if (MRxSmbIsThisADisconnectedOpen(capFobx->pSrvOpen)) {
  1211. return STATUS_ONLY_IF_CONNECTED;
  1212. #if defined(REMOTE_BOOT)
  1213. } else if (MRxSmbBootedRemotely) {
  1214. PSMBCE_SESSION pSession;
  1215. pSession = &SmbCeGetAssociatedVNetRootContext(
  1216. capFobx->pSrvOpen->pVNetRoot)->pSessionEntry->Session;
  1217. if (FlagOn(pSession->Flags,SMBCE_SESSION_FLAGS_REMOTE_BOOT_SESSION)) {
  1218. TYPE_OF_OPEN TypeOfOpen = NodeType(capFcb);
  1219. //
  1220. // Set this so we know to call the CSC epilogue, and can clean
  1221. // up correctly.
  1222. //
  1223. DidRemoteBootProcessing = TRUE;
  1224. SelfRelativeSd = NULL;
  1225. // DbgPrint( ">>> setting SD on %wZ\n", &capFcb->AlreadyPrefixedName);
  1226. //
  1227. // First we need to set the security descriptor on the CSC
  1228. // version of the file, if one exists.
  1229. //
  1230. Status = MRxSmbCscSetSecurityPrologue(RxContext);
  1231. if (Status != STATUS_SUCCESS) {
  1232. goto FINALLY;
  1233. }
  1234. if (MRxSmbRemoteBootDoMachineLogon) {
  1235. //
  1236. // Add our ACEs to the security descriptor. This returns the
  1237. // new security descriptor in SelfRelativeSd. If this is a
  1238. // directory we add inheritable ACEs.
  1239. //
  1240. Status = MRxSmbAddExtraAcesToSelfRelativeSD(
  1241. RxContext->SetSecurity.SecurityDescriptor,
  1242. (BOOLEAN)(TypeOfOpen == RDBSS_NTC_STORAGE_TYPE_DIRECTORY),
  1243. &SelfRelativeSd);
  1244. if (!NT_SUCCESS(Status)) {
  1245. goto FINALLY;
  1246. }
  1247. //
  1248. // Now replace the original SD with the new one.
  1249. //
  1250. OriginalSd = RxContext->SetSecurity.SecurityDescriptor;
  1251. RxContext->SetSecurity.SecurityDescriptor = SelfRelativeSd;
  1252. } else {
  1253. //
  1254. // If we logged on using the NULL session, then don't set ACLs
  1255. // on the server file. Jump to the end so that the CSC epilogue
  1256. // is called.
  1257. //
  1258. Status = STATUS_SUCCESS;
  1259. goto FINALLY;
  1260. }
  1261. }
  1262. #endif // defined(REMOTE_BOOT)
  1263. }
  1264. Status = MRxSmbDeferredCreate(RxContext);
  1265. if (Status!=STATUS_SUCCESS) {
  1266. goto FINALLY;
  1267. }
  1268. Status = STATUS_MORE_PROCESSING_REQUIRED;
  1269. smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  1270. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  1271. SMB_TRANSACTION_OPTIONS TransactionOptions = RxDefaultTransactionOptions;
  1272. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  1273. ULONG SdLength = RtlLengthSecurityDescriptor(RxContext->SetSecurity.SecurityDescriptor);
  1274. TransactionOptions.NtTransactFunction = NT_TRANSACT_SET_SECURITY_DESC;
  1275. SetSecurityRequest.Fid = smbSrvOpen->Fid;
  1276. SetSecurityRequest.Reserved = 0;
  1277. SetSecurityRequest.SecurityInformation = RxContext->SetSecurity.SecurityInformation;
  1278. Status = SmbCeTransact(
  1279. RxContext, // the RXContext for the transaction
  1280. &TransactionOptions, // transaction options
  1281. NULL, // the input setup buffer
  1282. 0, // input setup buffer length
  1283. NULL, // the output setup buffer
  1284. 0, // output setup buffer length
  1285. &SetSecurityRequest, // Input Param Buffer
  1286. sizeof(SetSecurityRequest), // Input param buffer length
  1287. NULL, // Output param buffer
  1288. 0, // output param buffer length
  1289. RxContext->SetSecurity.SecurityDescriptor, // Input data buffer
  1290. SdLength, // Input data buffer length
  1291. NULL, // output data buffer
  1292. 0, // output data buffer length
  1293. &ResumptionContext // the resumption context
  1294. );
  1295. //the old rdr doesn't return any info...................
  1296. //RxContext->InformationToReturn = SetSecurityResponse.LengthNeeded;
  1297. if ( NT_SUCCESS(Status) ) {
  1298. ULONG ReturnedDataCount = ResumptionContext.DataBytesReceived;
  1299. RxDbgTrace(0, Dbg, ("MRxSmbSetSecurityInformation...ReturnedDataCount=%08lx\n",ReturnedDataCount));
  1300. ASSERT(ResumptionContext.ParameterBytesReceived == 0);
  1301. ASSERT(ResumptionContext.SetupBytesReceived == 0);
  1302. ASSERT(ResumptionContext.DataBytesReceived == 0);
  1303. }
  1304. }
  1305. FINALLY:
  1306. #if defined(REMOTE_BOOT)
  1307. //
  1308. // If we modified the security descriptor for a remote boot server,
  1309. // clean it up.
  1310. //
  1311. if (DidRemoteBootProcessing) {
  1312. if (SelfRelativeSd != NULL) {
  1313. RxFreePool(SelfRelativeSd);
  1314. //
  1315. // If we successfully allocated SelfRelativeSd then we
  1316. // also replaced the original passed-in SD, so we need
  1317. // to put the old SD back.
  1318. //
  1319. RxContext->SetSecurity.SecurityDescriptor = OriginalSd;
  1320. }
  1321. MRxSmbCscSetSecurityEpilogue(RxContext, &Status);
  1322. }
  1323. #endif // defined(REMOTE_BOOT)
  1324. RxDbgTrace(-1, Dbg, ("MRxSmbSetSecurityInformation...exit, st=%08lx,info=%08lx\n",
  1325. Status, RxContext->InformationToReturn));
  1326. return Status;
  1327. }
  1328. NTSTATUS
  1329. MRxSmbLoadEaList(
  1330. IN PRX_CONTEXT RxContext,
  1331. IN PUCHAR UserEaList,
  1332. IN ULONG UserEaListLength,
  1333. OUT PFEALIST *ServerEaList
  1334. )
  1335. /*++
  1336. Routine Description:
  1337. This routine implements the NtQueryEaFile api.
  1338. It returns the following information:
  1339. Arguments:
  1340. IN PUCHAR UserEaList; - Supplies the Ea names required.
  1341. IN ULONG UserEaListLength;
  1342. OUT PFEALIST *ServerEaList - Eas returned by the server. Caller is responsible for
  1343. freeing memory.
  1344. Return Value:
  1345. Status - Result of the operation.
  1346. --*/
  1347. {
  1348. RxCaptureFobx;
  1349. PMRX_SMB_SRV_OPEN smbSrvOpen;
  1350. NTSTATUS Status;
  1351. USHORT Setup = TRANS2_QUERY_FILE_INFORMATION;
  1352. REQ_QUERY_FILE_INFORMATION QueryFileInfoRequest;
  1353. RESP_QUERY_FILE_INFORMATION QueryFileInfoResponse;
  1354. PBYTE pInputParamBuffer = NULL;
  1355. PBYTE pOutputParamBuffer = NULL;
  1356. PBYTE pInputDataBuffer = NULL;
  1357. PBYTE pOutputDataBuffer = NULL;
  1358. ULONG InputParamBufferLength = 0;
  1359. ULONG OutputParamBufferLength = 0;
  1360. ULONG InputDataBufferLength = 0;
  1361. ULONG OutputDataBufferLength = 0;
  1362. CLONG OutDataCount = EA_QUERY_SIZE;
  1363. CLONG OutSetupCount = 0;
  1364. PFEALIST Buffer;
  1365. PGEALIST ServerQueryEaList = NULL;
  1366. CLONG InDataCount;
  1367. PAGED_CODE();
  1368. RxDbgTrace(+1, Dbg, ("MRxSmbLoadEaList...\n"));
  1369. Status = STATUS_MORE_PROCESSING_REQUIRED;
  1370. smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  1371. //
  1372. // Convert the supplied UserEaList to a GEALIST. The server will return just the Eas
  1373. // requested by the application.
  1374. //
  1375. //
  1376. // If the application specified a subset of EaNames then convert to OS/2 1.2 format and
  1377. // pass that to the server. ie. Use the server to filter out the names.
  1378. //
  1379. //CODE.IMPROVEMENT if write-cacheing is enabled, then we could find out the size once and save it. in
  1380. // this way we would at least avoid this everytime. the best way would be an NT-->NT api that
  1381. // implements this in a reasonable fashion. (we can only do the above optimization if it's a full
  1382. // query instead of a ealist!=NULL query.
  1383. Buffer = RxAllocatePool ( PagedPool, OutDataCount );
  1384. if ( Buffer == NULL ) {
  1385. Status = STATUS_INSUFFICIENT_RESOURCES;
  1386. goto FINALLY;
  1387. }
  1388. if ( UserEaList != NULL) {
  1389. //
  1390. // OS/2 format is always a little less than or equal to the NT UserEaList size.
  1391. // This code relies on the I/O system verifying the EaList is valid.
  1392. //
  1393. ServerQueryEaList = RxAllocatePool ( PagedPool, UserEaListLength );
  1394. if ( ServerQueryEaList == NULL ) {
  1395. Status = STATUS_INSUFFICIENT_RESOURCES;
  1396. goto FINALLY;
  1397. };
  1398. MRxSmbNtGeaListToOs2((PFILE_GET_EA_INFORMATION )UserEaList, UserEaListLength, ServerQueryEaList );
  1399. InDataCount = (CLONG)ServerQueryEaList->cbList;
  1400. } else {
  1401. InDataCount = 0;
  1402. }
  1403. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  1404. PSMB_TRANSACTION_OPTIONS pTransactionOptions = &RxDefaultTransactionOptions;
  1405. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  1406. QueryFileInfoRequest.Fid = smbSrvOpen->Fid;
  1407. if ( UserEaList != NULL) {
  1408. QueryFileInfoRequest.InformationLevel = SMB_INFO_QUERY_EAS_FROM_LIST;
  1409. } else {
  1410. QueryFileInfoRequest.InformationLevel = SMB_INFO_QUERY_ALL_EAS;
  1411. }
  1412. // CODE.IMPROVEMENT it is unfortunate that this is defined so that a paramMDL cannot be passed
  1413. // perhaps it should be passed in the options!
  1414. Status = SmbCeTransact(
  1415. RxContext, // the RXContext for the transaction
  1416. pTransactionOptions, // transaction options
  1417. &Setup, // the setup buffer
  1418. sizeof(Setup), // setup buffer length
  1419. NULL, // the output setup buffer
  1420. 0, // output setup buffer length
  1421. &QueryFileInfoRequest, // Input Param Buffer
  1422. sizeof(QueryFileInfoRequest), // Input param buffer length
  1423. &QueryFileInfoResponse, // Output param buffer
  1424. sizeof(QueryFileInfoResponse),// output param buffer length
  1425. ServerQueryEaList, // Input data buffer
  1426. InDataCount, // Input data buffer length
  1427. Buffer, // output data buffer
  1428. OutDataCount, // output data buffer length
  1429. &ResumptionContext // the resumption context
  1430. );
  1431. if ( NT_SUCCESS(Status) ) {
  1432. ULONG ReturnedDataCount = ResumptionContext.DataBytesReceived;
  1433. RxDbgTrace(0, Dbg, ("MRxSmbLoadEaList...ReturnedDataCount=%08lx\n",ReturnedDataCount));
  1434. ASSERT(ResumptionContext.ParameterBytesReceived == sizeof(RESP_QUERY_FILE_INFORMATION));
  1435. if ( SmbGetUlong( &((PFEALIST)Buffer)->cbList) != ReturnedDataCount ){
  1436. Status = STATUS_EA_CORRUPT_ERROR;
  1437. }
  1438. if ( ReturnedDataCount == 0 ) {
  1439. Status = STATUS_NO_EAS_ON_FILE;
  1440. }
  1441. }
  1442. }
  1443. FINALLY:
  1444. if ( NT_SUCCESS(Status) ) {
  1445. *ServerEaList = Buffer;
  1446. } else {
  1447. if (Buffer != NULL) {
  1448. RxFreePool(Buffer);
  1449. }
  1450. }
  1451. if ( ServerQueryEaList != NULL) {
  1452. RxFreePool(ServerQueryEaList);
  1453. }
  1454. RxDbgTrace(-1, Dbg, ("MRxSmbLoadEaList...exit, st=%08lx\n",Status));
  1455. return Status;
  1456. }
  1457. VOID
  1458. MRxSmbNtGeaListToOs2 (
  1459. IN PFILE_GET_EA_INFORMATION NtGetEaList,
  1460. IN ULONG GeaListLength,
  1461. IN PGEALIST GeaList
  1462. )
  1463. /*++
  1464. Routine Description:
  1465. Converts a single NT GET EA list to OS/2 GEALIST style. The GEALIST
  1466. need not have any particular alignment.
  1467. Arguments:
  1468. NtGetEaList - An NT style get EA list to be converted to OS/2 format.
  1469. GeaListLength - the maximum possible length of the GeaList.
  1470. GeaList - Where to place the OS/2 1.2 style GEALIST.
  1471. Return Value:
  1472. none.
  1473. --*/
  1474. {
  1475. PGEA gea = GeaList->list;
  1476. PFILE_GET_EA_INFORMATION ntGetEa = NtGetEaList;
  1477. PAGED_CODE();
  1478. //
  1479. // Copy the Eas up until the last one
  1480. //
  1481. while ( ntGetEa->NextEntryOffset != 0 ) {
  1482. //
  1483. // Copy the NT format EA to OS/2 1.2 format and set the gea
  1484. // pointer for the next iteration.
  1485. //
  1486. gea = MRxSmbNtGetEaToOs2( gea, ntGetEa );
  1487. ASSERT( (ULONG_PTR)gea <= (ULONG_PTR)GeaList + GeaListLength );
  1488. ntGetEa = (PFILE_GET_EA_INFORMATION)((PCHAR)ntGetEa + ntGetEa->NextEntryOffset);
  1489. }
  1490. // Now copy the last entry.
  1491. gea = MRxSmbNtGetEaToOs2( gea, ntGetEa );
  1492. ASSERT( (ULONG_PTR)gea <= (ULONG_PTR)GeaList + GeaListLength );
  1493. //
  1494. // Set the number of bytes in the GEALIST.
  1495. //
  1496. SmbPutUlong(
  1497. &GeaList->cbList,
  1498. (ULONG)((PCHAR)gea - (PCHAR)GeaList)
  1499. );
  1500. UNREFERENCED_PARAMETER( GeaListLength );
  1501. }
  1502. PGEA
  1503. MRxSmbNtGetEaToOs2 (
  1504. OUT PGEA Gea,
  1505. IN PFILE_GET_EA_INFORMATION NtGetEa
  1506. )
  1507. /*++
  1508. Routine Description:
  1509. Converts a single NT Get EA entry to OS/2 GEA style. The GEA need not have
  1510. any particular alignment. This routine makes no checks on buffer
  1511. overrunning--this is the responsibility of the calling routine.
  1512. Arguments:
  1513. Gea - a pointer to the location where the OS/2 GEA is to be written.
  1514. NtGetEa - a pointer to the NT Get EA.
  1515. Return Value:
  1516. A pointer to the location after the last byte written.
  1517. --*/
  1518. {
  1519. PCHAR ptr;
  1520. PAGED_CODE();
  1521. Gea->cbName = NtGetEa->EaNameLength;
  1522. ptr = (PCHAR)(Gea) + 1;
  1523. RtlCopyMemory( ptr, NtGetEa->EaName, NtGetEa->EaNameLength );
  1524. ptr += NtGetEa->EaNameLength;
  1525. *ptr++ = '\0';
  1526. return ( (PGEA)ptr );
  1527. }
  1528. NTSTATUS
  1529. MRxSmbQueryEasFromServer(
  1530. IN PRX_CONTEXT RxContext,
  1531. IN PFEALIST ServerEaList,
  1532. IN PVOID Buffer,
  1533. IN OUT PULONG BufferLengthRemaining,
  1534. IN BOOLEAN ReturnSingleEntry,
  1535. IN BOOLEAN UserEaListSupplied
  1536. )
  1537. /*++
  1538. Routine Description:
  1539. This routine copies the required number of Eas from the ServerEaList
  1540. starting from the offset indicated in the Icb. The Icb is also updated
  1541. to show the last Ea returned.
  1542. Arguments:
  1543. IN PFEALIST ServerEaList - Supplies the Ea List in OS/2 format.
  1544. IN PVOID Buffer - Supplies where to put the NT format EAs
  1545. IN OUT PULONG BufferLengthRemaining - Supplies the user buffer space.
  1546. IN BOOLEAN ReturnSingleEntry
  1547. IN BOOLEAN UserEaListSupplied - ServerEaList is a subset of the Eas
  1548. Return Value:
  1549. NTSTATUS - The status for the Irp.
  1550. --*/
  1551. {
  1552. RxCaptureFobx;
  1553. ULONG EaIndex = capFobx->OffsetOfNextEaToReturn;
  1554. ULONG Index = 1;
  1555. ULONG Size;
  1556. ULONG OriginalLengthRemaining = *BufferLengthRemaining;
  1557. BOOLEAN Overflow = FALSE;
  1558. PFEA LastFeaStartLocation;
  1559. PFEA Fea = NULL;
  1560. PFEA LastFea = NULL;
  1561. PFILE_FULL_EA_INFORMATION NtFullEa = Buffer;
  1562. PFILE_FULL_EA_INFORMATION LastNtFullEa = Buffer;
  1563. PAGED_CODE();
  1564. RxDbgTrace(0, Dbg, ("MRxSmbQueryEasFromServer...EaIndex/Buffer/Remaining=%08lx/%08lx/%08lx\n",
  1565. EaIndex,Buffer,((BufferLengthRemaining)?*BufferLengthRemaining:0xbadbad)
  1566. ));
  1567. //
  1568. // If there are no Ea's present in the list, return the appropriate
  1569. // error.
  1570. //
  1571. // Os/2 servers indicate that a list is null if cbList==4.
  1572. //
  1573. if ( SmbGetUlong(&ServerEaList->cbList) == FIELD_OFFSET(FEALIST, list) ) {
  1574. return STATUS_NO_EAS_ON_FILE;
  1575. }
  1576. if (SmbGetUlong(&ServerEaList->cbList) > EA_QUERY_SIZE) {
  1577. return STATUS_INVALID_NETWORK_RESPONSE;
  1578. }
  1579. //
  1580. // Find the last location at which an FEA can start.
  1581. //
  1582. LastFeaStartLocation = (PFEA)( (PCHAR)ServerEaList +
  1583. SmbGetUlong( &ServerEaList->cbList ) -
  1584. sizeof(FEA) - 1 );
  1585. //
  1586. // Go through the ServerEaList until we find the entry corresponding to EaIndex
  1587. //
  1588. for ( Fea = ServerEaList->list;
  1589. (Fea <= LastFeaStartLocation) && (Index < EaIndex);
  1590. Index+= 1,
  1591. Fea = (PFEA)( (PCHAR)Fea + sizeof(FEA) +
  1592. Fea->cbName + 1 + SmbGetUshort( &Fea->cbValue ) ) ) {
  1593. NOTHING;
  1594. }
  1595. if ( Index != EaIndex ) {
  1596. if ( Index == EaIndex+1 ) {
  1597. return STATUS_NO_MORE_EAS;
  1598. }
  1599. //
  1600. // No such index
  1601. //
  1602. return STATUS_NONEXISTENT_EA_ENTRY;
  1603. }
  1604. //
  1605. // Go through the rest of the FEA list, converting from OS/2 1.2 format to NT
  1606. // until we pass the last possible location in which an FEA can start.
  1607. //
  1608. for ( ;
  1609. Fea <= LastFeaStartLocation;
  1610. Fea = (PFEA)( (PCHAR)Fea + sizeof(FEA) +
  1611. Fea->cbName + 1 + SmbGetUshort( &Fea->cbValue ) ) ) {
  1612. PCHAR ptr;
  1613. //
  1614. // Calculate the size of this Fea when converted to an NT EA structure.
  1615. //
  1616. // The last field shouldn't be padded.
  1617. //
  1618. if ((PFEA)((PCHAR)Fea+sizeof(FEA)+Fea->cbName+1+SmbGetUshort(&Fea->cbValue)) < LastFeaStartLocation) {
  1619. Size = SmbGetNtSizeOfFea( Fea );
  1620. } else {
  1621. Size = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) +
  1622. Fea->cbName + 1 + SmbGetUshort(&Fea->cbValue);
  1623. }
  1624. //
  1625. // Will the next Ea fit?
  1626. //
  1627. if ( *BufferLengthRemaining < Size ) {
  1628. if ( LastNtFullEa != NtFullEa ) {
  1629. if ( UserEaListSupplied == TRUE ) {
  1630. *BufferLengthRemaining = OriginalLengthRemaining;
  1631. return STATUS_BUFFER_OVERFLOW;
  1632. }
  1633. Overflow = TRUE;
  1634. break;
  1635. } else {
  1636. // Not even room for a single EA!
  1637. return STATUS_BUFFER_OVERFLOW;
  1638. }
  1639. } else {
  1640. *BufferLengthRemaining -= Size;
  1641. }
  1642. //
  1643. // We are comitted to copy the Os2 Fea to Nt format in the users buffer
  1644. //
  1645. LastNtFullEa = NtFullEa;
  1646. LastFea = Fea;
  1647. EaIndex++;
  1648. // Create new Nt Ea
  1649. NtFullEa->Flags = Fea->fEA;
  1650. NtFullEa->EaNameLength = Fea->cbName;
  1651. NtFullEa->EaValueLength = SmbGetUshort( &Fea->cbValue );
  1652. if ((PCHAR)(Fea+1)+NtFullEa->EaNameLength - (PCHAR)ServerEaList > EA_QUERY_SIZE) {
  1653. return STATUS_EA_CORRUPT_ERROR;
  1654. }
  1655. if ((PCHAR)(Fea+1)+NtFullEa->EaNameLength+NtFullEa->EaValueLength - (PCHAR)ServerEaList > EA_QUERY_SIZE) {
  1656. return STATUS_EA_CORRUPT_ERROR;
  1657. }
  1658. ptr = NtFullEa->EaName;
  1659. RtlCopyMemory( ptr, (PCHAR)(Fea+1), Fea->cbName );
  1660. ptr += NtFullEa->EaNameLength;
  1661. *ptr++ = '\0';
  1662. //
  1663. // Copy the EA value to the NT full EA.
  1664. //
  1665. RtlCopyMemory(
  1666. ptr,
  1667. (PCHAR)(Fea+1) + NtFullEa->EaNameLength + 1,
  1668. NtFullEa->EaValueLength
  1669. );
  1670. ptr += NtFullEa->EaValueLength;
  1671. //
  1672. // Longword-align ptr to determine the offset to the next location
  1673. // for an NT full EA.
  1674. //
  1675. ptr = (PCHAR)( ((ULONG_PTR)ptr + 3) & ~3 );
  1676. NtFullEa->NextEntryOffset = (ULONG)( ptr - (PCHAR)NtFullEa );
  1677. NtFullEa = (PFILE_FULL_EA_INFORMATION)ptr;
  1678. if ( ReturnSingleEntry == TRUE ) {
  1679. break;
  1680. }
  1681. }
  1682. //
  1683. // Set the NextEntryOffset field of the last full EA to 0 to indicate
  1684. // the end of the list.
  1685. //
  1686. LastNtFullEa->NextEntryOffset = 0;
  1687. //
  1688. // Record position the default start position for the next query
  1689. //
  1690. capFobx->OffsetOfNextEaToReturn = EaIndex;
  1691. if ( Overflow == FALSE ) {
  1692. return STATUS_SUCCESS;
  1693. } else {
  1694. return STATUS_BUFFER_OVERFLOW;
  1695. }
  1696. }
  1697. ULONG
  1698. MRxSmbNtFullEaSizeToOs2 (
  1699. IN PFILE_FULL_EA_INFORMATION NtFullEa
  1700. )
  1701. /*++
  1702. Routine Description:
  1703. Get the number of bytes that would be required to represent the
  1704. NT full EA list in OS/2 1.2 style. This routine assumes that
  1705. at least one EA is present in the buffer.
  1706. Arguments:
  1707. NtFullEa - a pointer to the list of NT EAs.
  1708. Return Value:
  1709. ULONG - number of bytes required to hold the EAs in OS/2 1.2 format.
  1710. --*/
  1711. {
  1712. ULONG size;
  1713. PAGED_CODE();
  1714. //
  1715. // Walk through the EAs, adding up the total size required to
  1716. // hold them in OS/2 format.
  1717. //
  1718. for ( size = FIELD_OFFSET(FEALIST, list[0]);
  1719. NtFullEa->NextEntryOffset != 0;
  1720. NtFullEa = (PFILE_FULL_EA_INFORMATION)(
  1721. (PCHAR)NtFullEa + NtFullEa->NextEntryOffset ) ) {
  1722. size += SmbGetOs2SizeOfNtFullEa( NtFullEa );
  1723. }
  1724. size += SmbGetOs2SizeOfNtFullEa( NtFullEa );
  1725. return size;
  1726. }
  1727. VOID
  1728. MRxSmbNtFullListToOs2 (
  1729. IN PFILE_FULL_EA_INFORMATION NtEaList,
  1730. IN PFEALIST FeaList
  1731. )
  1732. /*++
  1733. Routine Description:
  1734. Converts a single NT FULL EA list to OS/2 FEALIST style. The FEALIST
  1735. need not have any particular alignment.
  1736. It is the callers responsibility to ensure that FeaList is large enough.
  1737. Arguments:
  1738. NtEaList - An NT style get EA list to be converted to OS/2 format.
  1739. FeaList - Where to place the OS/2 1.2 style FEALIST.
  1740. Return Value:
  1741. none.
  1742. --*/
  1743. {
  1744. PFEA fea = FeaList->list;
  1745. PFILE_FULL_EA_INFORMATION ntFullEa = NtEaList;
  1746. PAGED_CODE();
  1747. //
  1748. // Copy the Eas up until the last one
  1749. //
  1750. while ( ntFullEa->NextEntryOffset != 0 ) {
  1751. //
  1752. // Copy the NT format EA to OS/2 1.2 format and set the fea
  1753. // pointer for the next iteration.
  1754. //
  1755. fea = MRxSmbNtFullEaToOs2( fea, ntFullEa );
  1756. ntFullEa = (PFILE_FULL_EA_INFORMATION)((PCHAR)ntFullEa + ntFullEa->NextEntryOffset);
  1757. }
  1758. // Now copy the last entry.
  1759. fea = MRxSmbNtFullEaToOs2( fea, ntFullEa );
  1760. //
  1761. // Set the number of bytes in the FEALIST.
  1762. //
  1763. SmbPutUlong(
  1764. &FeaList->cbList,
  1765. (ULONG)((PCHAR)fea - (PCHAR)FeaList)
  1766. );
  1767. }
  1768. PVOID
  1769. MRxSmbNtFullEaToOs2 (
  1770. OUT PFEA Fea,
  1771. IN PFILE_FULL_EA_INFORMATION NtFullEa
  1772. )
  1773. /*++
  1774. Routine Description:
  1775. Converts a single NT full EA to OS/2 FEA style. The FEA need not have
  1776. any particular alignment. This routine makes no checks on buffer
  1777. overrunning--this is the responsibility of the calling routine.
  1778. Arguments:
  1779. Fea - a pointer to the location where the OS/2 FEA is to be written.
  1780. NtFullEa - a pointer to the NT full EA.
  1781. Return Value:
  1782. A pointer to the location after the last byte written.
  1783. --*/
  1784. {
  1785. PCHAR ptr;
  1786. PAGED_CODE();
  1787. Fea->fEA = (UCHAR)NtFullEa->Flags;
  1788. Fea->cbName = NtFullEa->EaNameLength;
  1789. SmbPutUshort( &Fea->cbValue, NtFullEa->EaValueLength );
  1790. ptr = (PCHAR)(Fea + 1);
  1791. RtlCopyMemory( ptr, NtFullEa->EaName, NtFullEa->EaNameLength );
  1792. ptr += NtFullEa->EaNameLength;
  1793. *ptr++ = '\0';
  1794. RtlCopyMemory(
  1795. ptr,
  1796. NtFullEa->EaName + NtFullEa->EaNameLength + 1,
  1797. NtFullEa->EaValueLength
  1798. );
  1799. return (ptr + NtFullEa->EaValueLength);
  1800. }
  1801. NTSTATUS
  1802. MRxSmbSetEaList(
  1803. IN PRX_CONTEXT RxContext,
  1804. IN PFEALIST ServerEaList
  1805. )
  1806. /*++
  1807. Routine Description:
  1808. This routine implements the NtQueryEaFile api.
  1809. It returns the following information:
  1810. Arguments:
  1811. IN PFEALIST ServerEaList - Eas to be sent to the server.
  1812. Return Value:
  1813. Status - Result of the operation.
  1814. --*/
  1815. {
  1816. RxCaptureFobx;
  1817. PMRX_SMB_SRV_OPEN smbSrvOpen;
  1818. NTSTATUS Status;
  1819. USHORT Setup = TRANS2_SET_FILE_INFORMATION;
  1820. REQ_SET_FILE_INFORMATION SetFileInfoRequest;
  1821. RESP_SET_FILE_INFORMATION SetFileInfoResponse;
  1822. PBYTE pInputParamBuffer = NULL;
  1823. PBYTE pOutputParamBuffer = NULL;
  1824. PBYTE pInputDataBuffer = NULL;
  1825. PBYTE pOutputDataBuffer = NULL;
  1826. ULONG InputParamBufferLength = 0;
  1827. ULONG OutputParamBufferLength = 0;
  1828. ULONG InputDataBufferLength = 0;
  1829. ULONG OutputDataBufferLength = 0;
  1830. PAGED_CODE();
  1831. RxDbgTrace(+1, Dbg, ("MRxSmbSetEaList...\n"));
  1832. Status = STATUS_MORE_PROCESSING_REQUIRED;
  1833. SetFileInfoResponse.EaErrorOffset = 0;
  1834. smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  1835. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  1836. PSMB_TRANSACTION_OPTIONS pTransactionOptions = &RxDefaultTransactionOptions;
  1837. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  1838. //RxDbgTrace( 0, Dbg, ("MRxSmbNamedPipeFsControl: TransactionName %ws Length %ld\n",
  1839. // TransactionName.Buffer,TransactionName.Length));
  1840. SetFileInfoRequest.Fid = smbSrvOpen->Fid;
  1841. SetFileInfoRequest.InformationLevel = SMB_INFO_SET_EAS;
  1842. SetFileInfoRequest.Flags = 0;
  1843. // CODE.IMPROVEMENT it is unfortunate that this is defined so that a dataMDL cannot be passed
  1844. // perhaps it should be passed in the options!
  1845. Status = SmbCeTransact(
  1846. RxContext, // the RXContext for the transaction
  1847. pTransactionOptions, // transaction options
  1848. &Setup, // the setup buffer
  1849. sizeof(Setup), // setup buffer length
  1850. NULL, // the output setup buffer
  1851. 0, // output setup buffer length
  1852. &SetFileInfoRequest, // Input Param Buffer
  1853. sizeof(SetFileInfoRequest), // Input param buffer length
  1854. &SetFileInfoResponse, // Output param buffer
  1855. sizeof(SetFileInfoResponse), // output param buffer length
  1856. ServerEaList, // Input data buffer
  1857. SmbGetUlong(&ServerEaList->cbList), // Input data buffer length
  1858. NULL, // output data buffer
  1859. 0, // output data buffer length
  1860. &ResumptionContext // the resumption context
  1861. );
  1862. }
  1863. if (!NT_SUCCESS(Status)) {
  1864. USHORT EaErrorOffset = SetFileInfoResponse.EaErrorOffset;
  1865. RxDbgTrace( 0, Dbg, ("MRxSmbSetEaList: Failed .. returning %lx/%lx\n",Status,EaErrorOffset));
  1866. RxContext->InformationToReturn = (EaErrorOffset);
  1867. }
  1868. else
  1869. {
  1870. // succeeded in setting EAs, reset this flag so that when this
  1871. // srvopen is used again for getting the EAs we will succeed
  1872. smbSrvOpen->FileStatusFlags &= ~SMB_FSF_NO_EAS;
  1873. }
  1874. RxDbgTrace(-1, Dbg, ("MRxSmbSetEaList...exit\n"));
  1875. return Status;
  1876. }
  1877. NTSTATUS
  1878. MRxSmbQueryQuotaInformation(
  1879. IN OUT PRX_CONTEXT RxContext)
  1880. {
  1881. RxCaptureFobx;
  1882. PMRX_SMB_SRV_OPEN smbSrvOpen;
  1883. NTSTATUS Status;
  1884. USHORT Setup = NT_TRANSACT_QUERY_QUOTA;
  1885. PSID StartSid;
  1886. ULONG StartSidLength;
  1887. REQ_NT_QUERY_FS_QUOTA_INFO QueryQuotaInfoRequest;
  1888. RESP_NT_QUERY_FS_QUOTA_INFO QueryQuotaInfoResponse;
  1889. PBYTE pInputParamBuffer = NULL;
  1890. PBYTE pOutputParamBuffer = NULL;
  1891. PBYTE pInputDataBuffer = NULL;
  1892. PBYTE pOutputDataBuffer = NULL;
  1893. ULONG InputParamBufferLength = 0;
  1894. ULONG OutputParamBufferLength = 0;
  1895. ULONG InputDataBufferLength = 0;
  1896. ULONG OutputDataBufferLength = 0;
  1897. PAGED_CODE();
  1898. RxDbgTrace(+1, Dbg, ("MRxSmbQueryQuotaInformation...\n"));
  1899. Status = STATUS_MORE_PROCESSING_REQUIRED;
  1900. if (capFobx != NULL) {
  1901. smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  1902. }
  1903. if ((capFobx == NULL) ||
  1904. (smbSrvOpen == NULL)) {
  1905. Status = STATUS_INVALID_PARAMETER;
  1906. }
  1907. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  1908. StartSid = RxContext->QueryQuota.StartSid;
  1909. if (StartSid != NULL) {
  1910. StartSidLength = RtlLengthRequiredSid(((PISID)StartSid)->SubAuthorityCount);
  1911. } else {
  1912. StartSidLength = 0;
  1913. }
  1914. QueryQuotaInfoRequest.Fid = smbSrvOpen->Fid;
  1915. QueryQuotaInfoRequest.ReturnSingleEntry = RxContext->QueryQuota.ReturnSingleEntry;
  1916. QueryQuotaInfoRequest.RestartScan = RxContext->QueryQuota.RestartScan;
  1917. QueryQuotaInfoRequest.SidListLength = RxContext->QueryQuota.SidListLength;
  1918. QueryQuotaInfoRequest.StartSidOffset = ROUND_UP_COUNT(
  1919. RxContext->QueryQuota.SidListLength,
  1920. sizeof(ULONG));
  1921. QueryQuotaInfoRequest.StartSidLength = StartSidLength;
  1922. // The input data buffer to be supplied to the server consists of two pieces
  1923. // of information the start sid and the sid list. Currently the I/O
  1924. // subsystem allocates them in contigous memory. In such cases we avoid
  1925. // another allocation by reusing the same buffer. If this condition is
  1926. // not satisfied we allocate a buffer large enough for both the
  1927. // components and copy them over.
  1928. InputDataBufferLength = ROUND_UP_COUNT(
  1929. RxContext->QueryQuota.SidListLength,
  1930. sizeof(ULONG)) +
  1931. StartSidLength;
  1932. QueryQuotaInfoRequest.StartSidLength = StartSidLength;
  1933. if (((PBYTE)RxContext->QueryQuota.SidList +
  1934. ROUND_UP_COUNT(RxContext->QueryQuota.SidListLength,sizeof(ULONG))) !=
  1935. RxContext->QueryQuota.StartSid) {
  1936. pInputDataBuffer = RxAllocatePoolWithTag(
  1937. PagedPool,
  1938. InputDataBufferLength,
  1939. MRXSMB_MISC_POOLTAG);
  1940. if (pInputDataBuffer != NULL) {
  1941. RtlCopyMemory(
  1942. pInputDataBuffer ,
  1943. RxContext->QueryQuota.SidList,
  1944. RxContext->QueryQuota.SidListLength);
  1945. RtlCopyMemory(
  1946. pInputDataBuffer + QueryQuotaInfoRequest.StartSidOffset,
  1947. StartSid,
  1948. StartSidLength);
  1949. } else {
  1950. Status = STATUS_INSUFFICIENT_RESOURCES;
  1951. }
  1952. } else {
  1953. pInputDataBuffer = (PBYTE)RxContext->QueryQuota.SidList;
  1954. }
  1955. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  1956. SMB_TRANSACTION_OPTIONS TransactionOptions = RxDefaultTransactionOptions;
  1957. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  1958. TransactionOptions.NtTransactFunction = NT_TRANSACT_QUERY_QUOTA;
  1959. pOutputDataBuffer = RxContext->Info.Buffer;
  1960. OutputDataBufferLength = RxContext->Info.LengthRemaining;
  1961. Status = SmbCeTransact(
  1962. RxContext, // the RXContext for the transaction
  1963. &TransactionOptions, // transaction options
  1964. &Setup, // the setup buffer
  1965. sizeof(Setup), // setup buffer length
  1966. NULL, // the output setup buffer
  1967. 0, // output setup buffer length
  1968. &QueryQuotaInfoRequest, // Input Param Buffer
  1969. sizeof(QueryQuotaInfoRequest), // Input param buffer length
  1970. &QueryQuotaInfoResponse, // Output param buffer
  1971. sizeof(QueryQuotaInfoResponse), // output param buffer length
  1972. pInputDataBuffer, // Input data buffer
  1973. InputDataBufferLength, // Input data buffer length
  1974. pOutputDataBuffer, // output data buffer
  1975. OutputDataBufferLength, // output data buffer length
  1976. &ResumptionContext // the resumption context
  1977. );
  1978. }
  1979. if ((pInputDataBuffer != NULL) &&
  1980. (pInputDataBuffer != (PBYTE)RxContext->QueryQuota.SidList)) {
  1981. RxFreePool(pInputDataBuffer);
  1982. }
  1983. }
  1984. if (!NT_SUCCESS(Status)) {
  1985. RxContext->InformationToReturn = 0;
  1986. } else {
  1987. RxContext->InformationToReturn = QueryQuotaInfoResponse.Length;
  1988. }
  1989. RxDbgTrace(-1, Dbg, ("MRxSmbQueryQuotaInformation...exit\n"));
  1990. return Status;
  1991. }
  1992. NTSTATUS
  1993. MRxSmbSetQuotaInformation(
  1994. IN OUT PRX_CONTEXT RxContext)
  1995. {
  1996. RxCaptureFobx;
  1997. PMRX_SMB_SRV_OPEN smbSrvOpen;
  1998. NTSTATUS Status;
  1999. USHORT Setup = NT_TRANSACT_SET_QUOTA;
  2000. REQ_NT_SET_FS_QUOTA_INFO SetQuotaInfoRequest;
  2001. PBYTE pInputParamBuffer = NULL;
  2002. PBYTE pOutputParamBuffer = NULL;
  2003. PBYTE pInputDataBuffer = NULL;
  2004. PBYTE pOutputDataBuffer = NULL;
  2005. ULONG InputParamBufferLength = 0;
  2006. ULONG OutputParamBufferLength = 0;
  2007. ULONG InputDataBufferLength = 0;
  2008. ULONG OutputDataBufferLength = 0;
  2009. PAGED_CODE();
  2010. RxDbgTrace(+1, Dbg, ("MRxSmbSetQuotaInformation...\n"));
  2011. Status = STATUS_MORE_PROCESSING_REQUIRED;
  2012. if (capFobx != NULL) {
  2013. smbSrvOpen = MRxSmbGetSrvOpenExtension(capFobx->pSrvOpen);
  2014. }
  2015. if ((capFobx == NULL) ||
  2016. (smbSrvOpen == NULL)) {
  2017. Status = STATUS_INVALID_PARAMETER;
  2018. }
  2019. if (Status == STATUS_MORE_PROCESSING_REQUIRED) {
  2020. SMB_TRANSACTION_OPTIONS TransactionOptions = RxDefaultTransactionOptions;
  2021. SMB_TRANSACTION_RESUMPTION_CONTEXT ResumptionContext;
  2022. TransactionOptions.NtTransactFunction = NT_TRANSACT_SET_QUOTA;
  2023. SetQuotaInfoRequest.Fid = smbSrvOpen->Fid;
  2024. pInputDataBuffer = RxContext->Info.Buffer;
  2025. InputDataBufferLength = RxContext->Info.LengthRemaining;
  2026. Status = SmbCeTransact(
  2027. RxContext, // the RXContext for the transaction
  2028. &TransactionOptions, // transaction options
  2029. &Setup, // the setup buffer
  2030. sizeof(Setup), // setup buffer length
  2031. NULL, // the output setup buffer
  2032. 0, // output setup buffer length
  2033. &SetQuotaInfoRequest, // Input Param Buffer
  2034. sizeof(SetQuotaInfoRequest), // Input param buffer length
  2035. pOutputParamBuffer, // Output param buffer
  2036. OutputParamBufferLength, // output param buffer length
  2037. pInputDataBuffer, // Input data buffer
  2038. InputDataBufferLength, // Input data buffer length
  2039. pOutputDataBuffer, // output data buffer
  2040. OutputDataBufferLength, // output data buffer length
  2041. &ResumptionContext // the resumption context
  2042. );
  2043. }
  2044. RxDbgTrace(-1, Dbg, ("MRxSmbSetQuotaInformation...exit\n"));
  2045. return Status;
  2046. }