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.

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