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.

1650 lines
46 KiB

  1. /*
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. access.c
  5. Abstract:
  6. This module contains the routines for handling access related stuff.
  7. Author:
  8. Jameel Hyder (microsoft!jameelh)
  9. Revision History:
  10. 20 Sep 1992 Initial Version
  11. Notes: Tab stop: 4
  12. --*/
  13. #define FILENUM FILE_ACCESS
  14. #include <afp.h>
  15. #include <fdparm.h>
  16. #include <pathmap.h>
  17. #define _ACCESS_LOCALS
  18. #include <access.h>
  19. #include <client.h>
  20. #include <secutil.h>
  21. #include <seposix.h>
  22. #ifdef ALLOC_PRAGMA
  23. #pragma alloc_text( PAGE, AfpGetUserAndPrimaryGroupSids)
  24. #pragma alloc_text( PAGE, AfpMakeSecurityDescriptorForUser)
  25. #pragma alloc_text( PAGE, AfpGetAfpPermissions)
  26. #pragma alloc_text( PAGE, afpMoveAces)
  27. #pragma alloc_text( PAGE, AfpSetAfpPermissions)
  28. #pragma alloc_text( PAGE, afpPermissions2NtMask)
  29. #pragma alloc_text( PAGE, afpAddAceToAcl)
  30. #if DBG
  31. #pragma alloc_text( PAGE, AfpDumpSid)
  32. #pragma alloc_text( PAGE, AfpDumpSidnMask)
  33. #endif
  34. #endif
  35. #define ACCESS_CHECK_ACCESS_MASK 0x01
  36. #define GRPS_BUFFER_SIZE 1024
  37. /*** AfpMakeSecDescForAccessCheck
  38. *
  39. * Create a security descriptor for a SID. The security descriptor has the
  40. * Aces for the User alone.
  41. */
  42. AFPSTATUS
  43. AfpMakeSecDescForAccessCheck(
  44. IN PSID OwnerSid,
  45. OUT PISECURITY_DESCRIPTOR * ppSecDesc
  46. )
  47. {
  48. AFPSTATUS Status = AFP_ERR_MISC;
  49. PISECURITY_DESCRIPTOR pSecDesc;
  50. int DaclSize;
  51. PACCESS_ALLOWED_ACE pAce;
  52. PAGED_CODE( );
  53. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  54. ("AfpMakeSecDescForAccessCheck: Entered\n"));
  55. do
  56. {
  57. // Allocate a security descriptor
  58. pSecDesc = (PISECURITY_DESCRIPTOR)ALLOC_ACCESS_MEM(sizeof(SECURITY_DESCRIPTOR));
  59. *ppSecDesc = pSecDesc;
  60. if (pSecDesc == NULL)
  61. {
  62. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_ERR,
  63. ("ALLOC_ACCESS_MEM error for pSecDesc\n"));
  64. break;
  65. }
  66. // Initialize the security descriptor
  67. RtlCreateSecurityDescriptor(pSecDesc, SECURITY_DESCRIPTOR_REVISION);
  68. pSecDesc->Control = SE_DACL_PRESENT;
  69. // Set the owner and group Ids in the descriptor
  70. pSecDesc->Owner = OwnerSid;
  71. // Determine the size of the Dacl needed. The sizeof(DWORD) offsets the
  72. // SidStart field in the ACE.
  73. //
  74. // 2 ACEs for the owner (owner+inherit for owner)
  75. DaclSize = sizeof(ACL) + 2*(sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
  76. RtlLengthSid(OwnerSid));
  77. if ((pSecDesc->Dacl = (PACL)ALLOC_ACCESS_MEM(DaclSize)) == NULL)
  78. {
  79. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_ERR,
  80. ("ALLOC_ACCESS_MEM error for pSecDesc->Dacl\n"));
  81. break;
  82. }
  83. // Initialize the ACL with one ACE corres. to Owner getting all the
  84. // privileges. Add another ace which is identical to the first ace but is
  85. // a inheritance ACE.
  86. RtlCreateAcl(pSecDesc->Dacl, DaclSize, ACL_REVISION);
  87. // we will be adding to this as we add aces, so set it to the min here
  88. pSecDesc->Dacl->AclSize = sizeof(ACL);
  89. pAce = (PACCESS_ALLOWED_ACE)((PBYTE)pSecDesc->Dacl + sizeof(ACL));
  90. // Add the ALLOWED_ACE and the corres. inherit Ace for owner
  91. pAce = afpAddAceToAcl(pSecDesc->Dacl,
  92. pAce,
  93. ACCESS_CHECK_ACCESS_MASK,
  94. OwnerSid,
  95. True);
  96. Status = AFP_ERR_NONE;
  97. } while (False);
  98. // Do any cleanup on error
  99. if (!NT_SUCCESS(Status) && (pSecDesc != NULL))
  100. {
  101. if (pSecDesc->Dacl != NULL)
  102. AfpFreeMemory(pSecDesc->Dacl);
  103. AfpFreeMemory(pSecDesc);
  104. pSecDesc = NULL;
  105. }
  106. return Status;
  107. }
  108. /*** afpCheckUserMemberOfGroup
  109. *
  110. * Determine if the User is member of the given group, if it is a group.
  111. */
  112. LOCAL BOOLEAN
  113. afpCheckUserMemberOfGroup(
  114. IN PSDA pSda,
  115. IN PSID pSidGroup
  116. )
  117. {
  118. DWORD i;
  119. BOOLEAN IsAMember = False;
  120. PISECURITY_DESCRIPTOR pSecDesc = NULL;
  121. SECURITY_SUBJECT_CONTEXT SecSubjectContext = {0};
  122. ACCESS_MASK CheckAccessMaskIn = 0, CheckAccessMaskOut = 0;
  123. BOOLEAN fAccessCheckSuccess = False;
  124. BOOLEAN fRevertImpersonation = False;
  125. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  126. PAGED_CODE( );
  127. ASSERT ((pSda != NULL) && (pSidGroup != NULL));
  128. AfpDumpSid("afpCheckUserMemberOfGroup: Checking", pSidGroup);
  129. do
  130. {
  131. // Create SecurityDescriptor out of the Sid provided
  132. Status = AfpMakeSecDescForAccessCheck(pSidGroup, &pSecDesc);
  133. if (!NT_SUCCESS(Status))
  134. {
  135. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_ERR,
  136. ("AfpMakeSecDescForAccessCheck failed error (%0xld)\n", Status));
  137. break;
  138. }
  139. AfpImpersonateClient(pSda);
  140. fRevertImpersonation = True;
  141. SeCaptureSubjectContext(&SecSubjectContext);
  142. CheckAccessMaskIn = ACCESS_CHECK_ACCESS_MASK;
  143. fAccessCheckSuccess = SeAccessCheck (
  144. pSecDesc,
  145. &SecSubjectContext,
  146. FALSE,
  147. CheckAccessMaskIn,
  148. 0,
  149. NULL,
  150. IoGetFileObjectGenericMapping(),
  151. UserMode,
  152. &CheckAccessMaskOut,
  153. &Status
  154. );
  155. if (fAccessCheckSuccess && NT_SUCCESS(Status))
  156. {
  157. IsAMember = True;
  158. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  159. ("SeAccessCheck good : Status= (%0x), RetCode= (%ld), AccessOut= (%ld)\n", Status, fAccessCheckSuccess, CheckAccessMaskOut));
  160. }
  161. else
  162. {
  163. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  164. ("SeAccessCheck failed: Status = (%0x), RetCode= (%ld)\n", Status, fAccessCheckSuccess));
  165. }
  166. SeReleaseSubjectContext(&SecSubjectContext);
  167. }
  168. while (FALSE);
  169. if (fRevertImpersonation)
  170. AfpRevertBack();
  171. if (pSecDesc != NULL)
  172. {
  173. if (pSecDesc->Dacl != NULL)
  174. AfpFreeMemory(pSecDesc->Dacl);
  175. AfpFreeMemory(pSecDesc);
  176. }
  177. return IsAMember;
  178. }
  179. /*** afpGetUserAccess
  180. *
  181. * Determine the Access that is permitted for the user
  182. */
  183. LOCAL NTSTATUS
  184. afpGetUserAccess(
  185. IN PSDA pSda,
  186. IN PISECURITY_DESCRIPTOR pSecDesc,
  187. OUT PACCESS_MASK pGrantedAccess
  188. )
  189. {
  190. DWORD i;
  191. SECURITY_SUBJECT_CONTEXT SecSubjectContext = {0};
  192. ACCESS_MASK DesiredAccess = 0;
  193. BOOLEAN fAccessCheckSuccess = False;
  194. BOOLEAN fRevertImpersonation = False;
  195. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  196. PAGED_CODE( );
  197. ASSERT ((pSda != NULL) && (pSecDesc != NULL));
  198. do
  199. {
  200. AfpImpersonateClient(pSda);
  201. fRevertImpersonation = True;
  202. SeCaptureSubjectContext(&SecSubjectContext);
  203. DesiredAccess = MAXIMUM_ALLOWED;
  204. fAccessCheckSuccess = SeAccessCheck (
  205. pSecDesc,
  206. &SecSubjectContext,
  207. FALSE,
  208. DesiredAccess,
  209. 0,
  210. NULL,
  211. IoGetFileObjectGenericMapping(),
  212. UserMode,
  213. pGrantedAccess,
  214. &Status
  215. );
  216. if (fAccessCheckSuccess && NT_SUCCESS(Status))
  217. {
  218. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  219. ("SeAccessCheck good : Status= (%0x), RetCode= (%ld), AccessOut= (%0x)\n", Status, fAccessCheckSuccess, *pGrantedAccess));
  220. }
  221. else
  222. {
  223. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  224. ("SeAccessCheck failed: Status = (%0x), RetCode= (%0x)\n", Status, fAccessCheckSuccess));
  225. }
  226. SeReleaseSubjectContext(&SecSubjectContext);
  227. }
  228. while (FALSE);
  229. if (fRevertImpersonation)
  230. AfpRevertBack();
  231. return Status;
  232. }
  233. /*** AfpGetUserAndPrimaryGroupSids
  234. *
  235. * Get the Sids corres. to the user and his primary group.
  236. */
  237. NTSTATUS
  238. AfpGetUserAndPrimaryGroupSids(
  239. IN PSDA pSda
  240. )
  241. {
  242. DWORD i, j;
  243. NTSTATUS Status = STATUS_SUCCESS;
  244. DWORD SidLength, SizeNeeded, ExtraSpace, Offset;
  245. PSID_AND_ATTRIBUTES pSidnAttr;
  246. PTOKEN_GROUPS pGroups = NULL;
  247. PBYTE pGrpsBuffer = NULL;
  248. BYTE Buffer[256]; // We should not need a buffer larger
  249. // than this for User SID_AND_ATTRIBUTES
  250. PAGED_CODE( );
  251. do
  252. {
  253. pGrpsBuffer = (PBYTE)ALLOC_ACCESS_MEM(GRPS_BUFFER_SIZE);
  254. if (pGrpsBuffer == NULL)
  255. {
  256. Status = STATUS_INSUFFICIENT_RESOURCES;
  257. break;
  258. }
  259. pGroups = (PTOKEN_GROUPS)pGrpsBuffer;
  260. pSda->sda_pGroups = NULL;
  261. if (pSda->sda_ClientType == SDA_CLIENT_GUEST)
  262. {
  263. pSda->sda_UserSid = &AfpSidWorld;
  264. pSda->sda_GroupSid = &AfpSidWorld; // Primary group of Guest is also 'World'
  265. break;
  266. }
  267. pSidnAttr = (PSID_AND_ATTRIBUTES)Buffer;
  268. // Get the Owner Sid out of the User token and copy it into the Sda
  269. Status = NtQueryInformationToken(pSda->sda_UserToken,
  270. TokenOwner,
  271. pSidnAttr,
  272. sizeof(Buffer),
  273. &SizeNeeded);
  274. ASSERT (NT_SUCCESS(Status));
  275. if (!NT_SUCCESS(Status))
  276. {
  277. break;
  278. }
  279. AfpDumpSid("AfpGetUserAndPrimaryGroupSids: LOGON Owner Sid", pSidnAttr->Sid);
  280. SidLength = RtlLengthSid(pSidnAttr->Sid);
  281. pSda->sda_UserSid = (PSID)ALLOC_ACCESS_MEM(SidLength);
  282. if (pSda->sda_UserSid == NULL)
  283. {
  284. Status = STATUS_INSUFFICIENT_RESOURCES;
  285. break;
  286. }
  287. RtlCopyMemory(pSda->sda_UserSid, pSidnAttr->Sid, SidLength);
  288. // Get the primary group of this user
  289. Status = NtQueryInformationToken(pSda->sda_UserToken,
  290. TokenPrimaryGroup,
  291. pSidnAttr,
  292. sizeof(Buffer),
  293. &SizeNeeded);
  294. ASSERT (NT_SUCCESS(Status));
  295. if (!NT_SUCCESS(Status))
  296. {
  297. break;
  298. }
  299. AfpDumpSid("AfpGetUserAndPrimaryGroupSids: LOGON Group Sid", pSidnAttr->Sid);
  300. SidLength = RtlLengthSid(pSidnAttr->Sid);
  301. pSda->sda_GroupSid = (PSID)ALLOC_ACCESS_MEM(SidLength);
  302. if (pSda->sda_GroupSid == NULL)
  303. {
  304. Status = STATUS_INSUFFICIENT_RESOURCES;
  305. break;
  306. }
  307. RtlCopyMemory(pSda->sda_GroupSid, pSidnAttr->Sid, SidLength);
  308. // Get the User Sid out of the User token. This will be added to the
  309. // list of groups that we query later, if this is different from
  310. // the Owner Sid (which is now in sda_UserSid).
  311. Status = NtQueryInformationToken(pSda->sda_UserToken,
  312. TokenUser,
  313. pSidnAttr,
  314. sizeof(Buffer),
  315. &SizeNeeded);
  316. ASSERT (NT_SUCCESS(Status));
  317. if (!NT_SUCCESS(Status))
  318. {
  319. break;
  320. }
  321. AfpDumpSid("AfpGetUserAndPrimaryGroupSids: LOGON User Sid", pSidnAttr->Sid);
  322. // Get the list of groups this user is member of
  323. SizeNeeded = GRPS_BUFFER_SIZE;
  324. do
  325. {
  326. if (Status != STATUS_SUCCESS)
  327. {
  328. if (pGroups != (PTOKEN_GROUPS)pGrpsBuffer)
  329. AfpFreeMemory(pGroups);
  330. if ((pGroups = (PTOKEN_GROUPS)ALLOC_ACCESS_MEM(SizeNeeded)) == NULL)
  331. {
  332. Status = AFP_ERR_MISC;
  333. if (pSda->sda_ClientType == SDA_CLIENT_ADMIN)
  334. {
  335. Status = STATUS_INSUFFICIENT_RESOURCES;
  336. }
  337. break;
  338. }
  339. }
  340. Status = NtQueryInformationToken(pSda->sda_UserToken,
  341. TokenGroups,
  342. pGroups,
  343. SizeNeeded,
  344. &SizeNeeded);
  345. } while ((Status != STATUS_SUCCESS) &&
  346. ((Status == STATUS_BUFFER_TOO_SMALL) ||
  347. (Status == STATUS_BUFFER_OVERFLOW) ||
  348. (Status == STATUS_MORE_ENTRIES)));
  349. if (!NT_SUCCESS(Status))
  350. {
  351. AFPLOG_ERROR(AFPSRVMSG_USER_GROUPS, Status, NULL, 0, NULL);
  352. break;
  353. }
  354. // Allocate enough memory to copy the group information in the sda. If
  355. // the User and Owner Sids in the user token are not the same then we
  356. // want to add the user sid to the list of groups. This is especially
  357. // the case where an ADMIN logs on but his Owner Sid is Administrators.
  358. // Also fix up the pointers appropriately !!!
  359. ExtraSpace = 0; Offset = 0; j = 0;
  360. if (!RtlEqualSid(pSidnAttr->Sid, pSda->sda_UserSid))
  361. {
  362. ExtraSpace = (RtlLengthSid(pSidnAttr->Sid) + sizeof(pSidnAttr->Attributes));
  363. Offset = sizeof(SID_AND_ATTRIBUTES);
  364. j = 1;
  365. }
  366. if ((pSda->sda_pGroups = (PTOKEN_GROUPS)AfpAllocPagedMemory(2*SizeNeeded+2*ExtraSpace)) == NULL)
  367. {
  368. Status = STATUS_INSUFFICIENT_RESOURCES;
  369. break;
  370. }
  371. // If we are not copying the User Sid in sda_pGroups, then copy pGroups to sda_pGroups
  372. // directly and then fixup the individual pSid pointers. If we are then make the User
  373. // Sid as the first one in the list and copy the actual sid at the tail end of the
  374. // buffer.
  375. pSda->sda_pGroups->GroupCount = pGroups->GroupCount;
  376. RtlCopyMemory(&pSda->sda_pGroups->Groups[j],
  377. &pGroups->Groups[0],
  378. SizeNeeded - sizeof(DWORD)); // DWORD accounts for GroupCount
  379. if (ExtraSpace > 0)
  380. {
  381. pSda->sda_pGroups->Groups[0].Sid = (PSID)((PBYTE)(pSda->sda_pGroups) + SizeNeeded);
  382. RtlCopyMemory(pSda->sda_pGroups->Groups[0].Sid,
  383. pSidnAttr->Sid,
  384. RtlLengthSid(pSidnAttr->Sid));
  385. pSda->sda_pGroups->Groups[0].Attributes = pSidnAttr->Attributes;
  386. pSda->sda_pGroups->GroupCount ++;
  387. AfpDumpSid("AfpGetUserAndPrimaryGroupSids: Member of ",
  388. pSda->sda_pGroups->Groups[0].Sid);
  389. }
  390. for (i = 0; i < pGroups->GroupCount; i++, j++)
  391. {
  392. pSda->sda_pGroups->Groups[j].Sid = (PSID)((PBYTE)(pGroups->Groups[i].Sid) -
  393. (PBYTE)pGroups +
  394. (PBYTE)(pSda->sda_pGroups) +
  395. Offset);
  396. AfpDumpSid("AfpGetUserAndPrimaryGroupSids: Member of ",
  397. pSda->sda_pGroups->Groups[j].Sid);
  398. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  399. ("AfpGetUserAndPrimaryGroupSids: Attributes %lx\n",
  400. pSda->sda_pGroups->Groups[j].Attributes));
  401. }
  402. } while (False);
  403. if (pGroups != (PTOKEN_GROUPS)pGrpsBuffer)
  404. if (pGroups)
  405. AfpFreeMemory(pGroups);
  406. if (pGrpsBuffer != NULL)
  407. AfpFreeMemory(pGrpsBuffer);
  408. return Status;
  409. }
  410. /*** AfpMakeSecurityDescriptorForUser
  411. *
  412. * Create a security descriptor for a user. The security descriptor has the
  413. * Owner Sid, Primary Group Sid and Aces for the User alone.
  414. */
  415. AFPSTATUS
  416. AfpMakeSecurityDescriptorForUser(
  417. IN PSID OwnerSid,
  418. IN PSID GroupSid,
  419. OUT PISECURITY_DESCRIPTOR * ppSecDesc
  420. )
  421. {
  422. AFPSTATUS Status = AFP_ERR_MISC;
  423. PISECURITY_DESCRIPTOR pSecDesc;
  424. int DaclSize;
  425. PACCESS_ALLOWED_ACE pAce;
  426. PAGED_CODE( );
  427. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  428. ("AfpMakeSecurityDescriptorForUser: Entered\n"));
  429. do
  430. {
  431. // Allocate a security descriptor
  432. pSecDesc = (PISECURITY_DESCRIPTOR)ALLOC_ACCESS_MEM(sizeof(SECURITY_DESCRIPTOR));
  433. *ppSecDesc = pSecDesc;
  434. if (pSecDesc == NULL)
  435. break;
  436. // Initialize the security descriptor
  437. RtlCreateSecurityDescriptor(pSecDesc, SECURITY_DESCRIPTOR_REVISION);
  438. pSecDesc->Control = SE_DACL_PRESENT;
  439. // Set the owner and group Ids in the descriptor
  440. pSecDesc->Owner = OwnerSid;
  441. pSecDesc->Group = GroupSid;
  442. // Determine the size of the Dacl needed. The sizeof(DWORD) offsets the
  443. // SidStart field in the ACE. There are 7 aces in this security descriptor:
  444. //
  445. // 2 for the owner (owner+inherit for owner)
  446. // 2 for world (1 for world and 1 inherit for world).
  447. // 2 for system
  448. DaclSize = sizeof(ACL) + 2*(sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
  449. RtlLengthSid(OwnerSid)) +
  450. 2*(sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
  451. sizeof(AfpSidWorld)) +
  452. 2*(sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
  453. AfpSizeSidAdmins) +
  454. 2*(sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
  455. RtlLengthSid(&AfpSidSystem));
  456. if ((pSecDesc->Dacl = (PACL)ALLOC_ACCESS_MEM(DaclSize)) == NULL)
  457. break;
  458. // Initialize the ACL with one ACE corres. to Owner getting all the
  459. // privileges. Add another ace which is identical to the first ace but is
  460. // a inheritance ACE.
  461. // JH - Add another ace for world with minumum permissions and for administrators
  462. // with FullControl
  463. RtlCreateAcl(pSecDesc->Dacl, DaclSize, ACL_REVISION);
  464. // we will be adding to this as we add aces, so set it to the min here
  465. pSecDesc->Dacl->AclSize = sizeof(ACL);
  466. pAce = (PACCESS_ALLOWED_ACE)((PBYTE)pSecDesc->Dacl + sizeof(ACL));
  467. // Add the ALLOWED_ACE and the corres. inherit Ace for owner
  468. pAce = afpAddAceToAcl(pSecDesc->Dacl,
  469. pAce,
  470. (AFP_READ_ACCESS | AFP_WRITE_ACCESS | AFP_OWNER_ACCESS | FILE_DELETE_CHILD),
  471. OwnerSid,
  472. True);
  473. if (AfpSidAdmins != NULL)
  474. {
  475. // Add the ALLOWED_ACE and the corres. inherit Ace for 'Administrators'
  476. pAce = afpAddAceToAcl(pSecDesc->Dacl,
  477. pAce,
  478. (AFP_READ_ACCESS | AFP_WRITE_ACCESS | AFP_OWNER_ACCESS | FILE_DELETE_CHILD),
  479. AfpSidAdmins,
  480. True);
  481. }
  482. // Add a min. permission ace for world, but only if the owner is
  483. // not world already
  484. if (!RtlEqualSid(OwnerSid, &AfpSidWorld))
  485. {
  486. pAce = afpAddAceToAcl(pSecDesc->Dacl,
  487. pAce,
  488. (AFP_MIN_ACCESS),
  489. &AfpSidWorld,
  490. True);
  491. }
  492. // Now add Aces for System
  493. pAce = afpAddAceToAcl(pSecDesc->Dacl,
  494. pAce,
  495. AFP_READ_ACCESS | AFP_WRITE_ACCESS | AFP_OWNER_ACCESS,
  496. &AfpSidSystem,
  497. True);
  498. Status = AFP_ERR_NONE;
  499. } while (False);
  500. // Do any cleanup on error
  501. if (!NT_SUCCESS(Status) && (pSecDesc != NULL))
  502. {
  503. if (pSecDesc->Dacl != NULL)
  504. AfpFreeMemory(pSecDesc->Dacl);
  505. AfpFreeMemory(pSecDesc);
  506. }
  507. return Status;
  508. }
  509. /*** AfpGetAfpPermissions
  510. *
  511. * Read the security descriptor for this directory and obtain the SIDs for
  512. * Owner and Primary group. Determine if this user is a member of the directory
  513. * primary group. Finally obtain Owner,Group and World permissions.
  514. *
  515. * OwnerId, GroupId and permissions will always be valid if this call succeeds.
  516. */
  517. NTSTATUS
  518. AfpGetAfpPermissions(
  519. IN PSDA pSda,
  520. IN HANDLE DirHandle,
  521. IN OUT PFILEDIRPARM pFDParm
  522. )
  523. {
  524. NTSTATUS Status = STATUS_SUCCESS;
  525. DWORD SizeNeeded;
  526. PISECURITY_DESCRIPTOR pSecDesc = NULL;
  527. PBYTE pAbsSecDesc = NULL; // Used in conversion of
  528. // sec descriptor to
  529. // absolute format
  530. BOOLEAN SawOwnerAce = False,
  531. SawGroupAce = False,
  532. SawWorldAce = False,
  533. CheckUserRights = False;
  534. ACCESS_MASK OwnerGranted = 0, OwnerDenied = 0,
  535. GroupGranted = 0, GroupDenied = 0,
  536. WorldGranted = 0, WorldDenied = 0,
  537. UserGranted = 0, UserDenied = 0,
  538. UserAccess = 0;
  539. #ifdef PROFILING
  540. TIME TimeS, TimeE, TimeD;
  541. #endif
  542. PAGED_CODE( );
  543. #ifdef PROFILING
  544. INTERLOCKED_INCREMENT_LONG(&AfpServerProfile->perf_GetPermsCount);
  545. AfpGetPerfCounter(&TimeS);
  546. #endif
  547. // Read the security descriptor for this directory and determine the
  548. // rights for owner/group/world.We want to optimize on how much memory
  549. // we need to read this in. Its a pain to make a call just to get that.
  550. // So just make a guess. If that turns out to be short then do the exact
  551. // allocation.
  552. do
  553. {
  554. // 4096 has been emperically chosen
  555. SizeNeeded = 4096 - POOL_OVERHEAD;
  556. do
  557. {
  558. if (pSecDesc != NULL)
  559. {
  560. AfpFreeMemory(pSecDesc);
  561. }
  562. if ((pSecDesc = (PSECURITY_DESCRIPTOR)ALLOC_ACCESS_MEM(SizeNeeded)) == NULL)
  563. {
  564. Status = AFP_ERR_MISC;
  565. if (pSda->sda_ClientType == SDA_CLIENT_ADMIN)
  566. {
  567. Status = STATUS_INSUFFICIENT_RESOURCES;
  568. }
  569. break;
  570. }
  571. Status = NtQuerySecurityObject(DirHandle,
  572. OWNER_SECURITY_INFORMATION |
  573. GROUP_SECURITY_INFORMATION |
  574. DACL_SECURITY_INFORMATION,
  575. pSecDesc,
  576. SizeNeeded,
  577. &SizeNeeded);
  578. } while ((Status != STATUS_SUCCESS) &&
  579. ((Status == STATUS_BUFFER_TOO_SMALL) ||
  580. (Status == STATUS_BUFFER_OVERFLOW) ||
  581. (Status == STATUS_MORE_ENTRIES)));
  582. if (!NT_SUCCESS(Status))
  583. {
  584. break;
  585. }
  586. // If the security descriptor is in self-relative form, convert to absolute
  587. pSecDesc = (PISECURITY_DESCRIPTOR)((PBYTE)pSecDesc);
  588. if (pSecDesc->Control & SE_SELF_RELATIVE)
  589. {
  590. DWORD AbsoluteSizeNeeded;
  591. // An absolute SD is not necessarily the same size as a relative
  592. // SD, so an in-place conversion may not be possible.
  593. AbsoluteSizeNeeded = SizeNeeded;
  594. Status = RtlSelfRelativeToAbsoluteSD2(pSecDesc, &AbsoluteSizeNeeded);
  595. if (Status == STATUS_BUFFER_TOO_SMALL)
  596. {
  597. // Allocate a new buffer in which to store the absolute
  598. // security descriptor, copy the contents of the relative
  599. // descriptor in and try again
  600. pAbsSecDesc = (PBYTE)ALLOC_ACCESS_MEM(AbsoluteSizeNeeded);
  601. if (pAbsSecDesc == NULL)
  602. {
  603. Status = STATUS_NO_MEMORY;
  604. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_ERR,
  605. ("AfpGetAfpPermissions: ALLOC_ACCESS_MEM error\n"));
  606. }
  607. else
  608. {
  609. RtlCopyMemory(pAbsSecDesc, pSecDesc, SizeNeeded);
  610. Status = RtlSelfRelativeToAbsoluteSD2 (pAbsSecDesc,
  611. &AbsoluteSizeNeeded);
  612. if (NT_SUCCESS(Status))
  613. {
  614. // We don't need relative form anymore,
  615. // we will work with the Absolute form
  616. if (pSecDesc != NULL)
  617. {
  618. AfpFreeMemory(pSecDesc);
  619. }
  620. pSecDesc = (PISECURITY_DESCRIPTOR)pAbsSecDesc;
  621. }
  622. else
  623. {
  624. // We cannot use Absolute Form, throw it away
  625. AfpFreeMemory(pAbsSecDesc);
  626. pAbsSecDesc = NULL;
  627. }
  628. }
  629. }
  630. if (!NT_SUCCESS(Status))
  631. {
  632. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_ERR,
  633. ("AfpGetAfpPermissions: RtlSelfRelativeToAbsoluteSD2: returned error %lx\n", Status));
  634. break;
  635. }
  636. }
  637. // Now determine if the user is a member of the directories primary group.
  638. pFDParm->_fdp_OwnerId = 0;
  639. pFDParm->_fdp_GroupId = 0;
  640. pFDParm->_fdp_UserIsOwner = False;
  641. pFDParm->_fdp_UserIsMemberOfDirGroup = False;
  642. if (pSecDesc->Owner != NULL)
  643. {
  644. AfpDumpSid("AfpGetAfpPermissions: OwnerSid", pSecDesc->Owner);
  645. pFDParm->_fdp_UserIsOwner =
  646. (RtlEqualSid(pSecDesc->Owner, pSda->sda_UserSid) ||
  647. ((pSda->sda_ClientType != SDA_CLIENT_GUEST) &&
  648. (pSda->sda_ClientType != SDA_CLIENT_ADMIN) &&
  649. afpCheckUserMemberOfGroup(pSda,
  650. pSecDesc->Owner)));
  651. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  652. ("AfpGetAfpPermissions: User %s Owner\n",
  653. pFDParm->_fdp_UserIsOwner ? "is" : "isnt"));
  654. if (!NT_SUCCESS(Status = AfpSidToMacId(pSecDesc->Owner,
  655. &pFDParm->_fdp_OwnerId)))
  656. {
  657. // If we cant map the Sid, return Id SE_NULL_POSIX_ID
  658. pFDParm->_fdp_OwnerId = SE_NULL_POSIX_ID;
  659. Status = AFP_ERR_NONE;
  660. }
  661. }
  662. if (pSecDesc->Group != NULL)
  663. {
  664. AfpDumpSid("AfpGetAfpPermissions: GroupSid", pSecDesc->Group);
  665. if (!pFDParm->_fdp_UserIsOwner)
  666. pFDParm->_fdp_UserIsMemberOfDirGroup =
  667. (RtlEqualSid(pSecDesc->Group, pSda->sda_UserSid) ||
  668. ((pSda->sda_ClientType != SDA_CLIENT_GUEST) &&
  669. (pSda->sda_ClientType != SDA_CLIENT_ADMIN) &&
  670. afpCheckUserMemberOfGroup(pSda,
  671. pSecDesc->Group)));
  672. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  673. ("AfpGetAfpPermissions: Group %s member of PrimaryGroup\n",
  674. pFDParm->_fdp_UserIsMemberOfDirGroup ? "is" : "isnt"));
  675. if (!NT_SUCCESS(Status = AfpSidToMacId(pSecDesc->Group,
  676. &pFDParm->_fdp_GroupId)))
  677. {
  678. // If we cant map the Sid, return Id SE_NULL_POSIX_ID
  679. pFDParm->_fdp_GroupId = SE_NULL_POSIX_ID;
  680. Status = AFP_ERR_NONE;
  681. }
  682. }
  683. // Walk through the ACL list and determine Owner/Group/World and User
  684. // permissions. For Owner/Group and User, if the specific ace's are
  685. // not present then they inherit the world permissions.
  686. //
  687. // A NULL Acl => All rights to everyone. An empty Acl on the other
  688. // hand => no access for anyone.
  689. pFDParm->_fdp_UserRights = 0;
  690. pFDParm->_fdp_WorldRights = 0;
  691. if ((pSecDesc->Control & SE_DACL_PRESENT) &&
  692. (pSecDesc->Dacl != NULL))
  693. {
  694. USHORT i;
  695. PSID pSid;
  696. PACL pAcl;
  697. PACCESS_ALLOWED_ACE pAce;
  698. pAcl = pSecDesc->Dacl;
  699. pAce = (PACCESS_ALLOWED_ACE)((PBYTE)pAcl + sizeof(ACL));
  700. CheckUserRights = ((pSda->sda_ClientType != SDA_CLIENT_GUEST) &&
  701. (pSda->sda_ClientType != SDA_CLIENT_ADMIN));
  702. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  703. ("AfpGetAfpPermissions: # of aces %d\n", pSecDesc->Dacl->AceCount));
  704. for (i = 0; i < pSecDesc->Dacl->AceCount; i++)
  705. {
  706. if ((pAce->Header.AceType != ACCESS_ALLOWED_ACE_TYPE) &&
  707. (pAce->Header.AceType != ACCESS_DENIED_ACE_TYPE))
  708. {
  709. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  710. ("AfpGetAfpPermissions: Skipping ACE of type (%ld)\n", pAce->Header.AceType));
  711. pAce = (PACCESS_ALLOWED_ACE)((PBYTE)pAce + pAce->Header.AceSize);
  712. continue;
  713. }
  714. pSid = (PSID)(&pAce->SidStart);
  715. // Ignore inherit-only aces, & system
  716. if (pAce->Header.AceFlags & INHERIT_ONLY_ACE)
  717. {
  718. AfpDumpSidnMask("AfpGetAfpPermissions: Skipping",
  719. pSid,
  720. pAce->Mask,
  721. pAce->Header.AceType,
  722. pAce->Header.AceFlags);
  723. }
  724. else
  725. {
  726. AfpDumpSidnMask("AfpGetAfpPermissions: ACE",
  727. pSid,
  728. pAce->Mask,
  729. pAce->Header.AceType,
  730. pAce->Header.AceFlags);
  731. if ((pSecDesc->Owner != NULL) &&
  732. RtlEqualSid(pSid, pSecDesc->Owner))
  733. {
  734. if (pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
  735. {
  736. OwnerGranted |= (pAce->Mask & ~OwnerDenied);
  737. }
  738. else
  739. {
  740. OwnerDenied |= (pAce->Mask & ~OwnerGranted);
  741. }
  742. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  743. ("Owner: %s Ace Mask %lx\n",
  744. (pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) ?
  745. "Allow" : "Deny",
  746. pAce->Mask));
  747. SawOwnerAce = True;
  748. }
  749. if ((pSecDesc->Group != NULL) &&
  750. RtlEqualSid(pSid, pSecDesc->Group))
  751. {
  752. if (pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
  753. {
  754. GroupGranted |= (pAce->Mask & ~GroupDenied);
  755. }
  756. else
  757. {
  758. GroupDenied |= (pAce->Mask & ~GroupGranted);
  759. }
  760. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  761. ("Group: %s Ace Mask %lx\n",
  762. (pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) ?
  763. "Allow" : "Deny",
  764. pAce->Mask));
  765. SawGroupAce = True;
  766. }
  767. if ((RtlEqualSid(pSid, (PSID)&AfpSidWorld)))
  768. {
  769. if (pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
  770. {
  771. WorldGranted |= (pAce->Mask & ~WorldDenied);
  772. }
  773. else
  774. {
  775. WorldDenied |= (pAce->Mask & ~WorldGranted);
  776. }
  777. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  778. ("World: %s Ace Mask %lx\n",
  779. (pAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) ?
  780. "Allow" : "Deny",
  781. pAce->Mask));
  782. SawWorldAce = True;
  783. }
  784. }
  785. pAce = (PACCESS_ALLOWED_ACE)((PBYTE)pAce + pAce->Header.AceSize);
  786. }
  787. }
  788. else // Security descriptor not present, party time
  789. {
  790. pFDParm->_fdp_WorldRights = DIR_ACCESS_ALL;
  791. pFDParm->_fdp_UserRights = DIR_ACCESS_ALL | DIR_ACCESS_OWNER;
  792. }
  793. if (!SawGroupAce)
  794. pFDParm->_fdp_GroupRights = pFDParm->_fdp_WorldRights;
  795. if (SawOwnerAce)
  796. {
  797. AfpAccessMask2AfpPermissions(pFDParm->_fdp_OwnerRights,
  798. OwnerGranted,
  799. ACCESS_ALLOWED_ACE_TYPE);
  800. }
  801. if (SawGroupAce)
  802. {
  803. AfpAccessMask2AfpPermissions(pFDParm->_fdp_GroupRights,
  804. GroupGranted,
  805. ACCESS_ALLOWED_ACE_TYPE);
  806. }
  807. if (SawWorldAce)
  808. {
  809. AfpAccessMask2AfpPermissions(pFDParm->_fdp_WorldRights,
  810. WorldGranted,
  811. ACCESS_ALLOWED_ACE_TYPE);
  812. }
  813. // Get the ACCESS_MASK allowed for the user
  814. Status = afpGetUserAccess(
  815. pSda,
  816. pSecDesc,
  817. &UserAccess);
  818. if (NT_SUCCESS(Status))
  819. {
  820. UserGranted = UserAccess;
  821. }
  822. else
  823. {
  824. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_ERR,
  825. ("afpGetUserAccess failed with error %0x\n",
  826. Status));
  827. Status = AFP_ERR_NONE;
  828. }
  829. AfpAccessMask2AfpPermissions(pFDParm->_fdp_UserRights,
  830. UserGranted,
  831. ACCESS_ALLOWED_ACE_TYPE);
  832. // If this is a standalone server and the primary group of the
  833. // directory is MACHINE\None, do not return this information to
  834. // the caller.
  835. if (AfpServerIsStandalone &&
  836. (pSecDesc->Group != NULL) &&
  837. RtlEqualSid(pSecDesc->Group, AfpSidNone))
  838. {
  839. pFDParm->_fdp_GroupRights = 0;
  840. pFDParm->_fdp_GroupId = 0;
  841. }
  842. if (pSda->sda_ClientType == SDA_CLIENT_GUEST)
  843. pFDParm->_fdp_UserRights = pFDParm->_fdp_WorldRights;
  844. } while (False);
  845. if (pSecDesc != NULL)
  846. AfpFreeMemory(pSecDesc);
  847. #ifdef PROFILING
  848. AfpGetPerfCounter(&TimeE);
  849. TimeD.QuadPart = TimeE.QuadPart - TimeS.QuadPart;
  850. INTERLOCKED_ADD_LARGE_INTGR(&AfpServerProfile->perf_GetPermsTime,
  851. TimeD,
  852. &AfpStatisticsLock);
  853. #endif
  854. return Status;
  855. }
  856. /*** afpMoveAces
  857. *
  858. * Move a bunch of aces from the old security descriptor to the new security
  859. * descriptor.
  860. */
  861. LOCAL PACCESS_ALLOWED_ACE
  862. afpMoveAces(
  863. IN PACL pOldDacl,
  864. IN PACCESS_ALLOWED_ACE pAceStart,
  865. IN PSID pSidOldOwner,
  866. IN PSID pSidNewOwner,
  867. IN PSID pSidOldGroup,
  868. IN PSID pSidNewGroup,
  869. IN BOOLEAN DenyAces,
  870. IN BOOLEAN InheritedAces,
  871. IN OUT PACL pNewDacl
  872. )
  873. {
  874. USHORT i;
  875. PACCESS_ALLOWED_ACE pAceOld;
  876. PSID pSidAce;
  877. PAGED_CODE( );
  878. for (i = 0, pAceOld = (PACCESS_ALLOWED_ACE)((PBYTE)pOldDacl + sizeof(ACL));
  879. i < pOldDacl->AceCount;
  880. i++, pAceOld = (PACCESS_ALLOWED_ACE)((PBYTE)pAceOld + pAceOld->Header.AceSize))
  881. {
  882. if (InheritedAces && ((pAceOld->Header.AceFlags & INHERITED_ACE) != INHERITED_ACE))
  883. continue;
  884. if ((!InheritedAces) && ((pAceOld->Header.AceFlags & INHERITED_ACE) == INHERITED_ACE))
  885. continue;
  886. // Note: All deny aces are ahead of the grant aces.
  887. if (DenyAces && (pAceOld->Header.AceType != ACCESS_DENIED_ACE_TYPE))
  888. break;
  889. if (!DenyAces && (pAceOld->Header.AceType == ACCESS_DENIED_ACE_TYPE))
  890. continue;
  891. pSidAce = (PSID)(&pAceOld->SidStart);
  892. if (!RtlEqualSid(pSidAce, &AfpSidWorld) &&
  893. !RtlEqualSid(pSidAce, &AfpSidSystem) &&
  894. !RtlEqualSid(pSidAce, pSidOldOwner) &&
  895. !RtlEqualSid(pSidAce, pSidNewOwner) &&
  896. !RtlEqualSid(pSidAce, pSidOldGroup) &&
  897. !RtlEqualSid(pSidAce, pSidNewGroup))
  898. {
  899. RtlCopyMemory(pAceStart, pAceOld, pAceOld->Header.AceSize);
  900. pNewDacl->AclSize += pAceOld->Header.AceSize;
  901. pNewDacl->AceCount ++;
  902. pAceStart = (PACCESS_ALLOWED_ACE)((PBYTE)pAceStart +
  903. pAceStart->Header.AceSize);
  904. }
  905. }
  906. return pAceStart;
  907. }
  908. /*** AfpSetAfpPermissions
  909. *
  910. * Set the permissions on this directory. Also optionally set the owner and
  911. * group ids. For setting the owner and group ids verify if the user has the
  912. * needed access. This access is however not good enough. We check for this
  913. * access but do the actual setting of the permissions in the special server
  914. * context (RESTORE privilege is needed).
  915. */
  916. AFPSTATUS
  917. AfpSetAfpPermissions(
  918. IN HANDLE DirHandle,
  919. IN DWORD Bitmap,
  920. IN PFILEDIRPARM pFDParm
  921. )
  922. {
  923. AFPSTATUS Status = STATUS_SUCCESS;
  924. DWORD SizeNeeded;
  925. PISECURITY_DESCRIPTOR pSecDesc;
  926. PBYTE pAbsSecDesc = NULL; // Used in conversion of
  927. // sec descriptor to
  928. // absolute format
  929. SECURITY_INFORMATION SecInfo = DACL_SECURITY_INFORMATION;
  930. PSID pSidOwner = NULL, pSidGroup = NULL;
  931. PSID pSidOldOwner, pSidOldGroup;
  932. BOOLEAN SawOwnerAce = False, SawGroupAce = False;
  933. BOOLEAN OwnerIsWorld = False, GroupIsWorld = False;
  934. BOOLEAN fDir = IsDir(pFDParm);
  935. PACL pDaclNew = NULL;
  936. PACCESS_ALLOWED_ACE pAce;
  937. LONG SizeNewDacl;
  938. #ifdef PROFILING
  939. TIME TimeS, TimeE, TimeD;
  940. #endif
  941. PAGED_CODE( );
  942. #ifdef PROFILING
  943. INTERLOCKED_INCREMENT_LONG(&AfpServerProfile->perf_SetPermsCount);
  944. AfpGetPerfCounter(&TimeS);
  945. #endif
  946. do
  947. {
  948. // Read the security descriptor for this directory
  949. SizeNeeded = 4096 - POOL_OVERHEAD;
  950. pSecDesc = NULL;
  951. do
  952. {
  953. if (pSecDesc != NULL)
  954. {
  955. AfpFreeMemory(pSecDesc);
  956. }
  957. SizeNewDacl = SizeNeeded;
  958. if ((pSecDesc = (PSECURITY_DESCRIPTOR)ALLOC_ACCESS_MEM(SizeNeeded)) == NULL)
  959. {
  960. Status = AFP_ERR_MISC;
  961. break;
  962. }
  963. Status = NtQuerySecurityObject(DirHandle,
  964. OWNER_SECURITY_INFORMATION |
  965. GROUP_SECURITY_INFORMATION |
  966. DACL_SECURITY_INFORMATION,
  967. pSecDesc,
  968. SizeNeeded,
  969. &SizeNeeded);
  970. } while ((Status != STATUS_SUCCESS) &&
  971. ((Status == STATUS_BUFFER_TOO_SMALL) ||
  972. (Status == STATUS_BUFFER_OVERFLOW) ||
  973. (Status == STATUS_MORE_ENTRIES)));
  974. if (!NT_SUCCESS(Status))
  975. {
  976. Status = AfpIoConvertNTStatusToAfpStatus(Status);
  977. break;
  978. }
  979. pSecDesc = (PISECURITY_DESCRIPTOR)((PBYTE)pSecDesc);
  980. // If the security descriptor is in self-relative form, convert to absolute
  981. if (pSecDesc->Control & SE_SELF_RELATIVE)
  982. {
  983. DWORD AbsoluteSizeNeeded;
  984. // An absolute SD is not necessarily the same size as a relative
  985. // SD, so an in-place conversion may not be possible.
  986. AbsoluteSizeNeeded = SizeNeeded;
  987. Status = RtlSelfRelativeToAbsoluteSD2(pSecDesc, &AbsoluteSizeNeeded);
  988. if (Status == STATUS_BUFFER_TOO_SMALL)
  989. {
  990. // Allocate a new buffer in which to store the absolute
  991. // security descriptor, copy the contents of the relative
  992. // descriptor in and try again
  993. pAbsSecDesc = (PBYTE)ALLOC_ACCESS_MEM(AbsoluteSizeNeeded);
  994. if (pAbsSecDesc == NULL)
  995. {
  996. Status = STATUS_NO_MEMORY;
  997. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_ERR,
  998. ("AfpSetAfpPermissions: ALLOC_ACCESS_MEM 2 error\n"));
  999. }
  1000. else
  1001. {
  1002. RtlCopyMemory(pAbsSecDesc, pSecDesc, SizeNeeded);
  1003. Status = RtlSelfRelativeToAbsoluteSD2 (pAbsSecDesc,
  1004. &AbsoluteSizeNeeded);
  1005. if (NT_SUCCESS(Status))
  1006. {
  1007. // We don't need relative form anymore,
  1008. // we will work with the Absolute form
  1009. if (pSecDesc != NULL)
  1010. {
  1011. AfpFreeMemory(pSecDesc);
  1012. }
  1013. pSecDesc = (PISECURITY_DESCRIPTOR)pAbsSecDesc;
  1014. }
  1015. else
  1016. {
  1017. // We cannot use Absolute Form, throw it away
  1018. AfpFreeMemory(pAbsSecDesc);
  1019. pAbsSecDesc = NULL;
  1020. }
  1021. }
  1022. }
  1023. if (!NT_SUCCESS(Status))
  1024. {
  1025. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_ERR,
  1026. ("AfpSetAfpPermissions: RtlSelfRelativeToAbsoluteSD2: returned error %lx\n", Status));
  1027. break;
  1028. }
  1029. SizeNeeded = AbsoluteSizeNeeded;
  1030. }
  1031. SizeNewDacl = SizeNeeded;
  1032. // Add SE_DACL_AUTO_INHERIT_REQ
  1033. pSecDesc->Control |= SE_DACL_AUTO_INHERIT_REQ;
  1034. // Save the old Owner and Group Sids
  1035. pSidOldOwner = pSecDesc->Owner;
  1036. pSidOldGroup = pSecDesc->Group;
  1037. // Convert the owner/group ids, if any to be set to their corres. sids
  1038. if (Bitmap & DIR_BITMAP_OWNERID)
  1039. {
  1040. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  1041. ("AfpSetAfpPermissions: Setting Owner to ID %lx\n",
  1042. pFDParm->_fdp_OwnerId));
  1043. if (AfpMacIdToSid(pFDParm->_fdp_OwnerId, &pSidOwner) != STATUS_SUCCESS)
  1044. {
  1045. Status = AFP_ERR_MISC;
  1046. break;
  1047. }
  1048. // Don't allow owner sid to be set as the NULL sid, or
  1049. // to what it is presently set to
  1050. if (!RtlEqualSid(pSecDesc->Owner, pSidOwner) &&
  1051. !RtlEqualSid(&AfpSidNull, pSidOwner))
  1052. {
  1053. AfpDumpSid("AfpSetAfpPermissions: Setting Owner Sid to ", pSidOwner);
  1054. pSecDesc->Owner = pSidOwner;
  1055. SecInfo |= OWNER_SECURITY_INFORMATION;
  1056. }
  1057. }
  1058. if (Bitmap & DIR_BITMAP_GROUPID)
  1059. {
  1060. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  1061. ("AfpSetAfpPermissions: Setting Group to ID %lx\n",
  1062. pFDParm->_fdp_GroupId));
  1063. if (AfpMacIdToSid(pFDParm->_fdp_GroupId, &pSidGroup) != STATUS_SUCCESS)
  1064. {
  1065. Status = AFP_ERR_MISC;
  1066. break;
  1067. }
  1068. // Don't allow group sid to be set as the NULL or None sid, or
  1069. // to what it is presently set to
  1070. if (!RtlEqualSid(pSecDesc->Group, pSidGroup) &&
  1071. !RtlEqualSid(&AfpSidNull, pSidGroup) &&
  1072. (!AfpServerIsStandalone || !RtlEqualSid(AfpSidNone, pSidGroup)))
  1073. {
  1074. AfpDumpSid("AfpSetAfpPermissions: Setting Group Sid to ", pSidGroup);
  1075. pSecDesc->Group = pSidGroup;
  1076. SecInfo |= GROUP_SECURITY_INFORMATION;
  1077. }
  1078. }
  1079. // If either the owner or group or both is 'EveryOne' then coalesce the
  1080. // permissions
  1081. if (RtlEqualSid(pSecDesc->Owner, pSecDesc->Group))
  1082. {
  1083. pFDParm->_fdp_OwnerRights |= pFDParm->_fdp_GroupRights;
  1084. pFDParm->_fdp_GroupRights |= pFDParm->_fdp_OwnerRights;
  1085. }
  1086. if (RtlEqualSid(pSecDesc->Owner, &AfpSidWorld))
  1087. {
  1088. pFDParm->_fdp_WorldRights |= (pFDParm->_fdp_OwnerRights | DIR_ACCESS_OWNER);
  1089. OwnerIsWorld = True;
  1090. }
  1091. if (RtlEqualSid(pSecDesc->Group, &AfpSidWorld))
  1092. {
  1093. pFDParm->_fdp_WorldRights |= pFDParm->_fdp_GroupRights;
  1094. GroupIsWorld = True;
  1095. }
  1096. // Construct the new Dacl. This consists of Aces for World, Owner and Group
  1097. // followed by Old Aces for everybody else, but with Aces for World, OldOwner
  1098. // and OldGroup stripped out. First determine space for the new Dacl and
  1099. // allocated space for the new Dacl. Lets be exteremely conservative. We
  1100. // have two aces each for owner/group/world.
  1101. SizeNewDacl +=
  1102. (RtlLengthSid(pSecDesc->Owner) + sizeof(ACCESS_ALLOWED_ACE) +
  1103. RtlLengthSid(pSecDesc->Group) + sizeof(ACCESS_ALLOWED_ACE) +
  1104. sizeof(AfpSidSystem) + sizeof(ACCESS_ALLOWED_ACE) +
  1105. sizeof(AfpSidWorld) + sizeof(ACCESS_ALLOWED_ACE)) * 2;
  1106. if ((pDaclNew = (PACL)ALLOC_ACCESS_MEM(SizeNewDacl)) == NULL)
  1107. {
  1108. Status = AFP_ERR_MISC;
  1109. break;
  1110. }
  1111. RtlCreateAcl(pDaclNew, SizeNewDacl, ACL_REVISION);
  1112. // we will be adding to this as we add aces, so set it to the min here
  1113. pDaclNew->AclSize = sizeof(ACL);
  1114. pAce = (PACCESS_ALLOWED_ACE)((PBYTE)pDaclNew + sizeof(ACL));
  1115. // At this time the Acl list is empty, i.e. no access for anybody
  1116. // Start off by copying the Explicit/Non-inherited Deny Aces from
  1117. // the original Dacl list
  1118. // weeding out the Aces for World, old and new owner, new and old
  1119. // group, creator owner and creator group
  1120. if (pSecDesc->Dacl != NULL)
  1121. {
  1122. pAce = afpMoveAces(pSecDesc->Dacl,
  1123. pAce,
  1124. pSidOldOwner,
  1125. pSecDesc->Owner,
  1126. pSidOldGroup,
  1127. pSecDesc->Group,
  1128. True,
  1129. False,
  1130. pDaclNew);
  1131. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  1132. ("AfpSetAfpPermissions: Added (%d) old Non-inherited Deny Aces\n",
  1133. pDaclNew->AceCount));
  1134. ASSERT(((PBYTE)pAce - (PBYTE)pDaclNew) < SizeNewDacl);
  1135. }
  1136. // Now add Allowed Aces for System, World, Group & Owner - in that order
  1137. pAce = afpAddAceToAcl(pDaclNew,
  1138. pAce,
  1139. AFP_READ_ACCESS | AFP_WRITE_ACCESS | AFP_OWNER_ACCESS,
  1140. &AfpSidSystem,
  1141. fDir);
  1142. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  1143. ("AfpSetAfpPermissions: Added Aces for System (%d)\n",
  1144. pDaclNew->AceCount));
  1145. ASSERT(((PBYTE)pAce - (PBYTE)pDaclNew) < SizeNewDacl);
  1146. // Now add Ace for World
  1147. pAce = afpAddAceToAcl(pDaclNew,
  1148. pAce,
  1149. afpPermissions2NtMask(pFDParm->_fdp_WorldRights),
  1150. &AfpSidWorld,
  1151. fDir);
  1152. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  1153. ("AfpSetAfpPermissions: Added Aces for World (%d)\n",
  1154. pDaclNew->AceCount));
  1155. ASSERT(((PBYTE)pAce - (PBYTE)pDaclNew) < SizeNewDacl);
  1156. // Now add Ace for Group
  1157. if (!GroupIsWorld &&
  1158. !RtlEqualSid(pSecDesc->Group, &AfpSidNull) &&
  1159. (!AfpServerIsStandalone || !RtlEqualSid(pSecDesc->Group, AfpSidNone)))
  1160. {
  1161. pAce = afpAddAceToAcl(pDaclNew,
  1162. pAce,
  1163. afpPermissions2NtMask(pFDParm->_fdp_GroupRights),
  1164. pSecDesc->Group,
  1165. fDir);
  1166. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  1167. ("AfpSetAfpPermissions: Added Aces for Group (%d)\n",
  1168. pDaclNew->AceCount));
  1169. ASSERT(((PBYTE)pAce - (PBYTE)pDaclNew) < SizeNewDacl);
  1170. }
  1171. if (!OwnerIsWorld && !RtlEqualSid(pSecDesc->Owner, &AfpSidNull))
  1172. {
  1173. pFDParm->_fdp_OwnerRights |= DIR_ACCESS_OWNER;
  1174. pAce = afpAddAceToAcl(pDaclNew,
  1175. pAce,
  1176. afpPermissions2NtMask(pFDParm->_fdp_OwnerRights),
  1177. pSecDesc->Owner,
  1178. fDir);
  1179. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  1180. ("AfpSetAfpPermissions: Added Aces for Owner (%d)\n",
  1181. pDaclNew->AceCount));
  1182. ASSERT(((PBYTE)pAce - (PBYTE)pDaclNew) < SizeNewDacl);
  1183. }
  1184. // Now add in the Explicit/Non-inherited Grant Aces from the
  1185. // original Dacl list weeding out
  1186. // the Aces for World, old and new owner, new and old group, creator
  1187. // owner and creator group
  1188. if (pSecDesc->Dacl != NULL)
  1189. {
  1190. pAce = afpMoveAces(pSecDesc->Dacl,
  1191. pAce,
  1192. pSidOldOwner,
  1193. pSecDesc->Owner,
  1194. pSidOldGroup,
  1195. pSecDesc->Group,
  1196. False,
  1197. False,
  1198. pDaclNew);
  1199. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  1200. ("AfpSetAfpPermissions: Added (%d) old Non-inherited Grant Aces\n",
  1201. pDaclNew->AceCount));
  1202. ASSERT(((PBYTE)pAce - (PBYTE)pDaclNew) < SizeNewDacl);
  1203. }
  1204. // Now add in the Non-explicit/Inherited Deny Aces from
  1205. // the original Dacl list
  1206. // weeding out the Aces for World, old and new owner, new and old
  1207. // group, creator owner and creator group
  1208. if (pSecDesc->Dacl != NULL)
  1209. {
  1210. pAce = afpMoveAces(pSecDesc->Dacl,
  1211. pAce,
  1212. pSidOldOwner,
  1213. pSecDesc->Owner,
  1214. pSidOldGroup,
  1215. pSecDesc->Group,
  1216. True,
  1217. True,
  1218. pDaclNew);
  1219. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  1220. ("AfpSetAfpPermissions: Added (%d) old Inherited Deny Aces\n",
  1221. pDaclNew->AceCount));
  1222. ASSERT(((PBYTE)pAce - (PBYTE)pDaclNew) < SizeNewDacl);
  1223. }
  1224. // Now add in the Explicit/Non-inherited Grant Aces from the
  1225. // original Dacl list weeding out
  1226. // the Aces for World, old and new owner, new and old group, creator
  1227. // owner and creator group
  1228. if (pSecDesc->Dacl != NULL)
  1229. {
  1230. pAce = afpMoveAces(pSecDesc->Dacl,
  1231. pAce,
  1232. pSidOldOwner,
  1233. pSecDesc->Owner,
  1234. pSidOldGroup,
  1235. pSecDesc->Group,
  1236. False,
  1237. True,
  1238. pDaclNew);
  1239. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  1240. ("AfpSetAfpPermissions: Added (%d) old Inherited Grant Aces (%d)\n",
  1241. pDaclNew->AceCount));
  1242. ASSERT(((PBYTE)pAce - (PBYTE)pDaclNew) < SizeNewDacl);
  1243. }
  1244. // Now set the new security descriptor
  1245. pSecDesc->Dacl = pDaclNew;
  1246. // We need to impersonate the FspToken while we do this
  1247. AfpImpersonateClient(NULL);
  1248. Status = NtSetSecurityObject(DirHandle, SecInfo, pSecDesc);
  1249. if (!NT_SUCCESS(Status))
  1250. Status = AfpIoConvertNTStatusToAfpStatus(Status);
  1251. AfpRevertBack();
  1252. } while (False);
  1253. // Free the allocated buffers before we return
  1254. if (pSecDesc != NULL)
  1255. AfpFreeMemory(pSecDesc);
  1256. if (pDaclNew != NULL)
  1257. AfpFreeMemory(pDaclNew);
  1258. #ifdef PROFILING
  1259. AfpGetPerfCounter(&TimeE);
  1260. TimeD.QuadPart = TimeE.QuadPart - TimeS.QuadPart;
  1261. INTERLOCKED_ADD_LARGE_INTGR(&AfpServerProfile->perf_SetPermsTime,
  1262. TimeD,
  1263. &AfpStatisticsLock);
  1264. #endif
  1265. return Status;
  1266. }
  1267. /*** afpPermissions2NtMask
  1268. *
  1269. * Map Afp permissions to Nt access mask. FILE_DELETE_CHILD is added ONLY
  1270. * when all the Afp bits are set. This is in line with the FileManager
  1271. * which only sets this bit if "Full Control" is specified. Also under
  1272. * NT security model, FILE_DELETE_CHILD overrides any child access control
  1273. * as far as the ability to delete that entity goes.
  1274. */
  1275. LOCAL ACCESS_MASK
  1276. afpPermissions2NtMask(
  1277. IN BYTE AfpPermissions
  1278. )
  1279. {
  1280. ACCESS_MASK NtAccess = 0;
  1281. PAGED_CODE( );
  1282. if (AfpPermissions & DIR_ACCESS_OWNER)
  1283. NtAccess |= AFP_OWNER_ACCESS;
  1284. if ((AfpPermissions & DIR_ACCESS_ALL) == DIR_ACCESS_ALL)
  1285. NtAccess |= AFP_READ_ACCESS | AFP_WRITE_ACCESS | FILE_DELETE_CHILD;
  1286. else
  1287. {
  1288. if (AfpPermissions & (DIR_ACCESS_READ | DIR_ACCESS_SEARCH))
  1289. NtAccess |= AFP_READ_ACCESS;
  1290. if (AfpPermissions & DIR_ACCESS_WRITE)
  1291. NtAccess |= AFP_WRITE_ACCESS;
  1292. }
  1293. return NtAccess;
  1294. }
  1295. /*** afpAddAceToAcl
  1296. *
  1297. * Build an Ace corres. to the Sid(s) and mask and add these to the Acl. It is
  1298. * assumed that the Acl has space for the Aces. If the mask is 0 i.e. no access
  1299. * we give AFP_MIN_ACCESS. This is so that the file/dir permissions can be
  1300. * queried and a belted icon is generated instead of nothing.
  1301. */
  1302. LOCAL PACCESS_ALLOWED_ACE
  1303. afpAddAceToAcl(
  1304. IN PACL pAcl,
  1305. IN PACCESS_ALLOWED_ACE pAce,
  1306. IN ACCESS_MASK Mask,
  1307. IN PSID pSid,
  1308. IN BOOLEAN fInherit
  1309. )
  1310. {
  1311. USHORT SidLen;
  1312. PAGED_CODE( );
  1313. SidLen = (USHORT)RtlLengthSid(pSid);
  1314. // Add a vanilla ace
  1315. pAcl->AceCount ++;
  1316. pAce->Mask = Mask | SYNCHRONIZE | AFP_MIN_ACCESS;
  1317. pAce->Header.AceFlags = 0;
  1318. pAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  1319. pAce->Header.AceSize = (USHORT)(sizeof(ACE_HEADER) +
  1320. sizeof(ACCESS_MASK) +
  1321. SidLen);
  1322. RtlCopyMemory((PSID)(&pAce->SidStart), pSid, SidLen);
  1323. pAcl->AclSize += pAce->Header.AceSize;
  1324. AfpDumpSidnMask("afpAddAceToAcl ",
  1325. pSid,
  1326. pAce->Mask,
  1327. ACCESS_ALLOWED_ACE_TYPE,
  1328. pAce->Header.AceFlags);
  1329. // Now add an inherit ace
  1330. if (fInherit)
  1331. {
  1332. pAce = (PACCESS_ALLOWED_ACE)((PBYTE)pAce + pAce->Header.AceSize);
  1333. pAcl->AceCount ++;
  1334. pAce->Mask = Mask | SYNCHRONIZE | AFP_MIN_ACCESS;
  1335. pAce->Header.AceFlags = CONTAINER_INHERIT_ACE |
  1336. OBJECT_INHERIT_ACE |
  1337. INHERIT_ONLY_ACE;
  1338. pAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
  1339. pAce->Header.AceSize = (USHORT)(sizeof(ACE_HEADER) +
  1340. sizeof(ACCESS_MASK) +
  1341. SidLen);
  1342. RtlCopyMemory((PSID)(&pAce->SidStart), pSid, SidLen);
  1343. pAcl->AclSize += pAce->Header.AceSize;
  1344. AfpDumpSidnMask("afpAddAceToAcl (Inherit) ",
  1345. pSid,
  1346. pAce->Mask,
  1347. ACCESS_ALLOWED_ACE_TYPE,
  1348. pAce->Header.AceFlags);
  1349. }
  1350. return ((PACCESS_ALLOWED_ACE)((PBYTE)pAce + pAce->Header.AceSize));
  1351. }
  1352. #if DBG
  1353. /*** AfpDumpSid
  1354. *
  1355. */
  1356. VOID
  1357. AfpDumpSid(
  1358. IN PBYTE pString,
  1359. IN PISID pSid
  1360. )
  1361. {
  1362. WCHAR Buffer[128];
  1363. UNICODE_STRING SidStr;
  1364. PAGED_CODE( );
  1365. AfpSetEmptyUnicodeString(&SidStr, sizeof(Buffer), Buffer);
  1366. if ((AfpDebugComponent & DBG_COMP_SECURITY) && (DBG_LEVEL_INFO >= AfpDebugLevel))
  1367. {
  1368. RtlConvertSidToUnicodeString(&SidStr, pSid, False);
  1369. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  1370. ("%s %ws\n", pString, SidStr.Buffer));
  1371. }
  1372. }
  1373. /*** AfpDumpSidnMask
  1374. *
  1375. */
  1376. VOID
  1377. AfpDumpSidnMask(
  1378. IN PBYTE pString,
  1379. IN PISID pSid,
  1380. IN DWORD Mask,
  1381. IN UCHAR Type,
  1382. IN UCHAR Flags
  1383. )
  1384. {
  1385. WCHAR Buffer[128];
  1386. UNICODE_STRING SidStr;
  1387. PAGED_CODE( );
  1388. AfpSetEmptyUnicodeString(&SidStr, sizeof(Buffer), Buffer);
  1389. if ((AfpDebugComponent & DBG_COMP_SECURITY) && (DBG_LEVEL_INFO >= AfpDebugLevel))
  1390. {
  1391. RtlConvertSidToUnicodeString(&SidStr, pSid, False);
  1392. DBGPRINT(DBG_COMP_SECURITY, DBG_LEVEL_INFO,
  1393. ("%s Sid %ws, Mask %lx, Type %x, Flags %x\n",
  1394. pString, SidStr.Buffer, Mask, Type, Flags));
  1395. }
  1396. }
  1397. #endif