Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1361 lines
38 KiB

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