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.

1147 lines
27 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. createsd.c
  5. Abstract:
  6. Variable argument list function for creating a security descriptor
  7. Author:
  8. t-eugenz - September 2000
  9. Environment:
  10. User mode only.
  11. Revision History:
  12. Created - September 2000
  13. --*/
  14. #include "pch.h"
  15. #include "makesd.h"
  16. #include <stdarg.h>
  17. #include <stdio.h>
  18. //
  19. // ISSUE: Which public header is this in?
  20. //
  21. #define MAX_WORD 0xFFFF
  22. #define FLAG_ON(flags,bit) ((flags) & (bit))
  23. void FreeSecurityDescriptor2(
  24. IN PSECURITY_DESCRIPTOR pSd
  25. )
  26. /*++
  27. Routine Description:
  28. This frees a security descriptor created by CreateSecurityDescriptor
  29. Arguments:
  30. pSd - The pointer to the security descriptor to be freed
  31. Return Value:
  32. none
  33. --*/
  34. {
  35. ASSERT( pSd != NULL );
  36. free(pSd);
  37. }
  38. #define F_IS_DACL_ACE 0x00000001
  39. #define F_IS_CALLBACK 0x00000002
  40. #define F_IS_OBJECT 0x00000004
  41. #define F_RETURN_ALL_DATA 0x00000010
  42. typedef struct
  43. {
  44. DWORD dwFlags;
  45. ACE_HEADER pAce;
  46. ACCESS_MASK amMask;
  47. PSID pSid;
  48. DWORD dwOptDataSize;
  49. PVOID pvOptData;
  50. GUID * pgObject;
  51. GUID * pgInherit;
  52. } ACE_REQUEST_STRUCT, *PACE_REQUEST_STRUCT;
  53. BOOL GetNextAceInfo( IN OUT va_list *varArgList,
  54. IN OUT PACE_REQUEST_STRUCT pAceRequest
  55. )
  56. {
  57. DWORD dwAceSize = 0;
  58. BYTE bAceType = 0;
  59. BYTE bAceFlags = 0;
  60. DWORD amAccessMask = 0;
  61. PSID pSid = NULL;
  62. GUID * pgObject = NULL;
  63. GUID * pgInherit = NULL;
  64. DWORD dwOptDataSize = 0;
  65. PVOID pvOptData = NULL;
  66. DWORD dwErr = ERROR_SUCCESS;
  67. DWORD dwMask = 0;
  68. DWORD dwFlags = 0;
  69. //
  70. // Read the first arg to determine the ACE type,
  71. //
  72. bAceType = va_arg(*varArgList, BYTE);
  73. //
  74. // Different sets for DACL and SACL
  75. //
  76. if( pAceRequest->dwFlags & F_IS_DACL_ACE )
  77. {
  78. //
  79. // Calculate the size of the DACL ACE
  80. //
  81. switch( bAceType )
  82. {
  83. case ACCESS_ALLOWED_ACE_TYPE:
  84. dwAceSize += (
  85. sizeof(ACCESS_ALLOWED_ACE)
  86. - sizeof(DWORD)
  87. );
  88. break;
  89. case ACCESS_DENIED_ACE_TYPE:
  90. dwAceSize += (
  91. sizeof(ACCESS_DENIED_ACE)
  92. - sizeof(DWORD)
  93. );
  94. break;
  95. case ACCESS_ALLOWED_CALLBACK_ACE_TYPE:
  96. dwAceSize += (
  97. sizeof(ACCESS_ALLOWED_CALLBACK_ACE)
  98. - sizeof(DWORD)
  99. );
  100. dwFlags |= F_IS_CALLBACK;
  101. break;
  102. case ACCESS_DENIED_CALLBACK_ACE_TYPE:
  103. dwAceSize += (
  104. sizeof(ACCESS_DENIED_CALLBACK_ACE)
  105. - sizeof(DWORD)
  106. );
  107. dwFlags |= F_IS_CALLBACK;
  108. break;
  109. case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
  110. dwAceSize += (
  111. sizeof(ACCESS_ALLOWED_OBJECT_ACE)
  112. - sizeof(DWORD)
  113. - 2 * sizeof(GUID)
  114. );
  115. dwFlags |= F_IS_OBJECT;
  116. break;
  117. case ACCESS_DENIED_OBJECT_ACE_TYPE:
  118. dwAceSize += (
  119. sizeof(ACCESS_DENIED_OBJECT_ACE)
  120. - sizeof(DWORD)
  121. - 2 * sizeof(GUID)
  122. );
  123. dwFlags |= F_IS_OBJECT;
  124. break;
  125. case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE:
  126. dwAceSize += (
  127. sizeof(ACCESS_ALLOWED_CALLBACK_OBJECT_ACE)
  128. - sizeof(DWORD)
  129. - 2 * sizeof(GUID)
  130. );
  131. dwFlags |= F_IS_OBJECT;
  132. dwFlags |= F_IS_CALLBACK;
  133. break;
  134. case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE:
  135. dwAceSize += (
  136. sizeof(ACCESS_DENIED_CALLBACK_OBJECT_ACE)
  137. - sizeof(DWORD)
  138. - 2 * sizeof(GUID)
  139. );
  140. dwFlags |= F_IS_OBJECT;
  141. dwFlags |= F_IS_CALLBACK;
  142. break;
  143. default:
  144. dwErr = ERROR_INVALID_PARAMETER;
  145. goto error;
  146. }
  147. }
  148. else
  149. {
  150. switch( bAceType )
  151. {
  152. case SYSTEM_AUDIT_ACE_TYPE:
  153. dwAceSize += (
  154. sizeof(SYSTEM_AUDIT_ACE)
  155. - sizeof(DWORD)
  156. );
  157. break;
  158. case SYSTEM_AUDIT_CALLBACK_ACE_TYPE:
  159. dwAceSize += (
  160. sizeof(SYSTEM_AUDIT_CALLBACK_ACE)
  161. - sizeof(DWORD)
  162. );
  163. dwFlags |= F_IS_CALLBACK;
  164. break;
  165. case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
  166. dwAceSize += (
  167. sizeof(SYSTEM_AUDIT_OBJECT_ACE)
  168. - sizeof(DWORD)
  169. - 2 * sizeof(GUID)
  170. );
  171. dwFlags |= F_IS_OBJECT;
  172. break;
  173. case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE:
  174. dwAceSize += (
  175. sizeof(SYSTEM_AUDIT_CALLBACK_OBJECT_ACE)
  176. - sizeof(DWORD)
  177. - 2 * sizeof(GUID)
  178. );
  179. dwFlags |= F_IS_OBJECT;
  180. dwFlags |= F_IS_CALLBACK;
  181. break;
  182. default:
  183. dwErr = ERROR_INVALID_PARAMETER;
  184. goto error;
  185. }
  186. }
  187. //
  188. // Now we know the arguments contained
  189. //
  190. //
  191. // The flags
  192. //
  193. bAceFlags = va_arg(*varArgList, BYTE);
  194. //
  195. // The SID
  196. //
  197. pSid = va_arg(*varArgList, PSID);
  198. dwAceSize += GetLengthSid( pSid );
  199. //
  200. // Access mask
  201. //
  202. amAccessMask = va_arg(*varArgList, ACCESS_MASK);
  203. //
  204. // If callback, next two arguments are optional data size and data
  205. //
  206. if( dwFlags & F_IS_CALLBACK )
  207. {
  208. dwOptDataSize = va_arg(*varArgList, DWORD);
  209. pvOptData = va_arg(*varArgList, PVOID);
  210. dwAceSize += dwOptDataSize;
  211. }
  212. //
  213. // May contain GUIDs if object ACE
  214. //
  215. if( dwFlags & F_IS_OBJECT )
  216. {
  217. //
  218. // Up to 2 GUIDs if both are not NULL
  219. //
  220. pgObject = va_arg(*varArgList, GUID *);
  221. pgInherit = va_arg(*varArgList, GUID *);
  222. if( pgObject != NULL )
  223. {
  224. dwAceSize += sizeof(GUID);
  225. }
  226. if( pgInherit != NULL )
  227. {
  228. dwAceSize += sizeof(GUID);
  229. }
  230. }
  231. //
  232. // Finally, verify the ACE is within max size
  233. //
  234. if( dwAceSize > MAX_WORD )
  235. {
  236. dwErr = ERROR_INVALID_PARAMETER;
  237. }
  238. error:;
  239. if( dwErr != ERROR_SUCCESS )
  240. {
  241. SetLastError(dwErr);
  242. return 0;
  243. }
  244. else
  245. {
  246. //
  247. // Fill in the requested return values
  248. //
  249. if( pAceRequest->dwFlags & F_RETURN_ALL_DATA )
  250. {
  251. pAceRequest->dwFlags = dwFlags;
  252. pAceRequest->pAce.AceFlags = bAceFlags;
  253. pAceRequest->pAce.AceSize = (WORD)dwAceSize;
  254. pAceRequest->pAce.AceType = bAceType;
  255. pAceRequest->amMask = amAccessMask;
  256. pAceRequest->pSid = pSid;
  257. if( dwFlags & F_IS_CALLBACK )
  258. {
  259. pAceRequest->dwOptDataSize = dwOptDataSize;
  260. pAceRequest->pvOptData = pvOptData;
  261. }
  262. if( dwFlags & F_IS_OBJECT )
  263. {
  264. pAceRequest->pgObject = pgObject;
  265. pAceRequest->pgInherit = pgInherit;
  266. }
  267. }
  268. return dwAceSize;
  269. }
  270. }
  271. BOOL
  272. WINAPI
  273. CreateSecurityDescriptor2(
  274. OUT PSECURITY_DESCRIPTOR * ppSd,
  275. IN const DWORD dwOptions,
  276. IN const SECURITY_DESCRIPTOR_CONTROL sControl,
  277. IN const PSID psOwner,
  278. IN const PSID psGroup,
  279. IN const DWORD dwNumDaclAces,
  280. IN const DWORD dwNumSaclAces,
  281. ...
  282. )
  283. /*++
  284. Routine Description:
  285. Creates a security descriptor with a DACL and a SACL using a variable
  286. argument list as input. Following the above fixed arguments, the ACEs
  287. should be specified by using 4 arguments for any ACE, with 2 additional
  288. arguments if the ACE is a callback, and 2 more arguments if it's an
  289. object ACE.
  290. Any number of ACEs can be specified. First, dwNumDaclAces
  291. ACEs will be read into the DACL for the security descriptor, then
  292. dwNumSaclAces will be read into the SACL.
  293. ACCESS_ALLOWED_ACE, ACCESS_DENIED_ACE: 4 arguments in this sequence
  294. BYTE bAceType - The ACE type
  295. BYTE bAceFlags - The ACE flags
  296. PSID pSid - The SID for the ACE
  297. ACCESS_MASK amMask - The access mask for the ACE
  298. Callback ACEs have the above 4 arguments, and 2 additional arguments
  299. which immediately follow the above:
  300. DWORD dwOptDataSize - The size (in bytes) of the optional
  301. data to be appended to the end of the ACE
  302. PVOID pvOptData - Pointer to the optional data
  303. Object ACEs have the appropriate arguments from above, and 2 additional
  304. arguments:
  305. GUID * pgObjectType - Pointer to the object guid, or NULL for none
  306. GUID * pgInheritType - Pointer to the inheritance guid, or NULL
  307. for none
  308. ISSUE: Should ACE flags be verified? SIDs?
  309. Should ACL size be verified, since max ACL size is a SHORT?
  310. Arguments:
  311. ppSd - The pointer to the allocated security descriptor is
  312. stored here, and should be freed using
  313. FreeSecurityDescriptor()
  314. sControl - Only allowed bits are
  315. SE_DACL_AUTO_INHERITED
  316. SE_SACL_AUTO_INHERITED
  317. SE_SACL_PROTECTED
  318. psOwner - SID of the owner for the security descriptor
  319. psGroup - SID of the group for the security descriptor
  320. bDaclPresent - Whether the DACL should be non-NULL
  321. If this is FALSE, no ACEs should be passed in the
  322. variable args section for the DACL.
  323. dwNumDaclAces - Number of ACEs in the variable arguments for the DACL
  324. bSaclPresent - Whether the SACL should be non-NULL
  325. If this is FALSE, no ACEs should be passed in the
  326. variable args section for the SACL.
  327. dwNumSaclAces - Number of ACEs in the variable arguments for the SACL
  328. ... - The rest of the arguments for the ACEs, variable list
  329. Return Value:
  330. TRUE on success
  331. FALSE on failure, more information available with GetLastError()
  332. --*/
  333. {
  334. DWORD dwIdx = 0;
  335. DWORD dwTmp = 0;
  336. DWORD dwTempFlags = 0;
  337. //
  338. // Size of the security descriptor and ACLs
  339. //
  340. DWORD dwSizeSd = 0;
  341. DWORD dwDaclSize = 0;
  342. DWORD dwSaclSize = 0;
  343. //
  344. // Start of the security descriptor, must be a pointer
  345. // to a type with sizeof(type) = 1, such as BYTE, so that
  346. // adding a size offset will work.
  347. //
  348. PBYTE pSd = NULL;
  349. //
  350. // Current offset in the security descriptor, incremented while filling
  351. // in the security descriptor
  352. //
  353. DWORD dwCurOffset = 0;
  354. //
  355. // Temporary ACL header
  356. //
  357. ACL aclTemp;
  358. //
  359. // Output for the GetNextAceInfo
  360. //
  361. ACE_REQUEST_STRUCT AceRequest;
  362. //
  363. // Variable argument list
  364. //
  365. va_list varArgList;
  366. BOOL bArglistStarted = FALSE;
  367. DWORD dwErr = ERROR_SUCCESS;
  368. //
  369. // Verify the arguments we can verify
  370. //
  371. if( ( ppSd == NULL )
  372. || ( sControl & ~( SE_DACL_AUTO_INHERITED
  373. | SE_SACL_AUTO_INHERITED
  374. | SE_SACL_PROTECTED ) )
  375. || ( !FLAG_ON( dwOptions, CREATE_SD_DACL_PRESENT) && (dwNumDaclAces != 0))
  376. || ( !FLAG_ON( dwOptions, CREATE_SD_SACL_PRESENT) && (dwNumSaclAces != 0))
  377. || ( dwNumDaclAces > MAX_WORD )
  378. || ( dwNumSaclAces > MAX_WORD ) )
  379. {
  380. dwErr = ERROR_INVALID_PARAMETER;
  381. goto error;
  382. }
  383. //
  384. // First, we need to calculate the size of the security descriptor and the
  385. // ACLs, if any
  386. //
  387. pSd = NULL;
  388. dwSizeSd = sizeof(SECURITY_DESCRIPTOR);
  389. dwDaclSize = 0;
  390. dwSaclSize = 0;
  391. if( psOwner != NULL )
  392. {
  393. dwSizeSd += GetLengthSid(psOwner);
  394. }
  395. if( psGroup != NULL )
  396. {
  397. dwSizeSd += GetLengthSid(psGroup);
  398. }
  399. //
  400. // Start the variable args with the last non-varibale arg
  401. //
  402. va_start(varArgList, dwNumSaclAces);
  403. bArglistStarted = TRUE;
  404. //
  405. // Calculate the sizes of the DACL ACEs and the DACL itself
  406. //
  407. if ( FLAG_ON( dwOptions, CREATE_SD_DACL_PRESENT ))
  408. {
  409. dwDaclSize += sizeof(ACL);
  410. //
  411. // Now add all the ACEs (including SIDs)
  412. //
  413. for( dwIdx = 0; dwIdx < dwNumDaclAces; dwIdx++ )
  414. {
  415. //
  416. // Request next DACL ACE type, no additional data
  417. //
  418. AceRequest.dwFlags = F_IS_DACL_ACE;
  419. dwTmp = GetNextAceInfo( &varArgList, &AceRequest );
  420. if( dwTmp == 0 )
  421. {
  422. dwErr = ERROR_INVALID_PARAMETER;
  423. goto error;
  424. }
  425. else
  426. {
  427. dwDaclSize += dwTmp;
  428. }
  429. }
  430. }
  431. //
  432. // Calculate the sizes of the SACL ACEs and the SACL itself
  433. //
  434. if ( FLAG_ON( dwOptions, CREATE_SD_SACL_PRESENT ))
  435. {
  436. dwSaclSize += sizeof(ACL);
  437. //
  438. // Now add all the ACEs (including SIDs)
  439. //
  440. for( dwIdx = 0; dwIdx < dwNumSaclAces; dwIdx++ )
  441. {
  442. //
  443. // Request next SACL ACE type, no additional data
  444. //
  445. AceRequest.dwFlags = 0;
  446. dwTmp = GetNextAceInfo( &varArgList, &AceRequest );
  447. if( dwTmp == 0 )
  448. {
  449. dwErr = ERROR_INVALID_PARAMETER;
  450. goto error;
  451. }
  452. else
  453. {
  454. dwSaclSize += dwTmp;
  455. }
  456. }
  457. }
  458. //
  459. // Done with first pass through argument list
  460. //
  461. va_end(varArgList);
  462. bArglistStarted = FALSE;
  463. //
  464. // Verify that the ACLs will fit in the size limits (since ACL size
  465. // is a WORD)
  466. //
  467. if( ( dwDaclSize > MAX_WORD )
  468. || ( dwSaclSize > MAX_WORD ) )
  469. {
  470. dwErr = ERROR_INVALID_PARAMETER;
  471. goto error;
  472. }
  473. //
  474. // At this point we know the size of the security descriptor,
  475. // which is the sum of dwSizeSd, dwDaclSize, and dwSaclSize.
  476. // Therefore, we can allocate the memory and determine the offsets of
  477. // the two ACLs in the security descriptor, which will be self-relative.
  478. //
  479. pSd = malloc( dwSizeSd + dwDaclSize + dwSaclSize );
  480. if( pSd == NULL )
  481. {
  482. *ppSd = NULL;
  483. SetLastError(ERROR_OUTOFMEMORY);
  484. return FALSE;
  485. }
  486. //
  487. // Everything resides in the same memory block, so we can simply walk the
  488. // memory block and fill it in. We start just past the end of the
  489. // fixed size security descriptor structure. As we copy things into this
  490. // memory blocks, we also initialize the matching offsets in the
  491. // SECURITY_DESCRIPTOR (which is at the head of the block)
  492. //
  493. //
  494. // Revision
  495. //
  496. ((SECURITY_DESCRIPTOR *)pSd)->Revision = SECURITY_DESCRIPTOR_REVISION;
  497. //
  498. // Padding
  499. //
  500. ((SECURITY_DESCRIPTOR *)pSd)->Sbz1 = 0;
  501. //
  502. // SECURITY_DESCRIPTOR_CONTROL should reflect the fact that it is
  503. // self-relative. DACL and SACL are always present and not defaulted,
  504. // thought they may be NULL. User-specified inheritance flags are
  505. // also considered. The SD must be self relative. sControl is
  506. // verified earlier
  507. //
  508. ((SECURITY_DESCRIPTOR *)pSd)->Control = sControl
  509. | SE_DACL_PRESENT
  510. | SE_SACL_PRESENT
  511. | SE_SELF_RELATIVE;
  512. //
  513. // We start with the owner SID, which is right after the SECURITY_DESCRIPTOR
  514. // structure
  515. //
  516. dwCurOffset = sizeof(SECURITY_DESCRIPTOR);
  517. if( psOwner == NULL )
  518. {
  519. ((SECURITY_DESCRIPTOR *)pSd)->Owner = NULL;
  520. }
  521. else
  522. {
  523. ((SECURITY_DESCRIPTOR *)pSd)->Owner = (PSID)dwCurOffset;
  524. dwTmp = GetLengthSid(psOwner);
  525. memcpy( pSd + dwCurOffset, psOwner, dwTmp );
  526. dwCurOffset += dwTmp;
  527. }
  528. //
  529. // Following that, the group SID
  530. //
  531. if( psGroup == NULL )
  532. {
  533. ((SECURITY_DESCRIPTOR *)pSd)->Group = NULL;
  534. }
  535. else
  536. {
  537. ((SECURITY_DESCRIPTOR *)pSd)->Group = (PSID)dwCurOffset;
  538. dwTmp = GetLengthSid(psGroup);
  539. memcpy( pSd + dwCurOffset, psGroup, dwTmp );
  540. dwCurOffset += dwTmp;
  541. }
  542. //
  543. // Second pass through the optional arguments, this time
  544. // we copy the given ACEs into the security descriptor
  545. //
  546. va_start(varArgList, dwNumSaclAces);
  547. bArglistStarted = TRUE;
  548. //
  549. // Now we handle the DACL. If the DACL is not present, offset is NULL.
  550. // Otherwise, even if 0 ACEs, add the ACL structure
  551. //
  552. // ISSUE: In self-relative SD, is a 0 offset enough for no ACL, or must
  553. // the SE_DACL_PRESENT flag not be set?
  554. //
  555. if ( !FLAG_ON( dwOptions, CREATE_SD_DACL_PRESENT ))
  556. {
  557. ((SECURITY_DESCRIPTOR *)pSd)->Dacl = NULL;
  558. }
  559. else
  560. {
  561. //
  562. // Set the DACL offset to the current offset
  563. //
  564. ((SECURITY_DESCRIPTOR *)pSd)->Dacl = (PACL)dwCurOffset;
  565. //
  566. // First, copy in the ACL structure as the header
  567. //
  568. aclTemp.AceCount = (WORD)dwNumDaclAces;
  569. aclTemp.AclRevision = ACL_REVISION_DS;
  570. aclTemp.AclSize = (SHORT)dwDaclSize;
  571. aclTemp.Sbz1 = 0;
  572. aclTemp.Sbz2 = 0;
  573. memcpy( pSd + dwCurOffset, &aclTemp, sizeof(ACL) );
  574. dwCurOffset += sizeof(ACL);
  575. //
  576. // Now go through all the optional arguments for the DACL
  577. // and add the matching ACEs
  578. //
  579. for( dwIdx = 0; dwIdx < dwNumDaclAces; dwIdx++ )
  580. {
  581. //
  582. // This time, retrieve all the data
  583. //
  584. AceRequest.dwFlags = F_IS_DACL_ACE | F_RETURN_ALL_DATA;
  585. dwTmp = GetNextAceInfo( &varArgList, &AceRequest );
  586. if( dwTmp == 0 )
  587. {
  588. dwErr = GetLastError();
  589. goto error;
  590. }
  591. //
  592. // The ACE header is already filled in, and contains the ACE size
  593. //
  594. memcpy( pSd + dwCurOffset, &(AceRequest.pAce), sizeof(ACE_HEADER) );
  595. dwCurOffset += sizeof(ACE_HEADER);
  596. //
  597. // Set the access mask
  598. //
  599. *((PACCESS_MASK)( pSd + dwCurOffset )) = AceRequest.amMask;
  600. dwCurOffset += sizeof(ACCESS_MASK);
  601. //
  602. // If object ACE, set the object flags and GUIDs
  603. //
  604. if( AceRequest.dwFlags & F_IS_OBJECT )
  605. {
  606. dwTmp = 0;
  607. if( AceRequest.pgObject != NULL )
  608. {
  609. dwTmp |= ACE_OBJECT_TYPE_PRESENT;
  610. }
  611. if( AceRequest.pgInherit != NULL )
  612. {
  613. dwTmp |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
  614. }
  615. //
  616. // Set the object ACE flags
  617. //
  618. *((PDWORD)(pSd + dwCurOffset )) = dwTmp;
  619. dwCurOffset += sizeof(DWORD);
  620. //
  621. // Copy the GUIDs, if any
  622. //
  623. if( AceRequest.pgObject != NULL )
  624. {
  625. memcpy( pSd + dwCurOffset,
  626. AceRequest.pgObject,
  627. sizeof(GUID) );
  628. dwCurOffset += sizeof(GUID);
  629. }
  630. if( AceRequest.pgInherit != NULL )
  631. {
  632. memcpy( pSd + dwCurOffset,
  633. AceRequest.pgInherit,
  634. sizeof(GUID) );
  635. dwCurOffset += sizeof(GUID);
  636. }
  637. }
  638. //
  639. // Copy the SID
  640. //
  641. dwTmp = GetLengthSid( AceRequest.pSid );
  642. memcpy( pSd + dwCurOffset, AceRequest.pSid, dwTmp );
  643. dwCurOffset += dwTmp;
  644. //
  645. // If callback ACE, copy the optional data, if any
  646. //
  647. if( AceRequest.dwFlags & F_IS_CALLBACK
  648. && AceRequest.dwOptDataSize > 0 )
  649. {
  650. memcpy( pSd + dwCurOffset,
  651. AceRequest.pvOptData,
  652. AceRequest.dwOptDataSize );
  653. dwCurOffset += AceRequest.dwOptDataSize;
  654. }
  655. //
  656. // Done with the ACE
  657. //
  658. }
  659. //
  660. // Done with the DACL
  661. //
  662. }
  663. //
  664. // Now we handle the SACL
  665. //
  666. if ( !FLAG_ON( dwOptions, CREATE_SD_SACL_PRESENT ))
  667. {
  668. ((SECURITY_DESCRIPTOR *)pSd)->Sacl = NULL;
  669. }
  670. else
  671. {
  672. //
  673. // Set the SACL offset to the current offset
  674. //
  675. ((SECURITY_DESCRIPTOR *)pSd)->Sacl = (PACL)dwCurOffset;
  676. //
  677. // First, copy in the ACL structure as the header
  678. //
  679. aclTemp.AceCount = (WORD) dwNumDaclAces;
  680. aclTemp.AclRevision = ACL_REVISION_DS;
  681. aclTemp.AclSize = (WORD) dwSaclSize;
  682. aclTemp.Sbz1 = 0;
  683. aclTemp.Sbz2 = 0;
  684. memcpy( pSd + dwCurOffset, &aclTemp, sizeof(ACL) );
  685. dwCurOffset += sizeof(ACL);
  686. //
  687. // Now go through all the optional arguments for the DACL
  688. // and add the matching ACEs
  689. //
  690. for( dwIdx = 0; dwIdx < dwNumSaclAces; dwIdx++ )
  691. {
  692. //
  693. // This time, retrieve all the data
  694. //
  695. AceRequest.dwFlags = F_RETURN_ALL_DATA;
  696. dwTmp = GetNextAceInfo( &varArgList, &AceRequest );
  697. if( dwTmp == 0 )
  698. {
  699. dwErr = GetLastError();
  700. goto error;
  701. }
  702. //
  703. // The ACE header is already filled in, and contains the ACE size
  704. //
  705. memcpy( pSd + dwCurOffset, &(AceRequest.pAce), sizeof(ACE_HEADER) );
  706. dwCurOffset += sizeof(ACE_HEADER);
  707. //
  708. // Set the access mask
  709. //
  710. *((PACCESS_MASK)( pSd + dwCurOffset )) = AceRequest.amMask;
  711. dwCurOffset += sizeof(ACCESS_MASK);
  712. //
  713. // If object ACE, set the object flags and GUIDs
  714. //
  715. if( AceRequest.dwFlags & F_IS_OBJECT )
  716. {
  717. dwTmp = 0;
  718. if( AceRequest.pgObject != NULL )
  719. {
  720. dwTmp |= ACE_OBJECT_TYPE_PRESENT;
  721. }
  722. if( AceRequest.pgInherit != NULL )
  723. {
  724. dwTmp |= ACE_INHERITED_OBJECT_TYPE_PRESENT;
  725. }
  726. //
  727. // Set the object ACE flags
  728. //
  729. *((PDWORD)(pSd + dwCurOffset )) = dwTmp;
  730. dwCurOffset += sizeof(DWORD);
  731. //
  732. // Copy the GUIDs, if any
  733. //
  734. if( AceRequest.pgObject != NULL )
  735. {
  736. memcpy( pSd + dwCurOffset,
  737. AceRequest.pgObject,
  738. sizeof(GUID) );
  739. dwCurOffset += sizeof(GUID);
  740. }
  741. if( AceRequest.pgInherit != NULL )
  742. {
  743. memcpy( pSd + dwCurOffset,
  744. AceRequest.pgInherit,
  745. sizeof(GUID) );
  746. dwCurOffset += sizeof(GUID);
  747. }
  748. }
  749. //
  750. // Copy the SID
  751. //
  752. dwTmp = GetLengthSid( AceRequest.pSid );
  753. memcpy( pSd + dwCurOffset, AceRequest.pSid, dwTmp );
  754. dwCurOffset += dwTmp;
  755. //
  756. // If callback ACE, copy the optional data, if any
  757. //
  758. if( AceRequest.dwFlags & F_IS_CALLBACK
  759. && AceRequest.dwOptDataSize > 0 )
  760. {
  761. memcpy( pSd + dwCurOffset,
  762. AceRequest.pvOptData,
  763. AceRequest.dwOptDataSize );
  764. dwCurOffset += AceRequest.dwOptDataSize;
  765. }
  766. //
  767. // Done with the ACE
  768. //
  769. }
  770. //
  771. // Done with the SACL
  772. //
  773. }
  774. //
  775. // Done with the variable arg list
  776. //
  777. va_end(varArgList);
  778. bArglistStarted = FALSE;
  779. error:;
  780. if( dwErr != ERROR_SUCCESS )
  781. {
  782. if( bArglistStarted )
  783. {
  784. va_end(varArgList);
  785. }
  786. if( pSd != NULL )
  787. {
  788. free(pSd);
  789. }
  790. SetLastError(dwErr);
  791. return FALSE;
  792. }
  793. else
  794. {
  795. //
  796. // Make sure the sizes match
  797. //
  798. ASSERT( dwCurOffset == ( dwSizeSd + dwDaclSize + dwSaclSize ) );
  799. *ppSd = pSd;
  800. return TRUE;
  801. }
  802. }