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.

3700 lines
113 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. tree.cpp
  5. Abstract:
  6. SCE Engine security inheritance and propagation APIs
  7. Author:
  8. Jin Huang (jinhuang) 23-Jun-1997 created
  9. --*/
  10. #include "serverp.h"
  11. #include "srvutil.h"
  12. #include <io.h>
  13. BOOL gbQueriedIfSystemContext = FALSE;
  14. BOOL gbIsSystemContext = FALSE;
  15. #ifdef SCE_DBG
  16. DWORD gDbgNumPushed = 0;
  17. DWORD gDbgNumPopped = 0;
  18. #endif
  19. #if _WIN32_WINNT==0x0400
  20. #include "dsrights.h"
  21. #endif
  22. #pragma hdrstop
  23. #define SCETREE_QUERY_SD 1
  24. #define SE_VALID_CONTROL_BITS ( SE_DACL_UNTRUSTED | \
  25. SE_SERVER_SECURITY | \
  26. SE_DACL_AUTO_INHERIT_REQ | \
  27. SE_SACL_AUTO_INHERIT_REQ | \
  28. SE_DACL_AUTO_INHERITED | \
  29. SE_SACL_AUTO_INHERITED | \
  30. SE_DACL_PROTECTED | \
  31. SE_SACL_PROTECTED )
  32. #define SCEP_IGNORE_SOME_ERRORS(ErrorCode) ErrorCode == ERROR_FILE_NOT_FOUND ||\
  33. ErrorCode == ERROR_PATH_NOT_FOUND ||\
  34. ErrorCode == ERROR_ACCESS_DENIED ||\
  35. ErrorCode == ERROR_SHARING_VIOLATION ||\
  36. ErrorCode == ERROR_INVALID_OWNER ||\
  37. ErrorCode == ERROR_INVALID_PRIMARY_GROUP ||\
  38. ErrorCode == ERROR_INVALID_HANDLE ||\
  39. ErrorCode == ERROR_INVALID_SECURITY_DESCR ||\
  40. ErrorCode == ERROR_CANT_ACCESS_FILE
  41. DWORD
  42. AccRewriteSetNamedRights(
  43. IN LPWSTR pObjectName,
  44. IN SE_OBJECT_TYPE ObjectType,
  45. IN SECURITY_INFORMATION SecurityInfo,
  46. IN OUT PSECURITY_DESCRIPTOR pSecurityDescriptor,
  47. IN BOOL bSkipInheritanceComputation
  48. );
  49. SCESTATUS
  50. ScepCreateObjectNode(
  51. IN PWSTR Buffer,
  52. IN WCHAR Delim,
  53. IN PSCE_OBJECT_TREE *ParentNode,
  54. OUT PSCE_OBJECT_CHILD_LIST *NewNode
  55. );
  56. DWORD
  57. ScepDoesObjectHasChildren(
  58. IN SE_OBJECT_TYPE ObjectType,
  59. IN PWSTR ObjectName,
  60. OUT PBOOL pbHasChildren
  61. );
  62. DWORD
  63. ScepAddAutoInheritRequest(
  64. IN OUT PSECURITY_DESCRIPTOR pSD,
  65. IN OUT SECURITY_INFORMATION *pSeInfo
  66. );
  67. DWORD
  68. ScepSetSecurityOverwriteExplicit(
  69. IN PCWSTR ObjectName,
  70. IN SECURITY_INFORMATION SeInfo,
  71. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  72. IN SE_OBJECT_TYPE ObjectType,
  73. IN HANDLE Token,
  74. IN PGENERIC_MAPPING GenericMapping
  75. );
  76. DWORD
  77. ScepConfigureOneSubTreeFile(
  78. IN PSCE_OBJECT_TREE ThisNode,
  79. IN SE_OBJECT_TYPE ObjectType,
  80. IN HANDLE Token,
  81. IN PGENERIC_MAPPING GenericMapping,
  82. IN BOOL BackSlashExist
  83. );
  84. DWORD
  85. ScepConfigureOneSubTreeKey(
  86. IN PSCE_OBJECT_TREE ThisNode,
  87. IN SE_OBJECT_TYPE ObjectType,
  88. IN HANDLE Token,
  89. IN PGENERIC_MAPPING GenericMapping
  90. );
  91. typedef struct _SCEP_STACK_NODE_ {
  92. PWSTR Buffer;
  93. PSECURITY_DESCRIPTOR pObjectSecurity;
  94. struct _SCEP_STACK_NODE_ *Next;
  95. } SCEP_STACK_NODE, *PSCEP_STACK_NODE;
  96. DWORD
  97. ScepStackNodePush(
  98. IN PSCEP_STACK_NODE *ppStackHead,
  99. IN PWSTR pszObjectName,
  100. IN PSECURITY_DESCRIPTOR pSecurityDescriptor
  101. );
  102. VOID
  103. ScepStackNodePop(
  104. IN OUT PSCEP_STACK_NODE *ppStackHead,
  105. IN OUT PWSTR *ppszObjectName,
  106. IN OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor
  107. );
  108. VOID
  109. ScepFreeStack(
  110. IN PSCEP_STACK_NODE *ppStackHead
  111. );
  112. VOID
  113. ScepDumpStack(
  114. IN PSCEP_STACK_NODE *ppStackHead
  115. );
  116. SCESTATUS
  117. ScepBuildObjectTree(
  118. IN OUT PSCE_OBJECT_TREE *ParentNode,
  119. IN OUT PSCE_OBJECT_CHILD_LIST *ChildHead,
  120. IN ULONG Level,
  121. IN WCHAR Delim,
  122. IN PCWSTR ObjectFullName,
  123. IN BOOL IsContainer,
  124. IN BYTE Status,
  125. IN PSECURITY_DESCRIPTOR pInfSecurityDescriptor,
  126. IN SECURITY_INFORMATION InfSeInfo
  127. )
  128. /* ++
  129. Routine Description:
  130. This routine adds the ObjectFullName to the tree. When this routine is
  131. first called from outside, the root of the tree is passed in as *SiblingHead,
  132. and the ParentNode is NULL. Then the routine parses the ObjectFullName for
  133. each level and adds the node if it does not exist. For example:
  134. root
  135. level 1 c: ---------> d:--->...
  136. / /
  137. level 2 winnt->NTLDR->... "Program Files"->...
  138. /
  139. level 3 system32->system->...
  140. Arguments:
  141. ParentNode - The parent node pointer
  142. SiblingHead - The sibling head pointer for this level
  143. Level - The level (1,2,3...)
  144. Delim - The deliminator to separate each level in the full name component
  145. Currently '\' is used for file and registry objects, and '/' is used
  146. for acitve directory objects.
  147. ObjectFullName - Full path name of the object (file, registry)
  148. Status - The configuration status
  149. SCE_STATUS_CHECK (with AUTO_INHERIT)
  150. SCE_STATUS_NO_AUTO_INHERIT
  151. SCE_STATUS_IGNORE
  152. SCE_STATUS_OVERWRITE
  153. pInfSecurityDescriptor - The security descriptor set in the INF file
  154. InfSeInfo - The security information set in the INF file
  155. Return value:
  156. SCESTATUS_SUCCESS
  157. SCESTATUS_INVALID_PARAMETER
  158. SCESTATUS_NOT_ENOUGH_RESOURCE
  159. -- */
  160. {
  161. SCESTATUS rc;
  162. TCHAR *Buffer = NULL;
  163. PSCE_OBJECT_CHILD_LIST NewNode=NULL;
  164. PSCE_OBJECT_CHILD_LIST PrevSib=NULL;
  165. PSCE_OBJECT_TREE ThisNode=NULL;
  166. INT Result;
  167. BOOL LastOne=FALSE;
  168. DWORD dwObjectFullNameLen = 0;
  169. //
  170. // address for ParentNode can be empty( the root )
  171. // but address for the first node of the level cannot be empty.
  172. //
  173. if ( ChildHead == NULL ) {
  174. return(SCESTATUS_INVALID_PARAMETER);
  175. }
  176. //
  177. // find the object name for the level (from ObjectFullName)
  178. // e.g., if ObjectFullName is c:\winnt\system32 then
  179. // level 1 name is c:, level 2 name is winnt, level 3 name is system32
  180. //
  181. dwObjectFullNameLen = wcslen(ObjectFullName);
  182. Buffer = (TCHAR *)LocalAlloc(LMEM_ZEROINIT,
  183. sizeof(TCHAR) * (dwObjectFullNameLen + 1));
  184. if (NULL == Buffer) {
  185. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  186. goto Done;
  187. }
  188. memset(Buffer, '\0', dwObjectFullNameLen * sizeof(TCHAR));
  189. rc = ScepGetNameInLevel(ObjectFullName,
  190. Level,
  191. Delim,
  192. Buffer,
  193. &LastOne);
  194. if ( rc != SCESTATUS_SUCCESS )
  195. goto Done;
  196. if ( *ChildHead == NULL ) {
  197. //
  198. // This is the first node in this level
  199. // Create the node and assign it to the ChildHead
  200. //
  201. rc = ScepCreateObjectNode(
  202. Buffer,
  203. Delim,
  204. ParentNode,
  205. &NewNode
  206. );
  207. if ( rc != SCESTATUS_SUCCESS)
  208. goto Done;
  209. *ChildHead = NewNode;
  210. //
  211. // Establish the link if there is a parent
  212. //
  213. if ( ParentNode != NULL )
  214. if ( *ParentNode != NULL )
  215. (*ParentNode)->ChildList = NewNode;
  216. ThisNode = NewNode->Node;
  217. } else {
  218. //
  219. // There are existing nodes. Search all siblings
  220. // All siblings are stored in alphabetic order.
  221. //
  222. PSCE_OBJECT_CHILD_LIST pTemp;
  223. for ( pTemp = *ChildHead, PrevSib = NULL;
  224. pTemp != NULL;
  225. pTemp = pTemp->Next) {
  226. //
  227. // Compare the node's object name with the current object name
  228. //
  229. Result = _wcsicmp(pTemp->Node->Name, Buffer);
  230. //
  231. // if the node's object name is equal to (find it) or greater
  232. // than (insert the node) the current object name, then stop
  233. //
  234. if ( Result >= 0 ) {
  235. break;
  236. }
  237. PrevSib = pTemp;
  238. }
  239. if ( pTemp == NULL ) {
  240. //
  241. // Not exist. Append the new node
  242. //
  243. rc = ScepCreateObjectNode(
  244. Buffer,
  245. Delim,
  246. ParentNode,
  247. &NewNode
  248. );
  249. if ( rc != SCESTATUS_SUCCESS)
  250. goto Done;
  251. if ( PrevSib != NULL )
  252. PrevSib->Next = NewNode;
  253. else {
  254. //
  255. // this is the first one in the level
  256. //
  257. (*ChildHead)->Next = NewNode;
  258. }
  259. ThisNode = NewNode->Node;
  260. } else {
  261. //
  262. // either find it (i=0) or need to insert between PrevSib and ThisNode
  263. //
  264. if ( Result > 0 ) {
  265. //
  266. // insert the node
  267. //
  268. rc = ScepCreateObjectNode(
  269. Buffer,
  270. Delim,
  271. ParentNode,
  272. &NewNode
  273. );
  274. if ( rc != SCESTATUS_SUCCESS)
  275. goto Done;
  276. NewNode->Next = pTemp;
  277. if ( PrevSib != NULL )
  278. PrevSib->Next = NewNode;
  279. else {
  280. //
  281. // insert before SiblingHead
  282. //
  283. *ChildHead = NewNode;
  284. if ( ParentNode != NULL )
  285. if ( *ParentNode != NULL )
  286. (*ParentNode)->ChildList = NewNode;
  287. }
  288. ThisNode = NewNode->Node;
  289. } else {
  290. ThisNode = pTemp->Node;
  291. }
  292. }
  293. }
  294. if ( LastOne ) {
  295. //
  296. // Assign Inf security information to this node
  297. //
  298. ThisNode->pSecurityDescriptor = pInfSecurityDescriptor;
  299. ThisNode->SeInfo = InfSeInfo;
  300. ThisNode->Status = Status;
  301. ThisNode->IsContainer = IsContainer;
  302. } else {
  303. //
  304. // process next level recursively
  305. //
  306. rc = ScepBuildObjectTree(&ThisNode,
  307. &(ThisNode->ChildList),
  308. Level+1,
  309. Delim,
  310. ObjectFullName,
  311. IsContainer,
  312. Status,
  313. pInfSecurityDescriptor,
  314. InfSeInfo);
  315. }
  316. Done:
  317. if (Buffer) {
  318. LocalFree(Buffer);
  319. }
  320. return(rc);
  321. }
  322. SCESTATUS
  323. ScepCreateObjectNode(
  324. IN PWSTR Buffer,
  325. IN WCHAR Delim,
  326. IN PSCE_OBJECT_TREE *ParentNode,
  327. OUT PSCE_OBJECT_CHILD_LIST *NewNode
  328. )
  329. /* ++
  330. Routine Description:
  331. This routine allocates memory for a new node in the tree. The ParentNode
  332. is used to determine the full object name and link the new node (if not NULL)
  333. Arguments:
  334. Buffer - The component name of a object
  335. Delim - The deliminator to separate different levels in the full name.
  336. ParentNode - Pointer of the parent node of this new node
  337. NewNode - New created node
  338. Return value:
  339. SCESTATUS
  340. -- */
  341. {
  342. DWORD Len;
  343. if (NewNode == NULL )
  344. return(SCESTATUS_INVALID_PARAMETER);
  345. //
  346. // allocate buffer for the node
  347. //
  348. *NewNode = (PSCE_OBJECT_CHILD_LIST)ScepAlloc(LPTR, sizeof(SCE_OBJECT_CHILD_LIST));
  349. if ( *NewNode == NULL )
  350. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  351. PSCE_OBJECT_TREE Node = (PSCE_OBJECT_TREE)ScepAlloc((UINT)0, sizeof(SCE_OBJECT_TREE));
  352. if ( Node == NULL ) {
  353. ScepFree(*NewNode);
  354. *NewNode = NULL;
  355. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  356. }
  357. //
  358. // allocate buffer for the object name
  359. //
  360. Len = wcslen(Buffer);
  361. Node->Name = (PWSTR)ScepAlloc((UINT)0,
  362. (Len+1) * sizeof(TCHAR));
  363. if ( Node->Name == NULL ) {
  364. ScepFree(Node);
  365. ScepFree(*NewNode);
  366. *NewNode = NULL;
  367. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  368. }
  369. if ( ParentNode != NULL &&
  370. *ParentNode != NULL ) {
  371. Len += wcslen((*ParentNode)->ObjectFullName)+1;
  372. ++((*ParentNode)->dwSize_aChildNames);
  373. // Reserve a space for "\" for the root dir c:\ .
  374. } else if ( Buffer[1] == L':' ) {
  375. Len++;
  376. }
  377. Node->ObjectFullName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (Len+1)*sizeof(TCHAR));
  378. if ( Node->ObjectFullName == NULL ) {
  379. ScepFree(Node->Name );
  380. ScepFree(Node);
  381. ScepFree( *NewNode );
  382. *NewNode = NULL;
  383. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  384. }
  385. //
  386. // initialize
  387. //
  388. wcscpy(Node->Name, Buffer);
  389. Node->ChildList = NULL;
  390. Node->pSecurityDescriptor = NULL;
  391. Node->pApplySecurityDescriptor = NULL;
  392. Node->SeInfo = 0;
  393. Node->IsContainer = TRUE;
  394. Node->aChildNames = NULL;
  395. Node->dwSize_aChildNames = 0;
  396. if ( ParentNode != NULL &&
  397. *ParentNode != NULL ) {
  398. //
  399. // link to parent, use parent's status for this one
  400. //
  401. Node->Parent = *ParentNode;
  402. swprintf(Node->ObjectFullName,
  403. L"%s%c%s",
  404. (*ParentNode)->ObjectFullName,
  405. Delim,
  406. Buffer);
  407. Node->Status = (*ParentNode)->Status;
  408. } else {
  409. //
  410. // this is the first node.
  411. //
  412. Node->Parent = NULL;
  413. wcscpy(Node->ObjectFullName, Buffer);
  414. Node->Status = SCE_STATUS_CHECK;
  415. }
  416. (*NewNode)->Node = Node;
  417. return(SCESTATUS_SUCCESS);
  418. }
  419. SCESTATUS
  420. ScepCalculateSecurityToApply(
  421. IN PSCE_OBJECT_TREE ThisNode,
  422. IN SE_OBJECT_TYPE ObjectType,
  423. IN HANDLE Token,
  424. IN PGENERIC_MAPPING GenericMapping
  425. )
  426. /* ++
  427. Routine Description:
  428. This routine walks through the security tree to determine security
  429. descriptor for each node. It calls RtlNewSecurityObject, passing a
  430. parent node's SD and current node's SD specified in the INF file.
  431. The output SD from that API is the security descriptor to set to the
  432. current object.
  433. Arguments:
  434. ThisNode - The current object's node
  435. ObjectType - The object's type
  436. SE_FILE_OBJECT
  437. SE_REGISTRY_KEY
  438. Token - The thread/process token of the calling client
  439. GenericMapping - Generic access map table
  440. Return value:
  441. SCESTATUS_SUCCESS
  442. SCESTATUS_OTHER_ERROR (see log for detail error)
  443. -- */
  444. {
  445. SCESTATUS rc=SCESTATUS_SUCCESS;
  446. PSECURITY_DESCRIPTOR ParentSD=NULL;
  447. SECURITY_INFORMATION SeInfoGet;
  448. DWORD Win32rc;
  449. intptr_t hFile;
  450. struct _wfinddata_t *pFileInfo=NULL;
  451. DWORD dwChildIndex = 0;
  452. if ( ThisNode == NULL )
  453. return(SCESTATUS_SUCCESS);
  454. #ifdef SCE_DBG
  455. wprintf(L"%s\n", ThisNode->ObjectFullName);
  456. #endif
  457. //
  458. // if IGNORE is set, skip this node too
  459. //
  460. if ( ThisNode->Status != SCE_STATUS_CHECK &&
  461. ThisNode->Status != SCE_STATUS_NO_AUTO_INHERIT &&
  462. ThisNode->Status != SCE_STATUS_OVERWRITE )
  463. goto Done;
  464. if ( ThisNode->dwSize_aChildNames != 0) {
  465. ThisNode->aChildNames = (PWSTR *) LocalAlloc( LMEM_ZEROINIT,
  466. (sizeof(PWSTR) * ThisNode->dwSize_aChildNames));
  467. if ( ThisNode->aChildNames == NULL ) {
  468. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  469. goto Done;
  470. }
  471. }
  472. if ( ThisNode->Parent == NULL ) {
  473. //
  474. // this is the first node
  475. // should always use Rtl routine to compute security descriptor
  476. // so Creator Owner ace is translated properly.
  477. //
  478. if ( ThisNode->pSecurityDescriptor ) {
  479. Win32rc = ScepGetNewSecurity(
  480. ThisNode->ObjectFullName,
  481. NULL, // parent's SD
  482. ThisNode->pSecurityDescriptor,
  483. 0, // does not query current object SD
  484. (BOOLEAN)(ThisNode->IsContainer),
  485. ThisNode->SeInfo,
  486. ObjectType,
  487. Token,
  488. GenericMapping,
  489. &(ThisNode->pApplySecurityDescriptor)
  490. );
  491. if ( Win32rc != NO_ERROR ) {
  492. ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_BUILD_SD,
  493. ThisNode->ObjectFullName );
  494. rc = ScepDosErrorToSceStatus(Win32rc);
  495. goto Done;
  496. }
  497. } else {
  498. //
  499. // no explicit security specified for this node
  500. //
  501. ThisNode->pApplySecurityDescriptor = NULL;
  502. }
  503. goto ProcChild;
  504. }
  505. //
  506. // process children nodes
  507. //
  508. if ( ThisNode->pSecurityDescriptor != NULL ||
  509. ThisNode->Parent->pApplySecurityDescriptor != NULL ) {
  510. if ( ObjectType == SE_FILE_OBJECT && NULL == ThisNode->ChildList ) {
  511. //
  512. // detect if this is a file (non-container object)
  513. //
  514. pFileInfo = (struct _wfinddata_t *)ScepAlloc(0,sizeof(struct _wfinddata_t));
  515. if ( pFileInfo == NULL ) {
  516. //
  517. // out of memory, treat it as a container for now and
  518. // will error out later.
  519. //
  520. ThisNode->IsContainer = TRUE;
  521. } else {
  522. hFile = _wfindfirst(ThisNode->ObjectFullName, pFileInfo);
  523. ThisNode->IsContainer = FALSE;
  524. if ( hFile != -1 ) {
  525. _findclose(hFile);
  526. if ( pFileInfo->attrib & _A_SUBDIR ) {
  527. ThisNode->IsContainer = TRUE;
  528. }
  529. }
  530. ScepFree(pFileInfo);
  531. pFileInfo = NULL;
  532. }
  533. } else {
  534. ThisNode->IsContainer = TRUE;
  535. }
  536. //
  537. // even if the security descriptor is protected,
  538. // still need to call ScepNewSecurity to get CREATOR OWNER ace
  539. // translated correctly.
  540. //
  541. //
  542. // if this is the first explicit node in this branch,
  543. // the pApplySecurityDescriptor of the parent must be NULL.
  544. //
  545. if ( ThisNode->Parent->pApplySecurityDescriptor == NULL ) {
  546. //
  547. // yes, this is the first explicit node.
  548. // get the current system's setting on the parent node
  549. // have to use Win32 api because it will compute all inherited
  550. // security information from all parents automatically
  551. //
  552. SeInfoGet = 0;
  553. if ( ThisNode->SeInfo & DACL_SECURITY_INFORMATION )
  554. SeInfoGet |= DACL_SECURITY_INFORMATION;
  555. if ( ThisNode->SeInfo & SACL_SECURITY_INFORMATION )
  556. SeInfoGet |= SACL_SECURITY_INFORMATION;
  557. Win32rc = GetNamedSecurityInfo(
  558. ThisNode->Parent->ObjectFullName,
  559. ObjectType,
  560. SeInfoGet,
  561. NULL,
  562. NULL,
  563. NULL,
  564. NULL,
  565. &ParentSD
  566. );
  567. /*
  568. Win32rc = ScepGetNamedSecurityInfo(
  569. ThisNode->Parent->ObjectFullName,
  570. ObjectType,
  571. SeInfoGet,
  572. &ParentSD
  573. );
  574. */
  575. if ( Win32rc != NO_ERROR &&
  576. Win32rc != ERROR_FILE_NOT_FOUND &&
  577. Win32rc != ERROR_PATH_NOT_FOUND &&
  578. Win32rc != ERROR_ACCESS_DENIED &&
  579. Win32rc != ERROR_CANT_ACCESS_FILE &&
  580. Win32rc != ERROR_SHARING_VIOLATION ) {
  581. ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_QUERY_SECURITY,
  582. ThisNode->Parent->ObjectFullName );
  583. rc = ScepDosErrorToSceStatus(Win32rc);
  584. goto Done;
  585. }
  586. } else {
  587. ParentSD = ThisNode->Parent->pApplySecurityDescriptor;
  588. //
  589. // owner/group information are not inheritable
  590. //
  591. if ( ThisNode->Parent->SeInfo & DACL_SECURITY_INFORMATION )
  592. ThisNode->SeInfo |= DACL_SECURITY_INFORMATION;
  593. if ( ThisNode->Parent->SeInfo & SACL_SECURITY_INFORMATION )
  594. ThisNode->SeInfo |= SACL_SECURITY_INFORMATION;
  595. }
  596. //
  597. // compute the new security descriptor with inherited aces from the parentSD
  598. // if the status is SCE_STATUS_CHECK (auto inherit), need to query the current
  599. // object's security descriptor if no explicit SD is specified
  600. // (ThisNode->pSecurityDescriptor is NULL)
  601. //
  602. Win32rc = ScepGetNewSecurity(
  603. ThisNode->ObjectFullName,
  604. ParentSD,
  605. ThisNode->pSecurityDescriptor,
  606. (BYTE)(( ThisNode->Status == SCE_STATUS_CHECK ) ? SCETREE_QUERY_SD : 0),
  607. (BOOLEAN)(ThisNode->IsContainer),
  608. ThisNode->SeInfo,
  609. ObjectType,
  610. Token,
  611. GenericMapping,
  612. &(ThisNode->pApplySecurityDescriptor)
  613. );
  614. if ( ParentSD &&
  615. ParentSD != ThisNode->Parent->pApplySecurityDescriptor ) {
  616. //
  617. // free the parent security descriptor if it's allocated here
  618. //
  619. LocalFree(ParentSD);
  620. }
  621. if ( ERROR_SUCCESS == Win32rc ||
  622. ERROR_FILE_NOT_FOUND == Win32rc ||
  623. ERROR_PATH_NOT_FOUND == Win32rc ||
  624. ERROR_ACCESS_DENIED == Win32rc ||
  625. ERROR_CANT_ACCESS_FILE == Win32rc ||
  626. ERROR_SHARING_VIOLATION == Win32rc ) {
  627. rc = SCESTATUS_SUCCESS;
  628. } else {
  629. ScepLogOutput3(1, Win32rc,
  630. SCEDLL_ERROR_BUILD_SD,
  631. ThisNode->ObjectFullName
  632. );
  633. rc = ScepDosErrorToSceStatus(Win32rc);
  634. goto Done;
  635. }
  636. }
  637. ProcChild:
  638. //
  639. // then process left child
  640. //
  641. for ( PSCE_OBJECT_CHILD_LIST pTemp = ThisNode->ChildList;
  642. pTemp != NULL; pTemp = pTemp->Next ) {
  643. if ( pTemp->Node == NULL ) continue;
  644. ThisNode->aChildNames[dwChildIndex] = pTemp->Node->Name;
  645. ++dwChildIndex;
  646. rc = ScepCalculateSecurityToApply(
  647. pTemp->Node,
  648. ObjectType,
  649. Token,
  650. GenericMapping
  651. );
  652. if ( rc != SCESTATUS_SUCCESS )
  653. goto Done;
  654. }
  655. //
  656. // in case there are lesser child names than initially calcluated
  657. //
  658. if (dwChildIndex < ThisNode->dwSize_aChildNames) {
  659. ThisNode->dwSize_aChildNames = dwChildIndex;
  660. }
  661. Done:
  662. return(rc);
  663. }
  664. DWORD
  665. ScepGetNewSecurity(
  666. IN LPTSTR ObjectName,
  667. IN PSECURITY_DESCRIPTOR pParentSD OPTIONAL,
  668. IN PSECURITY_DESCRIPTOR pObjectSD OPTIONAL,
  669. IN BYTE nFlag,
  670. IN BOOLEAN bIsContainer,
  671. IN SECURITY_INFORMATION SeInfo,
  672. IN SE_OBJECT_TYPE ObjectType,
  673. IN HANDLE Token,
  674. IN PGENERIC_MAPPING GenericMapping,
  675. OUT PSECURITY_DESCRIPTOR *ppNewSD
  676. )
  677. /*
  678. Routine Description:
  679. This routine will compute a security descriptor based on parent's security
  680. descriptor and the explicit security descriptor for the object. If no owner
  681. information is specified in the object's security descriptor, this routine
  682. will query the current owner of the object on the system so CREATOR_OWNER
  683. ace can be translated into the proper ace based on the owner.
  684. Arguments:
  685. ObjectName - the object's full name
  686. pParentSD - optional security descriptor of the parent
  687. pObjectSD - optional explicit security descriptor of this object
  688. SeInfo - security information contained in the object's SD
  689. bIsContainer - if the object is a container
  690. pNewSD - the new computed security descriptor address
  691. Return Value:
  692. NTSTATUS of this operation
  693. */
  694. {
  695. BOOL bOwner;
  696. BOOLEAN tFlag;
  697. BOOLEAN aclPresent;
  698. PSID pOwner=NULL;
  699. PACL pDacl=NULL;
  700. PACL pSacl=NULL;
  701. SECURITY_DESCRIPTOR SD;
  702. PSECURITY_DESCRIPTOR pCurrentSD=NULL;
  703. DWORD Win32rc;
  704. NTSTATUS NtStatus;
  705. SECURITY_DESCRIPTOR_CONTROL Control;
  706. ULONG Revision;
  707. if ( !ppNewSD ) {
  708. return(ERROR_INVALID_PARAMETER);
  709. }
  710. //
  711. // In case there is no RPC call causing us to enter here, there
  712. // is no impersonation happening and the current thread is already
  713. // running under Local System context in which case there is no
  714. // need to RevertToSelf() etc. as below.
  715. // This behavior happens when, for example, the server side itself
  716. // initiates a configuration
  717. //
  718. if ( !gbQueriedIfSystemContext ) {
  719. //
  720. // if any error happens when checking if running under system context,
  721. // continue - since there will be impersonation errors later on in
  722. // this routine
  723. //
  724. NtStatus = ScepIsSystemContext(
  725. Token,
  726. &gbIsSystemContext);
  727. if (ERROR_SUCCESS == RtlNtStatusToDosError(NtStatus)) {
  728. gbQueriedIfSystemContext = TRUE;
  729. }
  730. }
  731. if ( nFlag == SCETREE_QUERY_SD &&
  732. !pObjectSD ) {
  733. //
  734. // current object's security descriptor is used, for SeInfo | OWNER
  735. // NOTE: the inherited ace from pCurrentSD are not copied (which is correct).
  736. //
  737. Win32rc = GetNamedSecurityInfo(
  738. ObjectName,
  739. ObjectType,
  740. SeInfo | OWNER_SECURITY_INFORMATION,
  741. NULL,
  742. NULL,
  743. NULL,
  744. NULL,
  745. &pCurrentSD
  746. );
  747. /*
  748. Win32rc = ScepGetNamedSecurityInfo(
  749. ObjectName,
  750. ObjectType,
  751. SeInfo | OWNER_SECURITY_INFORMATION,
  752. &pCurrentSD
  753. );
  754. */
  755. //
  756. // RtlNewSecurityObjectEx must be called on the process context (system)
  757. // because it will try to get process information inside the api.
  758. //
  759. if (!gbIsSystemContext) {
  760. RpcRevertToSelf();
  761. }
  762. if ( ERROR_SUCCESS == Win32rc ||
  763. ERROR_FILE_NOT_FOUND == Win32rc ||
  764. ERROR_PATH_NOT_FOUND == Win32rc ) {
  765. //
  766. // use the current SD to compute
  767. //
  768. NtStatus = RtlNewSecurityObjectEx(
  769. pParentSD,
  770. pCurrentSD,
  771. ppNewSD,
  772. NULL, // GUID
  773. bIsContainer,
  774. SEF_DACL_AUTO_INHERIT |
  775. SEF_SACL_AUTO_INHERIT |
  776. SEF_AVOID_OWNER_CHECK |
  777. SEF_AVOID_PRIVILEGE_CHECK,
  778. Token,
  779. GenericMapping
  780. );
  781. Win32rc = RtlNtStatusToDosError(NtStatus);
  782. }
  783. if ( pCurrentSD ) {
  784. ScepFree(pCurrentSD);
  785. }
  786. } else {
  787. //
  788. // RtlNewSecurityObjectEx must be called on the process context (system)
  789. // because it will try to get process information inside the api.
  790. //
  791. if (!gbIsSystemContext) {
  792. RpcRevertToSelf();
  793. }
  794. if ( pObjectSD ) {
  795. //
  796. // check if there is a owner
  797. //
  798. NtStatus = RtlGetOwnerSecurityDescriptor(
  799. pObjectSD,
  800. &pOwner,
  801. &tFlag);
  802. if ( NT_SUCCESS(NtStatus) && pOwner && !tFlag ) {
  803. bOwner = TRUE;
  804. } else {
  805. bOwner = FALSE;
  806. }
  807. } else {
  808. //
  809. // no owner
  810. //
  811. bOwner = FALSE;
  812. }
  813. if ( !bOwner ) {
  814. //
  815. // query owner information only
  816. //
  817. Win32rc = ScepGetNamedSecurityInfo(
  818. ObjectName,
  819. ObjectType,
  820. OWNER_SECURITY_INFORMATION,
  821. &pCurrentSD
  822. );
  823. if ( ERROR_SUCCESS == Win32rc ) {
  824. NtStatus = RtlGetOwnerSecurityDescriptor(
  825. pCurrentSD,
  826. &pOwner,
  827. &tFlag);
  828. Win32rc = RtlNtStatusToDosError(NtStatus);
  829. }
  830. if ( ERROR_FILE_NOT_FOUND == Win32rc ||
  831. ERROR_PATH_NOT_FOUND == Win32rc ) {
  832. Win32rc = ERROR_SUCCESS;
  833. }
  834. if ( ERROR_SUCCESS == Win32rc ) {
  835. //
  836. // build a security descriptor to use
  837. //
  838. if ( SeInfo & DACL_SECURITY_INFORMATION &&
  839. pObjectSD ) {
  840. //
  841. // Get DACL address
  842. //
  843. Win32rc = RtlNtStatusToDosError(
  844. RtlGetDaclSecurityDescriptor(
  845. pObjectSD,
  846. &aclPresent,
  847. &pDacl,
  848. &tFlag));
  849. if (Win32rc == NO_ERROR && !aclPresent ) {
  850. pDacl = NULL;
  851. }
  852. }
  853. if ( ERROR_SUCCESS == Win32rc &&
  854. (SeInfo & SACL_SECURITY_INFORMATION) &&
  855. pObjectSD ) {
  856. //
  857. // Get SACL address
  858. //
  859. Win32rc = RtlNtStatusToDosError(
  860. RtlGetSaclSecurityDescriptor(
  861. pObjectSD,
  862. &aclPresent,
  863. &pSacl,
  864. &tFlag));
  865. if ( Win32rc == NO_ERROR && !aclPresent ) {
  866. pSacl = NULL;
  867. }
  868. }
  869. if ( ERROR_SUCCESS == Win32rc ) {
  870. //
  871. // build an absolute security descriptor
  872. //
  873. NtStatus = RtlCreateSecurityDescriptor( &SD,
  874. SECURITY_DESCRIPTOR_REVISION );
  875. if ( NT_SUCCESS(NtStatus) ) {
  876. //
  877. // set control field
  878. //
  879. if ( pObjectSD ) {
  880. NtStatus = RtlGetControlSecurityDescriptor (
  881. pObjectSD,
  882. &Control,
  883. &Revision
  884. );
  885. if ( NT_SUCCESS(NtStatus) ) {
  886. Control &= SE_VALID_CONTROL_BITS;
  887. NtStatus = RtlSetControlSecurityDescriptor (
  888. &SD,
  889. Control,
  890. Control
  891. );
  892. }
  893. }
  894. //
  895. // set owner first
  896. //
  897. if ( pOwner ) {
  898. NtStatus = RtlSetOwnerSecurityDescriptor (
  899. &SD,
  900. pOwner,
  901. FALSE
  902. );
  903. }
  904. if ( NT_SUCCESS(NtStatus) ) {
  905. //
  906. // set DACL and SACL pointer to this SD
  907. //
  908. if ( SeInfo & DACL_SECURITY_INFORMATION && pDacl ) {
  909. NtStatus = RtlSetDaclSecurityDescriptor (
  910. &SD,
  911. TRUE,
  912. pDacl,
  913. FALSE
  914. );
  915. }
  916. if ( NT_SUCCESS(NtStatus) &&
  917. (SeInfo & SACL_SECURITY_INFORMATION) && pSacl ) {
  918. NtStatus = RtlSetSaclSecurityDescriptor (
  919. &SD,
  920. TRUE,
  921. pSacl,
  922. FALSE
  923. );
  924. }
  925. }
  926. //
  927. // now compute the new security descriptor
  928. //
  929. if ( NT_SUCCESS(NtStatus) ) {
  930. NtStatus = RtlNewSecurityObjectEx(
  931. pParentSD,
  932. &SD,
  933. ppNewSD,
  934. NULL, // GUID
  935. bIsContainer,
  936. SEF_DACL_AUTO_INHERIT |
  937. SEF_SACL_AUTO_INHERIT |
  938. SEF_AVOID_OWNER_CHECK |
  939. SEF_AVOID_PRIVILEGE_CHECK,
  940. Token,
  941. GenericMapping
  942. );
  943. }
  944. }
  945. Win32rc = RtlNtStatusToDosError(NtStatus);
  946. }
  947. }
  948. if ( pCurrentSD ) {
  949. //
  950. // this owner needs to be freed
  951. //
  952. LocalFree(pCurrentSD);
  953. }
  954. } else {
  955. //
  956. // there is a SD and there is a owner in it, just use it
  957. //
  958. NtStatus = RtlNewSecurityObjectEx(
  959. pParentSD,
  960. pObjectSD,
  961. ppNewSD,
  962. NULL, // GUID
  963. bIsContainer,
  964. SEF_DACL_AUTO_INHERIT |
  965. SEF_SACL_AUTO_INHERIT |
  966. SEF_AVOID_OWNER_CHECK |
  967. SEF_AVOID_PRIVILEGE_CHECK,
  968. Token,
  969. GenericMapping
  970. );
  971. Win32rc = RtlNtStatusToDosError(NtStatus);
  972. }
  973. }
  974. RPC_STATUS RpcStatus = RPC_S_OK;
  975. if (!gbIsSystemContext) {
  976. RpcStatus = RpcImpersonateClient( NULL );
  977. }
  978. if ( RpcStatus != RPC_S_OK ) {
  979. Win32rc = I_RpcMapWin32Status(RpcStatus);
  980. }
  981. if ( NO_ERROR != Win32rc &&
  982. *ppNewSD ) {
  983. //
  984. // free the buffer if there is an error
  985. //
  986. RtlDeleteSecurityObject(ppNewSD);
  987. *ppNewSD = NULL;
  988. }
  989. return(Win32rc);
  990. }
  991. DWORD
  992. ScepAddAutoInheritRequest(
  993. IN OUT PSECURITY_DESCRIPTOR pSD,
  994. IN OUT SECURITY_INFORMATION *pSeInfo
  995. )
  996. {
  997. SECURITY_DESCRIPTOR_CONTROL Control;
  998. SECURITY_DESCRIPTOR_CONTROL ToSet;
  999. ULONG Revision;
  1000. NTSTATUS NtStatus;
  1001. DWORD Win32rc=NO_ERROR;
  1002. if ( !pSeInfo )
  1003. return(ERROR_INVALID_PARAMETER);
  1004. if ( pSD != NULL &&
  1005. (*pSeInfo & DACL_SECURITY_INFORMATION ||
  1006. *pSeInfo & SACL_SECURITY_INFORMATION) ) {
  1007. NtStatus = RtlGetControlSecurityDescriptor (
  1008. pSD,
  1009. &Control,
  1010. &Revision
  1011. );
  1012. if ( !NT_SUCCESS(NtStatus) ) {
  1013. Win32rc = RtlNtStatusToDosError(NtStatus);
  1014. } else {
  1015. if ( !(Control & SE_DACL_PRESENT) )
  1016. *pSeInfo &= ~DACL_SECURITY_INFORMATION;
  1017. if ( !(Control & SE_SACL_PRESENT) )
  1018. *pSeInfo &= ~SACL_SECURITY_INFORMATION;
  1019. if ( *pSeInfo & (DACL_SECURITY_INFORMATION |
  1020. SACL_SECURITY_INFORMATION) ) {
  1021. ToSet = 0;
  1022. if ( *pSeInfo & DACL_SECURITY_INFORMATION ) {
  1023. ToSet |= (SE_DACL_AUTO_INHERIT_REQ |
  1024. SE_DACL_AUTO_INHERITED);
  1025. }
  1026. if ( *pSeInfo & SACL_SECURITY_INFORMATION) {
  1027. ToSet |= (SE_SACL_AUTO_INHERIT_REQ |
  1028. SE_SACL_AUTO_INHERITED);
  1029. }
  1030. if ( ToSet ) {
  1031. ((SECURITY_DESCRIPTOR *)pSD)->Control &= ~ToSet;
  1032. ((SECURITY_DESCRIPTOR *)pSD)->Control |= ToSet;
  1033. /*
  1034. NtStatus = RtlSetControlSecurityDescriptor (
  1035. pSD,
  1036. ToSet,
  1037. ToSet
  1038. );
  1039. Win32rc = RtlNtStatusToDosError(NtStatus);
  1040. */
  1041. }
  1042. }
  1043. }
  1044. }
  1045. return(Win32rc);
  1046. }
  1047. DWORD
  1048. ScepDoesObjectHasChildren(
  1049. IN SE_OBJECT_TYPE ObjectType,
  1050. IN PWSTR ObjectName,
  1051. OUT PBOOL pbHasChildren
  1052. )
  1053. {
  1054. PWSTR Name=NULL;
  1055. DWORD rc=NO_ERROR;
  1056. DWORD Len;
  1057. intptr_t hFile;
  1058. struct _wfinddata_t FileInfo;
  1059. HKEY hKey;
  1060. DWORD cSubKeys=0;
  1061. if ( ObjectName == NULL || pbHasChildren == NULL ) {
  1062. return(ERROR_INVALID_PARAMETER);
  1063. }
  1064. *pbHasChildren = TRUE; // default
  1065. if ( ObjectType == SE_FILE_OBJECT ) {
  1066. //
  1067. // detect if this is a container for file system
  1068. //
  1069. Len = wcslen(ObjectName);
  1070. Name = (PWSTR)ScepAlloc(0, (Len+5)*sizeof(WCHAR) );
  1071. if ( Name != NULL ) {
  1072. swprintf(Name, L"%s\\*.*", ObjectName);
  1073. Name[Len+3] = L'\0';
  1074. hFile = _wfindfirst(Name, &FileInfo);
  1075. if ( hFile == -1 ) {
  1076. *pbHasChildren = FALSE;
  1077. } else {
  1078. _findclose(hFile);
  1079. }
  1080. ScepFree(Name);
  1081. } else
  1082. rc = ERROR_NOT_ENOUGH_MEMORY;
  1083. #ifdef _WIN64
  1084. } else if ( ObjectType == SE_REGISTRY_KEY || ObjectType == SE_REGISTRY_WOW64_32KEY) {
  1085. #else
  1086. } else if ( ObjectType == SE_REGISTRY_KEY) {
  1087. #endif
  1088. rc = ScepOpenRegistryObject(
  1089. ObjectType,
  1090. (LPWSTR)ObjectName,
  1091. KEY_READ,
  1092. &hKey
  1093. );
  1094. if ( rc == NO_ERROR ) {
  1095. cSubKeys = 0;
  1096. rc = RegQueryInfoKey (
  1097. hKey,
  1098. NULL,
  1099. NULL,
  1100. NULL,
  1101. &cSubKeys,
  1102. NULL,
  1103. NULL,
  1104. NULL,
  1105. NULL,
  1106. NULL,
  1107. NULL,
  1108. NULL
  1109. );
  1110. if ( rc == NO_ERROR && cSubKeys == 0 ) {
  1111. *pbHasChildren = FALSE;
  1112. }
  1113. RegCloseKey(hKey);
  1114. }
  1115. }
  1116. return(rc);
  1117. }
  1118. SCESTATUS
  1119. ScepConfigureObjectTree(
  1120. IN PSCE_OBJECT_TREE ThisNode,
  1121. IN SE_OBJECT_TYPE ObjectType,
  1122. IN HANDLE Token,
  1123. IN PGENERIC_MAPPING GenericMapping,
  1124. IN DWORD ConfigOptions
  1125. )
  1126. /* ++
  1127. Routine Description:
  1128. This routine set security information to each node in the tree and objects of
  1129. the container if SCE_STATUS_OVERWRITE is set.
  1130. Arguments:
  1131. ThisNode - one node in the tree
  1132. ObjectType - type of the object (SE_FILE_OBJECT, SE_REGISTRY_KEY)
  1133. Token - The current process/thread's token (for computing new security descriptors)
  1134. GenericMapping - The access mask mappings from generic access rights to object
  1135. specific access rights.
  1136. Return value:
  1137. SCESTATUS_SUCCESS
  1138. SCESTATUS_OTHER_ERROR (see the log file for detail error)
  1139. -- */
  1140. {
  1141. // two error codes to distinguish between config status of "ThisNode" and "ThisNode's children"
  1142. DWORD rcThisNodeOnly = ERROR_SUCCESS;
  1143. DWORD rcThisNodeChildren = ERROR_SUCCESS;
  1144. if ( ThisNode == NULL )
  1145. return(SCESTATUS_SUCCESS);
  1146. //
  1147. // if IGNORE is set, skip this node, but post progress on it
  1148. //
  1149. if ( ThisNode->pSecurityDescriptor != NULL ) {
  1150. //
  1151. // notify the progress bar if there is any
  1152. //
  1153. switch(ObjectType) {
  1154. case SE_FILE_OBJECT:
  1155. ScepPostProgress(1, AREA_FILE_SECURITY, ThisNode->ObjectFullName);
  1156. break;
  1157. case SE_REGISTRY_KEY:
  1158. #ifdef _WIN64
  1159. case SE_REGISTRY_WOW64_32KEY:
  1160. #endif
  1161. ScepPostProgress(1, AREA_REGISTRY_SECURITY, ThisNode->ObjectFullName);
  1162. break;
  1163. default:
  1164. ScepPostProgress(1, 0, ThisNode->ObjectFullName);
  1165. break;
  1166. }
  1167. }
  1168. SCESTATUS rc=SCESTATUS_SUCCESS;
  1169. DWORD Win32Rc=ERROR_SUCCESS;
  1170. if ( ThisNode->Status != SCE_STATUS_CHECK &&
  1171. ThisNode->Status != SCE_STATUS_NO_AUTO_INHERIT &&
  1172. ThisNode->Status != SCE_STATUS_OVERWRITE )
  1173. goto SkipNode;
  1174. if ( ThisNode->pSecurityDescriptor != NULL ) {
  1175. ScepLogOutput3(2, 0, SCEDLL_SCP_CONFIGURE, ThisNode->ObjectFullName);
  1176. }
  1177. //
  1178. // Process this node first
  1179. // Note: we do not set NULL security descriptor
  1180. //
  1181. if ( ThisNode->pApplySecurityDescriptor != NULL ) {
  1182. if ( ThisNode->pSecurityDescriptor == NULL ) {
  1183. ScepLogOutput3(3, 0, SCEDLL_SCP_CONFIGURE, ThisNode->ObjectFullName);
  1184. }
  1185. BOOL BackSlashExist=FALSE;
  1186. if ( ThisNode->Status == SCE_STATUS_NO_AUTO_INHERIT ) {
  1187. //
  1188. // no auto inherit to children. Apply to this object only
  1189. // this flag is removed since 2/20/1998
  1190. //
  1191. Win32Rc = ScepSetSecurityObjectOnly(
  1192. ThisNode->ObjectFullName,
  1193. ThisNode->SeInfo,
  1194. ThisNode->pApplySecurityDescriptor,
  1195. ObjectType,
  1196. NULL
  1197. );
  1198. rcThisNodeOnly = Win32Rc;
  1199. } else if ( ThisNode->ChildList == NULL &&
  1200. ThisNode->Status != SCE_STATUS_OVERWRITE ) {
  1201. //
  1202. // there is no children
  1203. // apply security to everyone underneeth, using the win32 api.
  1204. //
  1205. Win32Rc = ScepDoesObjectHasChildren(ObjectType,
  1206. ThisNode->ObjectFullName,
  1207. &BackSlashExist // temp use
  1208. );
  1209. if ( Win32Rc == NO_ERROR ) {
  1210. if ( BackSlashExist ) {
  1211. //
  1212. // this is a container which has children
  1213. //
  1214. //
  1215. // new marta API without considering parent
  1216. //
  1217. Win32Rc = AccRewriteSetNamedRights(
  1218. ThisNode->ObjectFullName,
  1219. ObjectType,
  1220. ThisNode->SeInfo,
  1221. ThisNode->pApplySecurityDescriptor,
  1222. TRUE // bSkipInheritanceComputation
  1223. );
  1224. /*
  1225. Win32Rc = ScepSetSecurityWin32(
  1226. ThisNode->ObjectFullName,
  1227. ThisNode->SeInfo,
  1228. ThisNode->pApplySecurityDescriptor,
  1229. ObjectType
  1230. );
  1231. */
  1232. } else {
  1233. //
  1234. // no children
  1235. //
  1236. Win32Rc = ScepSetSecurityObjectOnly(
  1237. ThisNode->ObjectFullName,
  1238. ThisNode->SeInfo,
  1239. ThisNode->pApplySecurityDescriptor,
  1240. ObjectType,
  1241. NULL
  1242. );
  1243. }
  1244. } else {
  1245. ScepLogOutput3(1, Win32Rc, SCEDLL_SAP_ERROR_ENUMERATE,
  1246. ThisNode->ObjectFullName);
  1247. }
  1248. rcThisNodeOnly = Win32Rc;
  1249. } else {
  1250. //
  1251. // there is child(ren) in the tree, or OVERWRITE flag is set
  1252. //
  1253. Win32Rc = ScepDoesObjectHasChildren(ObjectType,
  1254. ThisNode->ObjectFullName,
  1255. &BackSlashExist // temp use
  1256. );
  1257. rcThisNodeOnly = Win32Rc;
  1258. if ( Win32Rc != ERROR_SUCCESS ) {
  1259. //
  1260. // for registry keys, the above function could fail if the key does
  1261. // not exist. Log the error in this case
  1262. //
  1263. ScepLogOutput3(1, Win32Rc, SCEDLL_SAP_ERROR_ENUMERATE,
  1264. ThisNode->ObjectFullName);
  1265. }
  1266. if ( Win32Rc == ERROR_SUCCESS && !BackSlashExist ) {
  1267. //
  1268. // no child exist
  1269. //
  1270. if (ThisNode->Status == SCE_STATUS_OVERWRITE ) {
  1271. //
  1272. // if OVERWRITE flag set and no children, set now (top-down)
  1273. // if OVERWRITE flag and has children then share logic with 0 mode, set later (bottom-up)
  1274. // maybe we can have all OVERWRITE mode go bottom-up if goto SkipNode is removed here
  1275. //
  1276. Win32Rc = ScepSetSecurityObjectOnly(
  1277. ThisNode->ObjectFullName,
  1278. ThisNode->SeInfo,
  1279. ThisNode->pApplySecurityDescriptor,
  1280. ObjectType,
  1281. &BackSlashExist
  1282. );
  1283. rcThisNodeOnly = rcThisNodeOnly == NO_ERROR ? Win32Rc: rcThisNodeOnly;
  1284. }
  1285. goto SkipNode;
  1286. }
  1287. if ( Win32Rc == ERROR_SUCCESS && BackSlashExist ) {
  1288. //
  1289. // set security for other files/keys under this directory
  1290. //
  1291. //
  1292. // child exist, set child node first
  1293. // set security for other files/keys under this directory
  1294. //
  1295. switch ( ObjectType ) {
  1296. case SE_FILE_OBJECT:
  1297. //
  1298. // detect if there is a \ at the end
  1299. //
  1300. BackSlashExist = ScepLastBackSlash(ThisNode->ObjectFullName);
  1301. Win32Rc = ScepConfigureOneSubTreeFile(ThisNode,
  1302. ObjectType,
  1303. Token,
  1304. GenericMapping,
  1305. BackSlashExist
  1306. );
  1307. break;
  1308. case SE_REGISTRY_KEY:
  1309. #ifdef _WIN64
  1310. case SE_REGISTRY_WOW64_32KEY:
  1311. #endif
  1312. //
  1313. // process this key and any sub keys
  1314. //
  1315. Win32Rc = ScepConfigureOneSubTreeKey(ThisNode,
  1316. ObjectType,
  1317. Token,
  1318. GenericMapping
  1319. );
  1320. break;
  1321. }
  1322. //
  1323. // this rc is the status for configuration of children of ThisNode
  1324. //
  1325. rcThisNodeChildren = Win32Rc;
  1326. }
  1327. }
  1328. //
  1329. // ignore some error codes and continue to configure other objects
  1330. //
  1331. if ( SCEP_IGNORE_SOME_ERRORS(Win32Rc) ) {
  1332. gWarningCode = Win32Rc;
  1333. rc = SCESTATUS_SUCCESS;
  1334. goto SkipNode;
  1335. }
  1336. if ( Win32Rc != ERROR_SUCCESS ) {
  1337. //
  1338. // if security for this object was specified in the config template/database, log to RSOP status
  1339. //
  1340. if (ThisNode->pSecurityDescriptor && (ConfigOptions & SCE_RSOP_CALLBACK) ) {
  1341. ScepRsopLog(ObjectType == SE_FILE_OBJECT ?
  1342. SCE_RSOP_FILE_SECURITY_INFO :
  1343. SCE_RSOP_REGISTRY_SECURITY_INFO,
  1344. rcThisNodeOnly,
  1345. ThisNode->ObjectFullName,0,0);
  1346. if (rcThisNodeOnly == ERROR_SUCCESS && rcThisNodeChildren != ERROR_SUCCESS) {
  1347. ScepRsopLog(ObjectType == SE_FILE_OBJECT ?
  1348. (SCE_RSOP_FILE_SECURITY_INFO | SCE_RSOP_FILE_SECURITY_INFO_CHILD) :
  1349. (SCE_RSOP_REGISTRY_SECURITY_INFO | SCE_RSOP_REGISTRY_SECURITY_INFO_CHILD),
  1350. rcThisNodeChildren,
  1351. ThisNode->ObjectFullName,0,0);
  1352. }
  1353. }
  1354. return(ScepDosErrorToSceStatus(Win32Rc));
  1355. }
  1356. }
  1357. //
  1358. // then process children
  1359. //
  1360. for ( PSCE_OBJECT_CHILD_LIST pTemp = ThisNode->ChildList;
  1361. pTemp != NULL; pTemp = pTemp->Next ) {
  1362. if ( pTemp->Node == NULL ) continue;
  1363. rc = ScepConfigureObjectTree(
  1364. pTemp->Node,
  1365. ObjectType,
  1366. Token,
  1367. GenericMapping,
  1368. ConfigOptions
  1369. );
  1370. Win32Rc = ScepSceStatusToDosError(rc);
  1371. //
  1372. // ignore some error codes and continue to configure other objects
  1373. //
  1374. if ( SCEP_IGNORE_SOME_ERRORS(Win32Rc) ) {
  1375. gWarningCode = Win32Rc;
  1376. Win32Rc = ERROR_SUCCESS;
  1377. rc = SCESTATUS_SUCCESS;
  1378. }
  1379. if ( rc != SCESTATUS_SUCCESS )
  1380. return(rc);
  1381. }
  1382. if ( ThisNode->pApplySecurityDescriptor != NULL &&
  1383. ThisNode->Status != SCE_STATUS_NO_AUTO_INHERIT &&
  1384. ( ThisNode->ChildList != NULL ||
  1385. ThisNode->Status == SCE_STATUS_OVERWRITE ) ) {
  1386. //
  1387. // finally config the current node - (post order)
  1388. //
  1389. Win32Rc = ScepSetSecurityObjectOnly(
  1390. ThisNode->ObjectFullName,
  1391. ThisNode->SeInfo,
  1392. ThisNode->pApplySecurityDescriptor,
  1393. ObjectType,
  1394. NULL
  1395. );
  1396. rc = ScepDosErrorToSceStatus(Win32Rc);
  1397. rcThisNodeOnly = rcThisNodeOnly == NO_ERROR ? Win32Rc: rcThisNodeOnly;
  1398. //
  1399. // ignore the following error codes and continue to configure other objects
  1400. //
  1401. if ( SCEP_IGNORE_SOME_ERRORS(Win32Rc) ) {
  1402. gWarningCode = Win32Rc;
  1403. Win32Rc = ERROR_SUCCESS;
  1404. rc = SCESTATUS_SUCCESS;
  1405. }
  1406. }
  1407. SkipNode:
  1408. //
  1409. // if security for this object was specified in the config template/database, log to RSOP status
  1410. //
  1411. if (ThisNode->pSecurityDescriptor && (ConfigOptions & SCE_RSOP_CALLBACK) ) {
  1412. ScepRsopLog(ObjectType == SE_FILE_OBJECT ?
  1413. SCE_RSOP_FILE_SECURITY_INFO :
  1414. SCE_RSOP_REGISTRY_SECURITY_INFO,
  1415. rcThisNodeOnly,
  1416. ThisNode->ObjectFullName,0,0);
  1417. if (rcThisNodeOnly == ERROR_SUCCESS && rcThisNodeChildren != ERROR_SUCCESS) {
  1418. ScepRsopLog(ObjectType == SE_FILE_OBJECT ?
  1419. (SCE_RSOP_FILE_SECURITY_INFO | SCE_RSOP_FILE_SECURITY_INFO_CHILD) :
  1420. (SCE_RSOP_REGISTRY_SECURITY_INFO | SCE_RSOP_REGISTRY_SECURITY_INFO_CHILD),
  1421. rcThisNodeChildren,
  1422. ThisNode->ObjectFullName,0,0);
  1423. }
  1424. }
  1425. return(rc);
  1426. }
  1427. DWORD
  1428. ScepConfigureOneSubTreeFile(
  1429. IN PSCE_OBJECT_TREE ThisNode,
  1430. IN SE_OBJECT_TYPE ObjectType,
  1431. IN HANDLE Token,
  1432. IN PGENERIC_MAPPING GenericMapping,
  1433. IN BOOL BackSlashExist
  1434. )
  1435. {
  1436. if ( NULL == ThisNode ) {
  1437. return(ERROR_SUCCESS);
  1438. }
  1439. DWORD BufSize;
  1440. PWSTR Buffer=NULL;
  1441. //
  1442. // find all files under this directory/file
  1443. //
  1444. BufSize = wcslen(ThisNode->ObjectFullName)+4;
  1445. Buffer = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  1446. if ( Buffer == NULL ) {
  1447. return( ERROR_NOT_ENOUGH_MEMORY );
  1448. }
  1449. if ( BackSlashExist ) {
  1450. swprintf(Buffer, L"%s*.*", ThisNode->ObjectFullName);
  1451. } else {
  1452. swprintf(Buffer, L"%s\\*.*", ThisNode->ObjectFullName);
  1453. }
  1454. intptr_t hFile;
  1455. struct _wfinddata_t *pFileInfo=NULL;
  1456. //
  1457. // allocate the find buffer
  1458. //
  1459. pFileInfo = (struct _wfinddata_t *)ScepAlloc(0,sizeof(struct _wfinddata_t));
  1460. if ( pFileInfo == NULL ) {
  1461. ScepFree(Buffer);
  1462. return( ERROR_NOT_ENOUGH_MEMORY );
  1463. }
  1464. hFile = _wfindfirst(Buffer, pFileInfo);
  1465. ScepFree(Buffer);
  1466. Buffer = NULL;
  1467. DWORD Win32Rc = ERROR_SUCCESS;
  1468. BOOL bFilePresentInTree;
  1469. if ( hFile != -1 ) {
  1470. PSCE_OBJECT_CHILD_LIST pTemp;
  1471. INT i;
  1472. DWORD EnumRc;
  1473. PSECURITY_DESCRIPTOR pChildrenSD=NULL;
  1474. do {
  1475. if ( pFileInfo->name[0] == L'.' &&
  1476. (pFileInfo->name[1] == L'\0' || (pFileInfo->name[1] == L'.' && pFileInfo->name[2] == L'\0')))
  1477. continue;
  1478. bFilePresentInTree = ScepBinarySearch(
  1479. ThisNode->aChildNames,
  1480. ThisNode->dwSize_aChildNames,
  1481. pFileInfo->name);
  1482. if ( ! bFilePresentInTree ) {
  1483. //
  1484. // The name is not in the list, so set.
  1485. // build the full name first
  1486. //
  1487. BufSize = wcslen(ThisNode->ObjectFullName)+wcslen(pFileInfo->name)+1;
  1488. Buffer = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  1489. if ( Buffer == NULL ) {
  1490. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  1491. break;
  1492. }
  1493. if ( BackSlashExist ) {
  1494. swprintf(Buffer, L"%s%s", ThisNode->ObjectFullName, pFileInfo->name);
  1495. } else {
  1496. swprintf(Buffer, L"%s\\%s", ThisNode->ObjectFullName, pFileInfo->name);
  1497. }
  1498. EnumRc = pFileInfo->attrib; // borrow this variable temperaorily
  1499. ScepFree(pFileInfo);
  1500. pFileInfo = NULL;
  1501. //
  1502. // compute the SDs for each individual object
  1503. //
  1504. Win32Rc = ScepGetNewSecurity(
  1505. Buffer,
  1506. ThisNode->pApplySecurityDescriptor, // parent's SD
  1507. NULL,
  1508. (BYTE)((ThisNode->Status != SCE_STATUS_OVERWRITE ) ? SCETREE_QUERY_SD : 0),
  1509. (BOOLEAN)(EnumRc & _A_SUBDIR),
  1510. ThisNode->SeInfo,
  1511. ObjectType,
  1512. Token,
  1513. GenericMapping,
  1514. &pChildrenSD
  1515. );
  1516. if (Win32Rc == ERROR_SHARING_VIOLATION ||
  1517. Win32Rc == ERROR_ACCESS_DENIED ||
  1518. Win32Rc == ERROR_CANT_ACCESS_FILE) {
  1519. ScepLogOutput3(1, Win32Rc, SCEDLL_ERROR_BUILD_SD, Buffer);
  1520. }
  1521. if ( Win32Rc == NO_ERROR ) {
  1522. if ( !(EnumRc & _A_SUBDIR) ) {
  1523. // this is a single file
  1524. //
  1525. Win32Rc = ScepSetSecurityObjectOnly(
  1526. Buffer,
  1527. (ThisNode->SeInfo & DACL_SECURITY_INFORMATION) |
  1528. (ThisNode->SeInfo & SACL_SECURITY_INFORMATION),
  1529. pChildrenSD,
  1530. ObjectType,
  1531. NULL
  1532. );
  1533. } else if ( ThisNode->Status == SCE_STATUS_OVERWRITE ) {
  1534. //
  1535. // enumerate all nodes under this one and "empty" explicit aces by
  1536. // calling NtSetSecurityInfo directly but please note
  1537. // Creator Owner Ace should be reserved
  1538. //
  1539. Win32Rc = ScepSetSecurityOverwriteExplicit(
  1540. Buffer,
  1541. (ThisNode->SeInfo & DACL_SECURITY_INFORMATION) |
  1542. (ThisNode->SeInfo & SACL_SECURITY_INFORMATION),
  1543. pChildrenSD,
  1544. ObjectType,
  1545. Token,
  1546. GenericMapping
  1547. );
  1548. } else {
  1549. //
  1550. // new marta API without considering parent
  1551. //
  1552. Win32Rc = AccRewriteSetNamedRights(
  1553. Buffer,
  1554. ObjectType,
  1555. ThisNode->SeInfo & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION),
  1556. pChildrenSD,
  1557. TRUE // bSkipInheritanceComputation
  1558. );
  1559. /*
  1560. Win32Rc = ScepSetSecurityWin32(
  1561. Buffer,
  1562. (ThisNode->SeInfo & DACL_SECURITY_INFORMATION) |
  1563. (ThisNode->SeInfo & SACL_SECURITY_INFORMATION),
  1564. pChildrenSD,
  1565. ObjectType
  1566. );
  1567. */
  1568. if ( Win32Rc != ERROR_SUCCESS ) {
  1569. //
  1570. // something is wrong to set inheritance info, log it
  1571. // but still continue to the next one
  1572. //
  1573. gWarningCode = Win32Rc;
  1574. Win32Rc = NO_ERROR;
  1575. }
  1576. }
  1577. }
  1578. ScepFree(Buffer);
  1579. Buffer = NULL;
  1580. //
  1581. // free the SD pointers allocated for this object
  1582. //
  1583. if ( pChildrenSD != NULL )
  1584. RtlDeleteSecurityObject( &pChildrenSD );
  1585. pChildrenSD = NULL;
  1586. if (Win32Rc == ERROR_FILE_NOT_FOUND ||
  1587. Win32Rc == ERROR_PATH_NOT_FOUND ||
  1588. Win32Rc == ERROR_SHARING_VIOLATION ||
  1589. Win32Rc == ERROR_ACCESS_DENIED ||
  1590. Win32Rc == ERROR_CANT_ACCESS_FILE ) {
  1591. gWarningCode = Win32Rc;
  1592. Win32Rc = NO_ERROR;
  1593. } else if ( Win32Rc != ERROR_SUCCESS )
  1594. break;
  1595. pFileInfo = (struct _wfinddata_t *)ScepAlloc(0,sizeof(struct _wfinddata_t));
  1596. if ( pFileInfo == NULL ) {
  1597. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  1598. break;
  1599. }
  1600. }
  1601. } while ( _wfindnext(hFile, pFileInfo) == 0 );
  1602. _findclose(hFile);
  1603. //
  1604. // free memory if allocated
  1605. //
  1606. if ( pChildrenSD != NULL &&
  1607. pChildrenSD != ThisNode->pApplySecurityDescriptor ) {
  1608. RtlDeleteSecurityObject( &pChildrenSD );
  1609. pChildrenSD = NULL;
  1610. }
  1611. }
  1612. if ( pFileInfo != NULL ) {
  1613. ScepFree(pFileInfo);
  1614. pFileInfo = NULL;
  1615. }
  1616. if ( Buffer != NULL ) {
  1617. ScepFree(Buffer);
  1618. Buffer = NULL;
  1619. }
  1620. return(Win32Rc);
  1621. }
  1622. DWORD
  1623. ScepConfigureOneSubTreeKey(
  1624. IN PSCE_OBJECT_TREE ThisNode,
  1625. IN SE_OBJECT_TYPE ObjectType,
  1626. IN HANDLE Token,
  1627. IN PGENERIC_MAPPING GenericMapping
  1628. )
  1629. {
  1630. if ( NULL == ThisNode ) {
  1631. return(ERROR_SUCCESS);
  1632. }
  1633. HKEY hKey=NULL;
  1634. DWORD Win32Rc;
  1635. DWORD SubKeyLen;
  1636. PWSTR Buffer1=NULL;
  1637. //
  1638. // open the key
  1639. //
  1640. Win32Rc = ScepOpenRegistryObject(
  1641. ObjectType,
  1642. ThisNode->ObjectFullName,
  1643. KEY_READ,
  1644. &hKey
  1645. );
  1646. if ( Win32Rc == ERROR_SUCCESS ) {
  1647. SubKeyLen = 0;
  1648. Win32Rc = RegQueryInfoKey (
  1649. hKey,
  1650. NULL,
  1651. NULL,
  1652. NULL,
  1653. NULL,
  1654. &SubKeyLen,
  1655. NULL,
  1656. NULL,
  1657. NULL,
  1658. NULL,
  1659. NULL,
  1660. NULL
  1661. );
  1662. } else {
  1663. ScepLogOutput3(1, Win32Rc, SCEDLL_ERROR_OPEN, ThisNode->ObjectFullName );
  1664. }
  1665. if ( Win32Rc == ERROR_SUCCESS ) {
  1666. //
  1667. // enumerate all subkeys of the key
  1668. //
  1669. Buffer1 = (PWSTR)ScepAlloc(0, (SubKeyLen+2)*sizeof(WCHAR));
  1670. if ( Buffer1 == NULL ) {
  1671. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  1672. }
  1673. }
  1674. if ( Win32Rc == ERROR_SUCCESS ) {
  1675. DWORD index;
  1676. DWORD EnumRc;
  1677. DWORD BufSize;
  1678. PSCE_OBJECT_CHILD_LIST pTemp;
  1679. INT i;
  1680. PWSTR Buffer=NULL;
  1681. PSECURITY_DESCRIPTOR pChildrenSD=NULL;
  1682. BOOL bKeyPresentInTree;
  1683. index = 0;
  1684. do {
  1685. BufSize = SubKeyLen+1;
  1686. memset(Buffer1, L'\0', (SubKeyLen+2)*sizeof(WCHAR));
  1687. EnumRc = RegEnumKeyEx(hKey,
  1688. index,
  1689. Buffer1,
  1690. &BufSize,
  1691. NULL,
  1692. NULL,
  1693. NULL,
  1694. NULL);
  1695. if ( EnumRc == ERROR_SUCCESS ) {
  1696. index++;
  1697. //
  1698. // find if the subkey is already in the tree
  1699. // if it is in the tree, it will be processed later
  1700. //
  1701. bKeyPresentInTree = ScepBinarySearch(
  1702. ThisNode->aChildNames,
  1703. ThisNode->dwSize_aChildNames,
  1704. Buffer1);
  1705. if ( ! bKeyPresentInTree ) {
  1706. //
  1707. // The name is not in the list, so set
  1708. // build the fullname first
  1709. //
  1710. BufSize += wcslen(ThisNode->ObjectFullName)+1;
  1711. Buffer = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  1712. if ( Buffer == NULL ) {
  1713. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  1714. break;
  1715. }
  1716. swprintf(Buffer, L"%s\\%s", ThisNode->ObjectFullName, Buffer1);
  1717. ScepLogOutput3(3, 0, SCEDLL_SCP_CONFIGURE, Buffer);
  1718. //
  1719. // compute the SDs for each individual object
  1720. //
  1721. Win32Rc = ScepGetNewSecurity(
  1722. Buffer,
  1723. ThisNode->pApplySecurityDescriptor, // parent's SD
  1724. NULL,
  1725. (BYTE)((ThisNode->Status != SCE_STATUS_OVERWRITE ) ? SCETREE_QUERY_SD : 0),
  1726. (BOOLEAN)TRUE,
  1727. ThisNode->SeInfo,
  1728. ObjectType,
  1729. Token,
  1730. GenericMapping,
  1731. &pChildrenSD
  1732. );
  1733. if (Win32Rc == ERROR_SHARING_VIOLATION ||
  1734. Win32Rc == ERROR_ACCESS_DENIED ||
  1735. Win32Rc == ERROR_CANT_ACCESS_FILE) {
  1736. ScepLogOutput3(1, Win32Rc, SCEDLL_ERROR_BUILD_SD, Buffer);
  1737. }
  1738. if ( Win32Rc == ERROR_SUCCESS ) {
  1739. if ( ThisNode->Status == SCE_STATUS_OVERWRITE ) {
  1740. //
  1741. // enumerate all nodes under this one and "empty" explicit aces by
  1742. // calling NtSetSecurityInfo directly
  1743. //
  1744. Win32Rc = ScepSetSecurityOverwriteExplicit(
  1745. Buffer,
  1746. (ThisNode->SeInfo & DACL_SECURITY_INFORMATION) |
  1747. (ThisNode->SeInfo & SACL_SECURITY_INFORMATION),
  1748. pChildrenSD,
  1749. ObjectType,
  1750. Token,
  1751. GenericMapping
  1752. );
  1753. } else {
  1754. //
  1755. // new marta API without considering parent
  1756. //
  1757. Win32Rc = AccRewriteSetNamedRights(
  1758. Buffer,
  1759. ObjectType,
  1760. ThisNode->SeInfo & (DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION),
  1761. pChildrenSD,
  1762. TRUE // bSkipInheritanceComputation
  1763. );
  1764. /*
  1765. Win32Rc = ScepSetSecurityWin32(
  1766. Buffer,
  1767. (ThisNode->SeInfo & DACL_SECURITY_INFORMATION) |
  1768. (ThisNode->SeInfo & SACL_SECURITY_INFORMATION),
  1769. pChildrenSD, // ThisNode->pApplySecurityDescriptor, calculate autoinheritance
  1770. ObjectType
  1771. );
  1772. */
  1773. if ( Win32Rc != ERROR_SUCCESS ) {
  1774. //
  1775. // can't set inheritance to children, log it but continue
  1776. //
  1777. gWarningCode = Win32Rc;
  1778. Win32Rc = NO_ERROR;
  1779. }
  1780. }
  1781. }
  1782. if ( pChildrenSD != NULL ) {
  1783. RtlDeleteSecurityObject( &pChildrenSD );
  1784. pChildrenSD = NULL;
  1785. }
  1786. if ( Win32Rc == ERROR_FILE_NOT_FOUND ||
  1787. Win32Rc == ERROR_INVALID_HANDLE ||
  1788. Win32Rc == ERROR_PATH_NOT_FOUND ||
  1789. Win32Rc == ERROR_ACCESS_DENIED ||
  1790. Win32Rc == ERROR_CANT_ACCESS_FILE ||
  1791. Win32Rc == ERROR_SHARING_VIOLATION ) {
  1792. gWarningCode = Win32Rc;
  1793. Win32Rc = NO_ERROR;
  1794. }
  1795. if ( Win32Rc != ERROR_SUCCESS )
  1796. ScepLogOutput3(1, Win32Rc, SCEDLL_ERROR_SET_SECURITY, Buffer);
  1797. ScepFree(Buffer);
  1798. Buffer = NULL;
  1799. if ( Win32Rc != ERROR_SUCCESS )
  1800. break;
  1801. }
  1802. } else if ( EnumRc != ERROR_NO_MORE_ITEMS ) {
  1803. break;
  1804. }
  1805. } while ( EnumRc != ERROR_NO_MORE_ITEMS );
  1806. ScepFree(Buffer1);
  1807. Buffer1 = NULL;
  1808. if ( EnumRc != ERROR_SUCCESS && EnumRc != ERROR_NO_MORE_ITEMS ) {
  1809. ScepLogOutput3(1, EnumRc, SCEDLL_SAP_ERROR_ENUMERATE,
  1810. ThisNode->ObjectFullName );
  1811. if ( Win32Rc == ERROR_SUCCESS )
  1812. Win32Rc = EnumRc;
  1813. }
  1814. //
  1815. // free memory if allocated
  1816. //
  1817. if ( pChildrenSD != NULL &&
  1818. pChildrenSD != ThisNode->pApplySecurityDescriptor ) {
  1819. RtlDeleteSecurityObject( &pChildrenSD );
  1820. pChildrenSD = NULL;
  1821. }
  1822. if ( Buffer != NULL ) {
  1823. ScepFree(Buffer);
  1824. Buffer = NULL;
  1825. }
  1826. }
  1827. if ( hKey ) {
  1828. RegCloseKey(hKey);
  1829. }
  1830. return(Win32Rc);
  1831. }
  1832. SCESTATUS
  1833. ScepFreeObject2Security(
  1834. IN PSCE_OBJECT_CHILD_LIST NodeList,
  1835. IN BOOL bFreeComputedSDOnly
  1836. )
  1837. /* ++
  1838. Routine Description:
  1839. This routine frees memory allocated by the security object tree.
  1840. Arguments:
  1841. ThisNode - one node in the tree
  1842. Return value:
  1843. None
  1844. -- */
  1845. {
  1846. NTSTATUS NtStatus;
  1847. SCESTATUS rc;
  1848. if ( NodeList == NULL )
  1849. return(SCESTATUS_SUCCESS);
  1850. PSCE_OBJECT_CHILD_LIST pTemp,pTemp1;
  1851. PSCE_OBJECT_TREE ThisNode;
  1852. //
  1853. // free children first
  1854. //
  1855. pTemp = NodeList;
  1856. while ( pTemp != NULL ) {
  1857. if ( pTemp->Node ) {
  1858. ThisNode = pTemp->Node;
  1859. rc = ScepFreeObject2Security(ThisNode->ChildList, bFreeComputedSDOnly);
  1860. //
  1861. // both security descriptors need to be freed for SAP/SMP type
  1862. //
  1863. if ( ThisNode->pApplySecurityDescriptor != NULL &&
  1864. ThisNode->pApplySecurityDescriptor != ThisNode->pSecurityDescriptor ) {
  1865. NtStatus = RtlDeleteSecurityObject(
  1866. &(ThisNode->pApplySecurityDescriptor)
  1867. );
  1868. ThisNode->pApplySecurityDescriptor = NULL;
  1869. }
  1870. if (!bFreeComputedSDOnly) {
  1871. if ( ThisNode->pSecurityDescriptor != NULL )
  1872. ScepFree(ThisNode->pSecurityDescriptor);
  1873. if ( ThisNode->Name != NULL)
  1874. ScepFree(ThisNode->Name);
  1875. if ( ThisNode->ObjectFullName != NULL )
  1876. ScepFree(ThisNode->ObjectFullName);
  1877. if ( ThisNode->aChildNames != NULL ) {
  1878. LocalFree(ThisNode->aChildNames);
  1879. }
  1880. ScepFree(ThisNode);
  1881. }
  1882. }
  1883. pTemp1 = pTemp;
  1884. pTemp = pTemp->Next;
  1885. if (!bFreeComputedSDOnly) {
  1886. ScepFree(pTemp1);
  1887. }
  1888. }
  1889. return(SCESTATUS_SUCCESS);
  1890. }
  1891. DWORD
  1892. ScepSetSecurityWin32(
  1893. IN PCWSTR ObjectName,
  1894. IN SECURITY_INFORMATION SeInfo,
  1895. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  1896. IN SE_OBJECT_TYPE ObjectType
  1897. )
  1898. /* ++
  1899. Routine Description:
  1900. This routine set security information to the object and inherited aces
  1901. are set to the object's children by calling Win32 API SetNamedSecurityInfo
  1902. Arguments:
  1903. ObjecName - name of the object to set security to
  1904. SeInfo - Security information to set
  1905. pSecurityDescriptor - the security descriptor
  1906. ObjectType - type of the object
  1907. SE_FILE_OBJECT
  1908. SE_REGISTRY_KEY
  1909. SE_DS_OBJECT
  1910. Return value:
  1911. Win32 error code
  1912. -- */
  1913. {
  1914. if ( !ObjectName || !pSecurityDescriptor || SeInfo == 0 ) {
  1915. return(ERROR_INVALID_PARAMETER);
  1916. }
  1917. DWORD Win32rc = NO_ERROR;
  1918. SECURITY_INFORMATION SeInfoSet;
  1919. BOOLEAN tFlag;
  1920. BOOLEAN aclPresent;
  1921. PSID pOwner=NULL;
  1922. PSID pGroup=NULL;
  1923. PACL pDacl=NULL;
  1924. PACL pSacl=NULL;
  1925. SECURITY_DESCRIPTOR_CONTROL Control=0;
  1926. if ( pSecurityDescriptor != NULL ) {
  1927. RtlGetControlSecurityDescriptor (
  1928. pSecurityDescriptor,
  1929. &Control,
  1930. &Win32rc // temp use
  1931. );
  1932. //
  1933. // Get Owner address
  1934. // always get the owner in case take ownership occurs
  1935. //
  1936. Win32rc = RtlNtStatusToDosError(
  1937. RtlGetOwnerSecurityDescriptor(
  1938. pSecurityDescriptor,
  1939. &pOwner,
  1940. &tFlag));
  1941. #if 0
  1942. //
  1943. // Get Group address
  1944. //
  1945. if ( SeInfo & GROUP_SECURITY_INFORMATION ) {
  1946. Win32rc = RtlNtStatusToDosError(
  1947. RtlGetGroupSecurityDescriptor(
  1948. pSecurityDescriptor,
  1949. &pGroup,
  1950. &tFlag));
  1951. }
  1952. #endif
  1953. //
  1954. // Get DACL address
  1955. //
  1956. if ( SeInfo & DACL_SECURITY_INFORMATION ) {
  1957. Win32rc = RtlNtStatusToDosError(
  1958. RtlGetDaclSecurityDescriptor(
  1959. pSecurityDescriptor,
  1960. &aclPresent,
  1961. &pDacl,
  1962. &tFlag));
  1963. if (Win32rc == NO_ERROR && !aclPresent )
  1964. pDacl = NULL;
  1965. }
  1966. //
  1967. // Get SACL address
  1968. //
  1969. if ( SeInfo & SACL_SECURITY_INFORMATION ) {
  1970. Win32rc = RtlNtStatusToDosError(
  1971. RtlGetSaclSecurityDescriptor(
  1972. pSecurityDescriptor,
  1973. &aclPresent,
  1974. &pSacl,
  1975. &tFlag));
  1976. if ( Win32rc == NO_ERROR && !aclPresent )
  1977. pSacl = NULL;
  1978. }
  1979. }
  1980. //
  1981. // if error occurs for this one, do not set. return
  1982. //
  1983. if ( Win32rc != NO_ERROR ) {
  1984. ScepLogOutput3(1, Win32rc, SCEDLL_INVALID_SECURITY, (PWSTR)ObjectName );
  1985. return(Win32rc);
  1986. }
  1987. //
  1988. // set permission
  1989. //
  1990. #ifdef SCE_DBG
  1991. printf("Calling SetNamedSecurityInfo:\n");
  1992. ScepPrintSecurityDescriptor( pSecurityDescriptor, TRUE );
  1993. #endif
  1994. //
  1995. // should set owner/group separately from dacl/sacl
  1996. // if access is denied, take ownership will occur.
  1997. //
  1998. if ( Win32rc != NO_ERROR ) {
  1999. //
  2000. // ignore the error code from setting owner/group
  2001. //
  2002. Win32rc = NO_ERROR;
  2003. }
  2004. //
  2005. // set DACL/SACL
  2006. //
  2007. SeInfoSet = 0;
  2008. if ( (SeInfo & DACL_SECURITY_INFORMATION) && pDacl ) {
  2009. SeInfoSet |= DACL_SECURITY_INFORMATION;
  2010. if ( Control & SE_DACL_PROTECTED ) {
  2011. SeInfoSet |= PROTECTED_DACL_SECURITY_INFORMATION;
  2012. }
  2013. }
  2014. if ( (SeInfo & SACL_SECURITY_INFORMATION) && pSacl ) {
  2015. SeInfoSet |= SACL_SECURITY_INFORMATION;
  2016. if ( Control & SE_SACL_PROTECTED ) {
  2017. SeInfoSet |= PROTECTED_SACL_SECURITY_INFORMATION;
  2018. }
  2019. }
  2020. Win32rc = SetNamedSecurityInfo(
  2021. (LPWSTR)ObjectName,
  2022. ObjectType,
  2023. SeInfoSet,
  2024. NULL,
  2025. NULL,
  2026. pDacl,
  2027. pSacl
  2028. );
  2029. if ( (Win32rc == ERROR_ACCESS_DENIED || Win32rc == ERROR_CANT_ACCESS_FILE) && NULL != AdminsSid ) {
  2030. //
  2031. // access denied, take ownership and then set
  2032. // should backup the old owner first
  2033. // NOTE: the old owner of this object is already stored in pOwner
  2034. // (pSecurityDescritor) which is queried from ScepGetNewSecurity(...
  2035. //
  2036. ScepLogOutput3(3,0, SCEDLL_SCP_TAKE_OWNER, (LPWSTR)ObjectName);
  2037. Win32rc = SetNamedSecurityInfo(
  2038. (LPWSTR)ObjectName,
  2039. ObjectType,
  2040. OWNER_SECURITY_INFORMATION,
  2041. AdminsSid,
  2042. NULL,
  2043. NULL,
  2044. NULL
  2045. );
  2046. if ( Win32rc == NO_ERROR ) {
  2047. //
  2048. // ownership is changed, then set security again
  2049. //
  2050. Win32rc = SetNamedSecurityInfo(
  2051. (LPWSTR)ObjectName,
  2052. ObjectType,
  2053. SeInfoSet,
  2054. NULL,
  2055. NULL,
  2056. pDacl,
  2057. pSacl
  2058. );
  2059. //
  2060. // set the old owner back (later)
  2061. //
  2062. } else {
  2063. ScepLogOutput3(2,Win32rc, SCEDLL_ERROR_TAKE_OWNER, (LPWSTR)ObjectName);
  2064. }
  2065. } else {
  2066. //
  2067. // no takeownership action is taken
  2068. //
  2069. if ( !(SeInfo & OWNER_SECURITY_INFORMATION) ) {
  2070. pOwner = NULL;
  2071. }
  2072. }
  2073. if ( Win32rc != NO_ERROR ) {
  2074. ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_SET_SECURITY,
  2075. (PWSTR)ObjectName );
  2076. } else {
  2077. if ( pOwner != NULL || pGroup != NULL ) {
  2078. if ( pOwner != NULL )
  2079. SeInfoSet = OWNER_SECURITY_INFORMATION;
  2080. else
  2081. SeInfoSet = 0;
  2082. if ( pGroup != NULL )
  2083. SeInfoSet |= GROUP_SECURITY_INFORMATION;
  2084. Win32rc = SetNamedSecurityInfo(
  2085. (LPWSTR)ObjectName,
  2086. ObjectType,
  2087. SeInfoSet,
  2088. pOwner,
  2089. pGroup,
  2090. NULL,
  2091. NULL
  2092. );
  2093. }
  2094. }
  2095. /*
  2096. #if 0
  2097. #ifdef SCE_DBG
  2098. printf("Calling SetNamedSecurityInfoEx:\n");
  2099. ScepPrintSecurityDescriptor( pSecurityDescriptor, TRUE );
  2100. #endif
  2101. //
  2102. // convert to the new structure
  2103. //
  2104. PACTRL_ACCESS pAccess=NULL;
  2105. PACTRL_AUDIT pAudit=NULL;
  2106. LPWSTR pOwner=NULL;
  2107. LPWSTR pGroup=NULL;
  2108. Win32rc = ConvertSecurityDescriptorToAccessNamed(
  2109. ObjectName,
  2110. ObjectType,
  2111. pSecurityDescriptor,
  2112. &pAccess,
  2113. &pAudit,
  2114. &pOwner,
  2115. &pGroup
  2116. );
  2117. if ( Win32rc == ERROR_SUCCESS ) {
  2118. //
  2119. // set DACL/SACL
  2120. //
  2121. SeInfoSet = (SeInfo & DACL_SECURITY_INFORMATION) |
  2122. (SeInfo & SACL_SECURITY_INFORMATION);
  2123. Win32rc = SetNamedSecurityInfoEx(
  2124. ObjectName,
  2125. ObjectType,
  2126. SeInfoSet,
  2127. NULL,
  2128. pAccess,
  2129. pAudit,
  2130. NULL,
  2131. NULL,
  2132. NULL
  2133. );
  2134. if ( (Win32rc == ERROR_ACCESS_DENIED || Win32rc == ERROR_CANT_ACCESS_FILE) && NULL != AdminsSid ) {
  2135. //
  2136. // access denied, take ownership and then set
  2137. // should backup the old owner first
  2138. // NOTE: the old owner of this object is already stored in pOwner
  2139. // (pSecurityDescritor) which is queried from ScepGetNewSecurity(...
  2140. //
  2141. ScepLogOutput3(3,0, SCEDLL_SCP_TAKE_OWNER, (LPWSTR)ObjectName);
  2142. Win32rc = SetNamedSecurityInfo(
  2143. (LPWSTR)ObjectName,
  2144. ObjectType,
  2145. OWNER_SECURITY_INFORMATION,
  2146. AdminsSid,
  2147. NULL,
  2148. NULL,
  2149. NULL
  2150. );
  2151. if ( Win32rc == NO_ERROR ) {
  2152. //
  2153. // ownership is changed, then set security again
  2154. //
  2155. Win32rc = SetNamedSecurityInfoEx(
  2156. ObjectName,
  2157. ObjectType,
  2158. SeInfoSet,
  2159. NULL,
  2160. pAccess,
  2161. pAudit,
  2162. NULL,
  2163. NULL,
  2164. NULL
  2165. );
  2166. //
  2167. // set the old owner back (later)
  2168. //
  2169. } else {
  2170. ScepLogOutput3(2,Win32rc, SCEDLL_ERROR_TAKE_OWNER, (LPWSTR)ObjectName);
  2171. }
  2172. }
  2173. if ( Win32rc != NO_ERROR ) {
  2174. ScepLogOutput3(1, Win32rc, SCEDLL_ERROR_SET_SECURITY,
  2175. (PWSTR)ObjectName );
  2176. } else {
  2177. if ( pOwner != NULL || pGroup != NULL ) {
  2178. if ( pOwner != NULL )
  2179. SeInfoSet = OWNER_SECURITY_INFORMATION;
  2180. else
  2181. SeInfoSet = 0;
  2182. if ( pGroup != NULL )
  2183. SeInfoSet |= GROUP_SECURITY_INFORMATION;
  2184. Win32rc = SetNamedSecurityInfoEx(
  2185. ObjectName,
  2186. ObjectType,
  2187. SeInfoSet,
  2188. NULL,
  2189. NULL,
  2190. NULL,
  2191. pOwner,
  2192. pGroup,
  2193. NULL
  2194. );
  2195. }
  2196. }
  2197. }
  2198. if ( pAccess ) {
  2199. LocalFree(pAccess);
  2200. }
  2201. if ( pAudit ) {
  2202. LocalFree(pAudit);
  2203. }
  2204. if ( pGroup ) {
  2205. LocalFree(pGroup);
  2206. }
  2207. if ( pOwner ) {
  2208. LocalFree(pOwner);
  2209. }
  2210. #endif
  2211. */
  2212. if (Win32rc == ERROR_FILE_NOT_FOUND ||
  2213. Win32rc == ERROR_PATH_NOT_FOUND ||
  2214. Win32rc == ERROR_SHARING_VIOLATION ||
  2215. Win32rc == ERROR_ACCESS_DENIED ||
  2216. Win32rc == ERROR_CANT_ACCESS_FILE ||
  2217. Win32rc == ERROR_INVALID_HANDLE ) {
  2218. gWarningCode = Win32rc;
  2219. Win32rc = NO_ERROR;
  2220. }
  2221. return(Win32rc);
  2222. }
  2223. DWORD
  2224. ScepSetSecurityOverwriteExplicit(
  2225. IN PCWSTR pszRootObjectName,
  2226. IN SECURITY_INFORMATION SeInfo,
  2227. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  2228. IN SE_OBJECT_TYPE ObjectType,
  2229. IN HANDLE Token,
  2230. IN PGENERIC_MAPPING GenericMapping
  2231. )
  2232. /*
  2233. Routine Description:
  2234. This routine will set security to the current object and all children.
  2235. By calling this function, the existing security descriptor for all children
  2236. will be totally replaced by pSecurityDescriptor if it is a container, or by
  2237. pObjectSecurity if it is a file object.
  2238. The difference between this function and SetNamedSecurityInfo is that
  2239. SetNamedSecurityInfo only overwrites the inherited aces for all children
  2240. but not the explicit aces.
  2241. Arguments:
  2242. ObjectName - The container object's name
  2243. SeInfo - Security Information to set
  2244. pSecurityDescriptor - Security descriptor for container type objects
  2245. ObjectType - The object type
  2246. SE_FILE_OBJECT
  2247. SE_REGISTRY_KEY
  2248. Return Value:
  2249. Win32 error codes
  2250. */
  2251. {
  2252. PSCEP_STACK_NODE pStackHead = NULL;
  2253. DWORD rc;
  2254. BOOL bPushedOntoStack = FALSE;
  2255. //
  2256. // for file objects - to avoid excessive heap operations
  2257. //
  2258. struct _wfinddata_t FileInfo = {0};
  2259. //
  2260. // for registry objects - to avoid excessive heap operations
  2261. //
  2262. WCHAR Buffer1[261];
  2263. PWSTR ObjectName = NULL;
  2264. Buffer1[0] = L'\0';
  2265. rc = ScepStackNodePush(&pStackHead,
  2266. (PWSTR)pszRootObjectName,
  2267. pSecurityDescriptor);
  2268. if (rc == ERROR_SUCCESS ) {
  2269. while (pStackHead) {
  2270. ScepStackNodePop(&pStackHead,
  2271. &ObjectName,
  2272. &pSecurityDescriptor);
  2273. #ifdef SCE_DBG
  2274. ScepDumpStack(&pStackHead);
  2275. #endif
  2276. BOOL bHasChild=FALSE;
  2277. //
  2278. // set security to the current object first
  2279. //
  2280. #ifdef _WIN64
  2281. rc = ScepSetSecurityObjectOnly(
  2282. ObjectName,
  2283. SeInfo,
  2284. pSecurityDescriptor,
  2285. ObjectType,
  2286. (ObjectType == SE_REGISTRY_KEY || ObjectType == SE_REGISTRY_WOW64_32KEY) ? &bHasChild : NULL
  2287. );
  2288. #else
  2289. rc = ScepSetSecurityObjectOnly(
  2290. ObjectName,
  2291. SeInfo,
  2292. pSecurityDescriptor,
  2293. ObjectType,
  2294. (ObjectType == SE_REGISTRY_KEY) ? &bHasChild : NULL
  2295. );
  2296. #endif
  2297. if ( rc == ERROR_ACCESS_DENIED ||
  2298. rc == ERROR_CANT_ACCESS_FILE ||
  2299. rc == ERROR_FILE_NOT_FOUND ||
  2300. rc == ERROR_PATH_NOT_FOUND ||
  2301. rc == ERROR_SHARING_VIOLATION ||
  2302. rc == ERROR_INVALID_HANDLE ) {
  2303. gWarningCode = rc;
  2304. if (ObjectName != pszRootObjectName) {
  2305. ScepFree(ObjectName);
  2306. ObjectName = NULL;
  2307. if (pSecurityDescriptor) {
  2308. RtlDeleteSecurityObject( &pSecurityDescriptor );
  2309. pSecurityDescriptor = NULL;
  2310. }
  2311. }
  2312. continue;
  2313. }
  2314. if ( rc != ERROR_SUCCESS )
  2315. break;
  2316. PWSTR Buffer=NULL;
  2317. DWORD BufSize;
  2318. PSECURITY_DESCRIPTOR pObjectSecurity=NULL;
  2319. switch ( ObjectType ) {
  2320. case SE_FILE_OBJECT:
  2321. //
  2322. // find all files under this directory/file
  2323. //
  2324. BufSize = wcslen(ObjectName)+4;
  2325. Buffer = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  2326. if ( Buffer == NULL ) {
  2327. rc = ERROR_NOT_ENOUGH_MEMORY;
  2328. break;
  2329. }
  2330. swprintf(Buffer, L"%s\\*.*", ObjectName);
  2331. intptr_t hFile;
  2332. hFile = _wfindfirst(Buffer, &FileInfo);
  2333. ScepFree(Buffer);
  2334. Buffer = NULL;
  2335. if ( hFile != -1 ) {
  2336. do {
  2337. if ( FileInfo.name[0] == L'.')
  2338. continue;
  2339. //
  2340. // build the full name for this object
  2341. //
  2342. BufSize = wcslen(ObjectName)+wcslen(FileInfo.name)+1;
  2343. Buffer = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  2344. if ( Buffer == NULL ) {
  2345. rc = ERROR_NOT_ENOUGH_MEMORY;
  2346. break;
  2347. }
  2348. swprintf(Buffer, L"%s\\%s", ObjectName, FileInfo.name);
  2349. //
  2350. // compute the new security descriptor because
  2351. // different objects may have different owner and
  2352. // the creator owner ace must be translated correctly
  2353. //
  2354. rc = ScepGetNewSecurity(
  2355. Buffer,
  2356. pSecurityDescriptor, // parent's SD
  2357. NULL, // object SD
  2358. 0, // does not query current object SD
  2359. (BOOLEAN)(FileInfo.attrib & _A_SUBDIR ),
  2360. SeInfo,
  2361. ObjectType,
  2362. Token,
  2363. GenericMapping,
  2364. &pObjectSecurity
  2365. );
  2366. if ( ERROR_SUCCESS == rc ) {
  2367. if ( FileInfo.attrib & _A_SUBDIR ) {
  2368. //
  2369. // enumerate all nodes under this one and "empty" explicit aces by
  2370. // calling NtSetSecurityInfo directly
  2371. //
  2372. /*rc = ScepSetSecurityOverwriteExplicit(
  2373. Buffer,
  2374. SeInfo,
  2375. pObjectSecurity,
  2376. ObjectType,
  2377. Token,
  2378. GenericMapping
  2379. );*/
  2380. rc = ScepStackNodePush(&pStackHead,
  2381. Buffer,
  2382. pObjectSecurity);
  2383. if (rc == ERROR_SUCCESS)
  2384. bPushedOntoStack = TRUE;
  2385. } else {
  2386. //
  2387. // this is a file. Set the file security descriptor to this object
  2388. // using NT api
  2389. //
  2390. rc = ScepSetSecurityObjectOnly(
  2391. Buffer,
  2392. SeInfo,
  2393. pObjectSecurity,
  2394. ObjectType,
  2395. NULL
  2396. );
  2397. if ( rc == ERROR_ACCESS_DENIED ||
  2398. rc == ERROR_CANT_ACCESS_FILE ||
  2399. rc == ERROR_FILE_NOT_FOUND ||
  2400. rc == ERROR_PATH_NOT_FOUND ||
  2401. rc == ERROR_SHARING_VIOLATION ||
  2402. rc == ERROR_INVALID_HANDLE ) {
  2403. gWarningCode = rc;
  2404. rc = NO_ERROR;
  2405. }
  2406. }
  2407. }
  2408. if ( !bPushedOntoStack ) {
  2409. if (pObjectSecurity) {
  2410. RtlDeleteSecurityObject( &pObjectSecurity );
  2411. pObjectSecurity = NULL;
  2412. }
  2413. if (Buffer) {
  2414. ScepFree(Buffer);
  2415. Buffer = NULL;
  2416. }
  2417. }
  2418. bPushedOntoStack = FALSE;
  2419. if ( rc != ERROR_SUCCESS )
  2420. break;
  2421. } while ( _wfindnext(hFile, &FileInfo) == 0 );
  2422. _findclose(hFile);
  2423. }
  2424. break;
  2425. case SE_REGISTRY_KEY:
  2426. #ifdef _WIN64
  2427. case SE_REGISTRY_WOW64_32KEY:
  2428. #endif
  2429. if ( bHasChild ) {
  2430. HKEY hKey;
  2431. //
  2432. // open the key
  2433. //
  2434. rc = ScepOpenRegistryObject(
  2435. ObjectType,
  2436. (LPWSTR)ObjectName,
  2437. KEY_READ,
  2438. &hKey
  2439. );
  2440. if ( rc == ERROR_SUCCESS ) {
  2441. DWORD SubKeyLen;
  2442. DWORD cSubKeys;
  2443. cSubKeys = 0;
  2444. rc = RegQueryInfoKey (
  2445. hKey,
  2446. NULL,
  2447. NULL,
  2448. NULL,
  2449. &cSubKeys,
  2450. &SubKeyLen,
  2451. NULL,
  2452. NULL,
  2453. NULL,
  2454. NULL,
  2455. NULL,
  2456. NULL
  2457. );
  2458. if ( rc != NO_ERROR ) {
  2459. ScepLogOutput3(1, rc, SCEDLL_ERROR_QUERY_INFO, (PWSTR)ObjectName );
  2460. cSubKeys = 0;
  2461. SubKeyLen = 0;
  2462. rc = NO_ERROR;
  2463. }
  2464. if ( cSubKeys && SubKeyLen ) {
  2465. DWORD index;
  2466. DWORD EnumRc;
  2467. index = 0;
  2468. //
  2469. // enumerate all subkeys of the key
  2470. //
  2471. do {
  2472. BufSize = 260;
  2473. EnumRc = RegEnumKeyEx(hKey,
  2474. index,
  2475. Buffer1,
  2476. &BufSize,
  2477. NULL,
  2478. NULL,
  2479. NULL,
  2480. NULL);
  2481. if ( EnumRc == ERROR_SUCCESS ) {
  2482. index++;
  2483. BufSize += wcslen(ObjectName)+1;
  2484. Buffer = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  2485. if ( Buffer == NULL ) {
  2486. rc = ERROR_NOT_ENOUGH_MEMORY;
  2487. break;
  2488. }
  2489. swprintf(Buffer, L"%s\\%s", ObjectName, Buffer1);
  2490. //
  2491. // compute the new security descriptor because
  2492. // different objects may have different owner and
  2493. // the creator owner ace must be translated correctly
  2494. //
  2495. rc = ScepGetNewSecurity(
  2496. Buffer,
  2497. pSecurityDescriptor, // parent's SD
  2498. NULL, // object SD
  2499. 0, // does not query current object SD
  2500. (BOOLEAN)TRUE,
  2501. SeInfo,
  2502. ObjectType,
  2503. Token,
  2504. GenericMapping,
  2505. &pObjectSecurity
  2506. );
  2507. if ( ERROR_SUCCESS == rc ) {
  2508. //
  2509. // enumerate all nodes under this one and "empty" explicit aces by
  2510. // calling NtSetSecurityInfo directly
  2511. //
  2512. /*rc = ScepSetSecurityOverwriteExplicit(
  2513. Buffer,
  2514. SeInfo,
  2515. pObjectSecurity,
  2516. ObjectType,
  2517. Token,
  2518. GenericMapping
  2519. );*/
  2520. rc = ScepStackNodePush(&pStackHead,
  2521. Buffer,
  2522. pObjectSecurity);
  2523. if (rc == ERROR_SUCCESS)
  2524. bPushedOntoStack = TRUE;
  2525. }
  2526. if ( rc != ERROR_SUCCESS )
  2527. ScepLogOutput3(1, rc, SCEDLL_ERROR_SET_SECURITY, Buffer);
  2528. if ( !bPushedOntoStack ) {
  2529. if ( pObjectSecurity ) {
  2530. RtlDeleteSecurityObject( &pObjectSecurity );
  2531. pObjectSecurity = NULL;
  2532. }
  2533. ScepFree(Buffer);
  2534. Buffer = NULL;
  2535. }
  2536. bPushedOntoStack = FALSE;
  2537. if ( rc != ERROR_SUCCESS )
  2538. break;
  2539. } else if ( EnumRc != ERROR_NO_MORE_ITEMS ) {
  2540. break;
  2541. }
  2542. } while ( EnumRc != ERROR_NO_MORE_ITEMS );
  2543. if ( EnumRc != ERROR_SUCCESS && EnumRc != ERROR_NO_MORE_ITEMS ) {
  2544. ScepLogOutput3(1, EnumRc, SCEDLL_SAP_ERROR_ENUMERATE, (PWSTR)ObjectName );
  2545. if ( rc == ERROR_SUCCESS )
  2546. rc = EnumRc;
  2547. }
  2548. }
  2549. RegCloseKey(hKey);
  2550. } else
  2551. ScepLogOutput3(1, rc, SCEDLL_ERROR_OPEN, (PWSTR)ObjectName );
  2552. }
  2553. break;
  2554. }
  2555. if (ObjectName != pszRootObjectName) {
  2556. ScepFree(ObjectName);
  2557. ObjectName = NULL;
  2558. if (pSecurityDescriptor) {
  2559. RtlDeleteSecurityObject( &pSecurityDescriptor );
  2560. pSecurityDescriptor = NULL;
  2561. }
  2562. }
  2563. }
  2564. if ( rc != ERROR_SUCCESS ) {
  2565. ScepFreeStack(&pStackHead);
  2566. }
  2567. }
  2568. return(rc);
  2569. }
  2570. VOID
  2571. ScepFreeStack(
  2572. IN PSCEP_STACK_NODE *ppStackHead
  2573. )
  2574. {
  2575. if (ppStackHead == NULL || *ppStackHead == NULL )
  2576. return;
  2577. PSCEP_STACK_NODE pNode;
  2578. while ( pNode = *ppStackHead ) {
  2579. ScepFree( pNode->Buffer );
  2580. RtlDeleteSecurityObject( &(pNode->pObjectSecurity) );
  2581. *ppStackHead = pNode->Next;
  2582. LocalFree(pNode);
  2583. }
  2584. return;
  2585. }
  2586. VOID
  2587. ScepDumpStack(
  2588. IN PSCEP_STACK_NODE *ppStackHead
  2589. )
  2590. {
  2591. if (ppStackHead == NULL || *ppStackHead == NULL )
  2592. return;
  2593. PSCEP_STACK_NODE pNode = *ppStackHead;
  2594. wprintf(L"\n >>>>>>>>> Stack contents");
  2595. while ( pNode ) {
  2596. if ( pNode->Buffer)
  2597. wprintf(L"\n %s", pNode->Buffer );
  2598. pNode = pNode->Next;
  2599. }
  2600. return;
  2601. }
  2602. DWORD
  2603. ScepStackNodePush(
  2604. IN PSCEP_STACK_NODE *ppStackHead,
  2605. IN PWSTR pszObjectName,
  2606. IN PSECURITY_DESCRIPTOR pSecurityDescriptor
  2607. )
  2608. {
  2609. if (ppStackHead == NULL) {
  2610. return ERROR_INVALID_PARAMETER;
  2611. }
  2612. PSCEP_STACK_NODE pNode = (PSCEP_STACK_NODE) LocalAlloc(LMEM_ZEROINIT, sizeof(SCEP_STACK_NODE));
  2613. if ( pNode == NULL )
  2614. return ERROR_NOT_ENOUGH_MEMORY;
  2615. pNode->Buffer = pszObjectName;
  2616. pNode->pObjectSecurity = pSecurityDescriptor;
  2617. pNode->Next = *ppStackHead;
  2618. *ppStackHead = pNode;
  2619. #ifdef SCE_DBG
  2620. gDbgNumPushed ++;
  2621. #endif
  2622. return ERROR_SUCCESS;
  2623. }
  2624. VOID
  2625. ScepStackNodePop(
  2626. IN OUT PSCEP_STACK_NODE *ppStackHead,
  2627. IN OUT PWSTR *ppszObjectName,
  2628. IN OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor
  2629. )
  2630. {
  2631. if (ppStackHead == NULL ||
  2632. *ppStackHead == NULL ||
  2633. ppszObjectName == NULL ||
  2634. ppSecurityDescriptor == NULL )
  2635. return;
  2636. PSCEP_STACK_NODE pNode = *ppStackHead;
  2637. *ppszObjectName = pNode->Buffer;
  2638. *ppSecurityDescriptor = pNode->pObjectSecurity;
  2639. *ppStackHead = pNode->Next;
  2640. LocalFree(pNode);
  2641. #ifdef SCE_DBG
  2642. gDbgNumPopped ++;
  2643. #endif
  2644. return;
  2645. }
  2646. DWORD
  2647. ScepSetSecurityObjectOnly(
  2648. IN PCWSTR ObjectName,
  2649. IN SECURITY_INFORMATION SeInfo,
  2650. IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
  2651. IN SE_OBJECT_TYPE ObjectType,
  2652. OUT PBOOL pbHasChild
  2653. )
  2654. /* ++
  2655. Routine Description:
  2656. This routine set security information to the object only. Security
  2657. for children of this object is not set.
  2658. Arguments:
  2659. ObjecName - name of the object to set security to
  2660. SeInfo - Security information to set
  2661. pSecurityDescriptor - the security descriptor
  2662. ObjectType - type of the object (FILE, REGISTRY, ...)
  2663. Return value:
  2664. Win32 error code
  2665. -- */
  2666. {
  2667. DWORD rc=ERROR_SUCCESS;
  2668. HANDLE Handle=NULL;
  2669. NTSTATUS NtStatus;
  2670. DWORD cSubKeys;
  2671. SECURITY_INFORMATION SeInfoToSet=0;
  2672. SECURITY_DESCRIPTOR SD;
  2673. #ifdef SCE_DBG
  2674. UCHAR psdbuffer[1024];
  2675. PISECURITY_DESCRIPTOR psecuritydescriptor = (PISECURITY_DESCRIPTOR) psdbuffer;
  2676. ULONG bytesneeded = 0;
  2677. ULONG newbytesneeded;
  2678. printf("Before calling NtSetSecurityObject:\n");
  2679. ScepPrintSecurityDescriptor( pSecurityDescriptor, TRUE );
  2680. #endif
  2681. //
  2682. // make a absolute format security descriptor which only contains AdminsSid
  2683. // as the owner.
  2684. //
  2685. switch ( ObjectType ) {
  2686. case SE_FILE_OBJECT:
  2687. //
  2688. // open file object. If it can't be opend due to access denied,
  2689. // take ownership then open again.
  2690. //
  2691. rc = ScepOpenFileObject(
  2692. (LPWSTR)ObjectName,
  2693. ScepGetDesiredAccess(MODIFY_ACCESS_RIGHTS, SeInfo),
  2694. &Handle
  2695. );
  2696. if ( (rc == ERROR_ACCESS_DENIED || rc == ERROR_CANT_ACCESS_FILE) && NULL != AdminsSid ) {
  2697. //
  2698. // open with access to set owner
  2699. //
  2700. ScepLogOutput3(3,0, SCEDLL_SCP_TAKE_OWNER, (LPWSTR)ObjectName);
  2701. rc = ScepOpenFileObject(
  2702. (LPWSTR)ObjectName,
  2703. ScepGetDesiredAccess(WRITE_ACCESS_RIGHTS, OWNER_SECURITY_INFORMATION),
  2704. &Handle
  2705. );
  2706. if ( rc == ERROR_SUCCESS ) {
  2707. //
  2708. // make a absolute format of security descriptor
  2709. // to set owner with
  2710. // if error occurs, continue
  2711. //
  2712. NtStatus = RtlCreateSecurityDescriptor( &SD,
  2713. SECURITY_DESCRIPTOR_REVISION );
  2714. if ( NT_SUCCESS(NtStatus) ) {
  2715. NtStatus = RtlSetOwnerSecurityDescriptor (
  2716. &SD,
  2717. AdminsSid,
  2718. FALSE
  2719. );
  2720. if ( NT_SUCCESS(NtStatus) ) {
  2721. NtStatus = NtSetSecurityObject(
  2722. Handle,
  2723. OWNER_SECURITY_INFORMATION,
  2724. &SD
  2725. );
  2726. }
  2727. }
  2728. rc = RtlNtStatusToDosError(NtStatus);
  2729. CloseHandle(Handle);
  2730. if ( rc == ERROR_SUCCESS ) {
  2731. //
  2732. // old owner of the object is already stored in the security descriptor
  2733. // passed in, which is created from ScepGetNewSecurity...
  2734. //
  2735. SeInfoToSet = OWNER_SECURITY_INFORMATION;
  2736. //
  2737. // re-open the file
  2738. //
  2739. rc = ScepOpenFileObject(
  2740. (LPWSTR)ObjectName,
  2741. ScepGetDesiredAccess(MODIFY_ACCESS_RIGHTS, SeInfoToSet | SeInfo), //SeInfo),
  2742. &Handle
  2743. );
  2744. }
  2745. }
  2746. if ( ERROR_SUCCESS != rc ) {
  2747. ScepLogOutput3(2, rc, SCEDLL_ERROR_TAKE_OWNER, (PWSTR)ObjectName );
  2748. }
  2749. }
  2750. if (rc == ERROR_SUCCESS ) {
  2751. //
  2752. // set security to this object
  2753. //
  2754. SeInfoToSet |= SeInfo;
  2755. ScepAddAutoInheritRequest(pSecurityDescriptor, &SeInfoToSet);
  2756. NtStatus = NtSetSecurityObject(
  2757. Handle,
  2758. SeInfoToSet,
  2759. pSecurityDescriptor
  2760. );
  2761. rc = RtlNtStatusToDosError(NtStatus);
  2762. #ifdef SCE_DBG
  2763. if ( rc == NO_ERROR ) {
  2764. printf("After calling NtSetSecurityObject:\n");
  2765. NtStatus = NtQuerySecurityObject( Handle,
  2766. SeInfo,
  2767. psecuritydescriptor,
  2768. 1024,
  2769. &bytesneeded);
  2770. if (STATUS_BUFFER_TOO_SMALL == NtStatus)
  2771. {
  2772. if (NULL != (psecuritydescriptor = (PISECURITY_DESCRIPTOR)
  2773. ScepAlloc(LMEM_ZEROINIT, bytesneeded) ))
  2774. NtStatus = NtQuerySecurityObject(Handle,
  2775. SeInfo,
  2776. psecuritydescriptor,
  2777. bytesneeded,
  2778. &newbytesneeded);
  2779. }
  2780. if (NT_SUCCESS(NtStatus)) {
  2781. ScepPrintSecurityDescriptor( (PSECURITY_DESCRIPTOR)psecuritydescriptor, TRUE );
  2782. } else
  2783. printf("error occurs: %x\n", NtStatus);
  2784. if (bytesneeded > 1024)
  2785. ScepFree(psecuritydescriptor);
  2786. }
  2787. #endif
  2788. CloseHandle(Handle);
  2789. }
  2790. if ( rc == ERROR_SUCCESS && pbHasChild != NULL ) {
  2791. ScepDoesObjectHasChildren(ObjectType, (PWSTR)ObjectName, pbHasChild);
  2792. }
  2793. break;
  2794. case SE_REGISTRY_KEY:
  2795. #ifdef _WIN64
  2796. case SE_REGISTRY_WOW64_32KEY:
  2797. #endif
  2798. //
  2799. // open registry object. If it can't be opened due to access denied,
  2800. // take ownership then open again.
  2801. //
  2802. rc = ScepOpenRegistryObject(
  2803. ObjectType,
  2804. (LPWSTR)ObjectName,
  2805. ScepGetDesiredAccess(WRITE_ACCESS_RIGHTS, SeInfo),
  2806. (PHKEY)&Handle
  2807. );
  2808. if ( (rc == ERROR_ACCESS_DENIED || rc == ERROR_CANT_ACCESS_FILE) && NULL != AdminsSid ) {
  2809. ScepLogOutput3(3,0, SCEDLL_SCP_TAKE_OWNER, (LPWSTR)ObjectName);
  2810. //
  2811. // open registry object with access to set owner
  2812. //
  2813. rc = ScepOpenRegistryObject(
  2814. ObjectType,
  2815. (LPWSTR)ObjectName,
  2816. ScepGetDesiredAccess(WRITE_ACCESS_RIGHTS, OWNER_SECURITY_INFORMATION),
  2817. (PHKEY)&Handle
  2818. );
  2819. if ( rc == ERROR_SUCCESS ) {
  2820. //
  2821. // make a absolute format of security descriptor
  2822. // to set owner with
  2823. // if error occurs, continue
  2824. //
  2825. NtStatus = RtlCreateSecurityDescriptor( &SD,
  2826. SECURITY_DESCRIPTOR_REVISION );
  2827. if ( NT_SUCCESS(NtStatus) ) {
  2828. NtStatus = RtlSetOwnerSecurityDescriptor (
  2829. &SD,
  2830. AdminsSid,
  2831. FALSE
  2832. );
  2833. }
  2834. if ( NT_SUCCESS(NtStatus) ) {
  2835. rc = RegSetKeySecurity((HKEY)Handle,
  2836. OWNER_SECURITY_INFORMATION,
  2837. &SD);
  2838. } else {
  2839. rc = RtlNtStatusToDosError(NtStatus);
  2840. }
  2841. RegCloseKey((HKEY)Handle);
  2842. if ( rc == ERROR_SUCCESS ) {
  2843. //
  2844. // old owner is already stored in the pSecurityDescriptor passed in
  2845. // which is created in ScepGetNewSecurity...
  2846. //
  2847. SeInfoToSet = OWNER_SECURITY_INFORMATION;
  2848. //
  2849. // re-open the registry key
  2850. //
  2851. rc = ScepOpenRegistryObject(
  2852. ObjectType,
  2853. (LPWSTR)ObjectName,
  2854. ScepGetDesiredAccess(WRITE_ACCESS_RIGHTS, SeInfoToSet | SeInfo),
  2855. (PHKEY)&Handle
  2856. );
  2857. }
  2858. }
  2859. if ( ERROR_SUCCESS != rc ) {
  2860. ScepLogOutput3(2, rc, SCEDLL_ERROR_TAKE_OWNER, (PWSTR)ObjectName );
  2861. }
  2862. }
  2863. if (rc == ERROR_SUCCESS ) {
  2864. //
  2865. // set security to the registry key
  2866. //
  2867. SeInfoToSet |= SeInfo;
  2868. ScepAddAutoInheritRequest(pSecurityDescriptor, &SeInfoToSet);
  2869. rc = RegSetKeySecurity((HKEY)Handle,
  2870. SeInfoToSet,
  2871. pSecurityDescriptor);
  2872. RegCloseKey((HKEY)Handle);
  2873. //
  2874. // query key info for subkeys first
  2875. //
  2876. if ( ERROR_SUCCESS == rc && pbHasChild != NULL ) {
  2877. rc = ScepOpenRegistryObject(
  2878. ObjectType,
  2879. (LPWSTR)ObjectName,
  2880. KEY_READ,
  2881. (PHKEY)&Handle
  2882. );
  2883. if ( ERROR_SUCCESS == rc ) {
  2884. cSubKeys = 0;
  2885. rc = RegQueryInfoKey (
  2886. (HKEY)Handle,
  2887. NULL,
  2888. NULL,
  2889. NULL,
  2890. &cSubKeys,
  2891. NULL,
  2892. NULL,
  2893. NULL,
  2894. NULL,
  2895. NULL,
  2896. NULL,
  2897. NULL
  2898. );
  2899. RegCloseKey((HKEY)Handle);
  2900. }
  2901. if ( rc != NO_ERROR ) {
  2902. ScepLogOutput3(1, rc, SCEDLL_ERROR_QUERY_INFO, (PWSTR)ObjectName );
  2903. cSubKeys = 0;
  2904. rc = NO_ERROR;
  2905. }
  2906. if (cSubKeys == 0 )
  2907. *pbHasChild = FALSE;
  2908. else
  2909. // ignore the error, just set has child.
  2910. //
  2911. *pbHasChild = TRUE;
  2912. }
  2913. } else
  2914. ScepLogOutput3(1, rc, SCEDLL_ERROR_OPEN, (PWSTR)ObjectName);
  2915. break;
  2916. }
  2917. if ( rc != NO_ERROR )
  2918. ScepLogOutput3(1, rc, SCEDLL_ERROR_SET_SECURITY, (PWSTR)ObjectName);
  2919. if ( rc == ERROR_INVALID_OWNER ||
  2920. rc == ERROR_INVALID_PRIMARY_GROUP ||
  2921. rc == ERROR_INVALID_SECURITY_DESCR )
  2922. rc = NO_ERROR;
  2923. return(rc);
  2924. }