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.

5972 lines
170 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. setupcln.cpp
  5. Abstract:
  6. SCE setup Client APIs
  7. Author:
  8. Jin Huang (jinhuang) 23-Jun-1997 created
  9. Revision History:
  10. jinhuang 23-Jan-1998 split to client-server model
  11. --*/
  12. #include "headers.h"
  13. #include "scerpc.h"
  14. #include "scesetup.h"
  15. #include "sceutil.h"
  16. #include "clntutil.h"
  17. #include "scedllrc.h"
  18. #include "infp.h"
  19. #include <ntrpcp.h>
  20. #include <io.h>
  21. //#include "gpedit.h"
  22. //#include <initguid.h>
  23. #include <lmaccess.h>
  24. #include "commonrc.h"
  25. #include <aclapi.h>
  26. #include <rpcasync.h>
  27. #include <sddl.h>
  28. typedef HRESULT (*PFREGISTERSERVER)(void);
  29. extern BOOL gbClientInDcPromo;
  30. static SCEPR_CONTEXT hSceSetupHandle=NULL;
  31. extern PVOID theCallBack;
  32. extern HANDLE hCallbackWnd;
  33. extern DWORD CallbackType;
  34. extern HINSTANCE MyModuleHandle;
  35. TCHAR szCallbackPrefix[MAX_PATH];
  36. #define STR_GUID_LEN 36
  37. #define SCESETUP_BACKUP_SECURITY 0x40
  38. #define PRODUCT_UNKNOWN 0
  39. #define EFS_NOTIFY_PATH TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify\\EFS")
  40. DWORD dwThisMachine = PRODUCT_UNKNOWN;
  41. WCHAR szUpInfFile[MAX_PATH*2+1] = {'\0'};
  42. BOOL bIsNT5 = TRUE;
  43. DWORD
  44. WhichNTProduct();
  45. BOOL
  46. ScepAddAuthUserToLocalGroup();
  47. DWORD dwCallbackTotal=0;
  48. DWORD
  49. ScepSetupOpenSecurityDatabase(
  50. IN BOOL bSystemOrAdmin
  51. );
  52. DWORD
  53. ScepSetupCloseSecurityDatabase();
  54. typedef enum _SCESETUP_OPERATION_TYPE {
  55. SCESETUP_UPDATE=1,
  56. SCESETUP_MOVE
  57. } SCESETUP_OPERATION_TYPE;
  58. typedef enum _SCESETUP_OBJECT_TYPE {
  59. SCESETUP_FILE=1,
  60. SCESETUP_KEY,
  61. SCESETUP_SERVICE
  62. } SCESETUP_OBJECT_TYPE;
  63. DWORD
  64. SceSetuppLogComponent(
  65. IN DWORD ErrCode,
  66. IN SCESETUP_OBJECT_TYPE ObjType,
  67. IN SCESETUP_OPERATION_TYPE OptType,
  68. IN PWSTR Name,
  69. IN PWSTR SDText OPTIONAL,
  70. IN PWSTR SecondName OPTIONAL
  71. );
  72. SCESTATUS
  73. ScepSetupWriteOneError(
  74. IN HANDLE hFile,
  75. IN DWORD rc,
  76. IN LPTSTR buf
  77. );
  78. SCESTATUS
  79. ScepSetupWriteError(
  80. IN LPTSTR LogFileName,
  81. IN PSCE_ERROR_LOG_INFO pErrlog
  82. );
  83. SCESTATUS
  84. ScepUpdateBackupSecurity(
  85. IN PCTSTR pszSetupInf,
  86. IN PCTSTR pszWindowsFolder,
  87. IN BOOL bIsDC
  88. );
  89. BOOL
  90. pCreateDefaultGPOsInSysvol(
  91. IN LPTSTR DomainDnsName,
  92. IN LPTSTR szSysvolPath,
  93. IN DWORD Options,
  94. IN LPTSTR LogFileName
  95. );
  96. BOOL
  97. pCreateSysvolContainerForGPO(
  98. IN LPCTSTR strGuid,
  99. IN LPTSTR szPath,
  100. IN DWORD dwStart
  101. );
  102. BOOL
  103. pCreateOneGroupPolicyObject(
  104. IN PWSTR pszGPOSysPath,
  105. IN BOOL bDomainLevel,
  106. IN PWSTR LogFileName
  107. );
  108. DWORD
  109. ScepDcPromoSharedInfo(
  110. IN HANDLE ClientToken,
  111. IN BOOL bDeleteLog,
  112. IN BOOL bSetSecurity,
  113. IN DWORD dwPromoteOptions,
  114. IN PSCE_PROMOTE_CALLBACK_ROUTINE pScePromoteCallBack OPTIONAL
  115. );
  116. NTSTATUS
  117. ScepDcPromoRemoveUserRights();
  118. NTSTATUS
  119. ScepDcPromoRemoveTwoRights(
  120. IN LSA_HANDLE PolicyHandle,
  121. IN SID_IDENTIFIER_AUTHORITY *pIA,
  122. IN UCHAR SubAuthCount,
  123. IN DWORD Rid1,
  124. IN DWORD Rid2
  125. );
  126. DWORD
  127. ScepSystemSecurityInSetup(
  128. IN PWSTR InfName,
  129. IN PCWSTR LogFileName OPTIONAL,
  130. IN AREA_INFORMATION Area,
  131. IN UINT nFlag,
  132. IN PSCE_NOTIFICATION_CALLBACK_ROUTINE pSceNotificationCallBack OPTIONAL,
  133. IN OUT PVOID pValue OPTIONAL
  134. );
  135. DWORD
  136. ScepMoveRegistryValue(
  137. IN HKEY hKey,
  138. IN PWSTR KeyFrom,
  139. IN PWSTR ValueFrom,
  140. IN PWSTR KeyTo OPTIONAL,
  141. IN PWSTR ValueTo OPTIONAL
  142. );
  143. DWORD
  144. ScepBreakSDDLToMultiFields(
  145. IN PWSTR pszObjName,
  146. IN PWSTR pszSDDL,
  147. IN DWORD dwSDDLsize,
  148. IN BYTE ObjStatus,
  149. OUT PWSTR *ppszAdjustedInfLine
  150. );
  151. SCESTATUS
  152. SceInfpBreakTextIntoMultiFields(
  153. IN PWSTR szText,
  154. IN DWORD dLen,
  155. OUT LPDWORD pnFields,
  156. OUT LPDWORD *arrOffset
  157. );
  158. #ifndef _WIN64
  159. BOOL
  160. GetIsWow64 (
  161. VOID
  162. );
  163. #endif // _WIN64
  164. //
  165. // Client APIs in scesetup.h (for setup integration)
  166. //
  167. DWORD
  168. WINAPI
  169. SceSetupUpdateSecurityFile(
  170. IN PWSTR FileFullName,
  171. IN UINT nFlag,
  172. IN PWSTR SDText
  173. )
  174. /*
  175. Routine Description:
  176. This routine applies the security specified in SDText to the file on
  177. local system and update the SDDL security information to the SCE
  178. database.
  179. Arguments:
  180. FileFullName - the full path name of the file to update
  181. nFlag - reserved flag for file option
  182. SDText - the SDDL format security descriptor
  183. Return Value:
  184. WIN32 error code for the status of this operation
  185. */
  186. {
  187. if ( FileFullName == NULL || SDText == NULL ) {
  188. return(ERROR_INVALID_PARAMETER);
  189. }
  190. //
  191. // global database handle
  192. //
  193. SCESTATUS rc = ScepSetupOpenSecurityDatabase(FALSE);
  194. if ( rc == NO_ERROR ) {
  195. RpcTryExcept {
  196. //
  197. // update the file
  198. //
  199. rc = SceRpcSetupUpdateObject(
  200. hSceSetupHandle,
  201. (wchar_t *)FileFullName,
  202. (DWORD)SE_FILE_OBJECT,
  203. nFlag,
  204. (wchar_t *)SDText
  205. );
  206. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  207. //
  208. // get exception code (DWORD)
  209. //
  210. rc = RpcExceptionCode();
  211. } RpcEndExcept;
  212. }
  213. SceSetuppLogComponent(rc,
  214. SCESETUP_FILE,
  215. SCESETUP_UPDATE,
  216. FileFullName,
  217. SDText,
  218. NULL);
  219. return rc;
  220. }
  221. DWORD
  222. WINAPI
  223. SceSetupUpdateSecurityService(
  224. IN PWSTR ServiceName,
  225. IN DWORD StartType,
  226. IN PWSTR SDText
  227. )
  228. /*
  229. Routine Description:
  230. This routine applies the security specified in SDText to the service on
  231. local system and update the SDDL security information to the SCE
  232. database.
  233. Arguments:
  234. ServiceName - the name of the service to update
  235. StartType - startup type of the service
  236. SDText - the SDDL format security descriptor
  237. Return Value:
  238. WIN32 error code for the status of this operation
  239. */
  240. {
  241. if ( ServiceName == NULL || SDText == NULL )
  242. return(ERROR_INVALID_PARAMETER);
  243. //
  244. // global database handle
  245. //
  246. SCESTATUS rc = ScepSetupOpenSecurityDatabase(FALSE);
  247. if ( rc == NO_ERROR ) {
  248. RpcTryExcept {
  249. //
  250. // Update the object information
  251. //
  252. rc = SceRpcSetupUpdateObject(
  253. hSceSetupHandle,
  254. (wchar_t *)ServiceName,
  255. (DWORD)SE_SERVICE,
  256. (UINT)StartType,
  257. (wchar_t *)SDText
  258. );
  259. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  260. //
  261. // get exception code (DWORD)
  262. //
  263. rc = RpcExceptionCode();
  264. } RpcEndExcept;
  265. }
  266. SceSetuppLogComponent(rc,
  267. SCESETUP_SERVICE,
  268. SCESETUP_UPDATE,
  269. ServiceName,
  270. SDText,
  271. NULL);
  272. return rc;
  273. }
  274. // Registry object names returned by NtQueryObject are prefixed by
  275. // the following
  276. #define REG_OBJ_TAG L"\\REGISTRY\\"
  277. #define REG_OBJ_TAG_LEN (sizeof(REG_OBJ_TAG) / sizeof(WCHAR) - 1)
  278. DWORD
  279. WINAPI
  280. SceSetupUpdateSecurityKey(
  281. IN HKEY hKeyRoot,
  282. IN PWSTR KeyPath,
  283. IN UINT nFlag,
  284. IN PWSTR SDText
  285. )
  286. /*
  287. Routine Description:
  288. This routine applies the security specified in SDText to the registry key
  289. on local system and update the SDDL security information to the SCE
  290. database.
  291. on a 64 bit platform; if the client is 64 bit, then we secure the 64 bit
  292. registry. if the client is 32 bit, then we secure the 32 bit registry. Unless,
  293. SCE_SETUP_32KEY is set in the flags, in which case will secure always the 32 bit
  294. registry; or if the SCE_SETUP_64KEY is set in the flags, in which case will secure the
  295. 64 bit registry always. if both are defined the SCE_SETUP_32KEY takes precedence.
  296. Arguments:
  297. hKeyRoot - root handle of the key
  298. KeyPath - the subdir key path relative to the root
  299. nFlag - reserved flag for key option
  300. SDText - the SDDL format security descriptor
  301. Return Value:
  302. WIN32 error code for the status of this operation
  303. */
  304. {
  305. if ( hKeyRoot == NULL || SDText == NULL )
  306. return(ERROR_INVALID_PARAMETER);
  307. DWORD rc = ERROR_SUCCESS;
  308. PWSTR KeyFullName=NULL;
  309. DWORD Len= 16;
  310. DWORD cLen=0;
  311. POBJECT_NAME_INFORMATION pNI=NULL;
  312. NTSTATUS Status;
  313. LPWSTR pwszPath=NULL;
  314. DWORD cchPath=0;
  315. #ifndef _WIN64
  316. static BOOL bGetWow64 = TRUE;
  317. static BOOL bIsWow64 = FALSE;
  318. #endif //_WIN64
  319. //
  320. // translate the root key first
  321. // to determine the length required for the full name
  322. //
  323. if ( hKeyRoot != HKEY_LOCAL_MACHINE &&
  324. hKeyRoot != HKEY_USERS &&
  325. hKeyRoot != HKEY_CLASSES_ROOT ) {
  326. //
  327. // First, determine the size of the buffer we need...
  328. //
  329. Status = NtQueryObject(hKeyRoot,
  330. ObjectNameInformation,
  331. pNI,
  332. 0,
  333. &cLen);
  334. if ( NT_SUCCESS(Status) ||
  335. Status == STATUS_BUFFER_TOO_SMALL ||
  336. Status == STATUS_INFO_LENGTH_MISMATCH ||
  337. Status == STATUS_BUFFER_OVERFLOW ) {
  338. //
  339. // allocate a buffer to get name information
  340. //
  341. pNI = (POBJECT_NAME_INFORMATION)LocalAlloc(LPTR, cLen);
  342. if ( pNI == NULL ) {
  343. rc = ERROR_NOT_ENOUGH_MEMORY;
  344. } else {
  345. Status = NtQueryObject(hKeyRoot,
  346. ObjectNameInformation,
  347. pNI,
  348. cLen,
  349. NULL);
  350. if (!NT_SUCCESS(Status))
  351. {
  352. rc = RtlNtStatusToDosError(Status);
  353. }
  354. else if ( pNI && pNI->Name.Buffer && pNI->Name.Length > 0 )
  355. {
  356. //
  357. // Server doesn't like \REGISTRY as a prefix -- get
  358. // rid of it and the backslash that follows it.
  359. //
  360. DWORD dwSize = sizeof(L"\\REGISTRY\\") - sizeof(WCHAR);
  361. DWORD dwLen = dwSize / sizeof(WCHAR);
  362. if (_wcsnicmp(pNI->Name.Buffer,
  363. L"\\REGISTRY\\",
  364. min(dwLen,
  365. pNI->Name.Length / sizeof(WCHAR))) == 0)
  366. {
  367. RtlMoveMemory(pNI->Name.Buffer,
  368. pNI->Name.Buffer + dwLen,
  369. pNI->Name.Length - dwSize);
  370. pNI->Name.Length -= (USHORT) dwSize;
  371. }
  372. //
  373. // get the required length, plus one space for the backslash,
  374. // and one for null
  375. //
  376. Len = pNI->Name.Length/sizeof(WCHAR) + 2;
  377. }
  378. else
  379. {
  380. rc = ERROR_INVALID_PARAMETER;
  381. }
  382. }
  383. } else {
  384. rc = RtlNtStatusToDosError(Status);
  385. }
  386. }
  387. if ( rc == ERROR_SUCCESS ) {
  388. //
  389. // make a full path name for the key
  390. //
  391. if ( KeyPath != NULL ) {
  392. Len += wcslen(KeyPath);
  393. }
  394. KeyFullName = (PWSTR)LocalAlloc(LMEM_ZEROINIT, Len*sizeof(WCHAR));
  395. if ( KeyFullName == NULL ) {
  396. rc = ERROR_NOT_ENOUGH_MEMORY;
  397. }
  398. }
  399. if ( rc == ERROR_SUCCESS ) {
  400. //
  401. // translate the root key
  402. //
  403. if ( hKeyRoot == HKEY_LOCAL_MACHINE ) {
  404. wcscpy(KeyFullName, L"MACHINE");
  405. } else if ( hKeyRoot == HKEY_USERS ) {
  406. wcscpy(KeyFullName, L"USERS");
  407. } else if ( hKeyRoot == HKEY_CLASSES_ROOT ) {
  408. wcscpy(KeyFullName, L"CLASSES_ROOT");
  409. } else if ( pNI && pNI->Name.Buffer && pNI->Name.Length > 0 ) {
  410. //
  411. // copy the name of the key
  412. //
  413. memcpy(KeyFullName, pNI->Name.Buffer, pNI->Name.Length);
  414. KeyFullName[pNI->Name.Length/sizeof(WCHAR)] = L'\0';
  415. } else {
  416. rc = ERROR_INVALID_PARAMETER;
  417. }
  418. if ( rc == ERROR_SUCCESS && KeyPath != NULL ) {
  419. wcscat(KeyFullName, L"\\");
  420. wcscat(KeyFullName, KeyPath);
  421. }
  422. }
  423. if ( rc == ERROR_SUCCESS ) {
  424. //
  425. // global database handle
  426. //
  427. rc = ScepSetupOpenSecurityDatabase(FALSE);
  428. if ( NO_ERROR == rc ) {
  429. //
  430. // since the server side only understands SCE_SETUP_32KEY,
  431. // and otherwise will set the 64 bit registry then:
  432. //
  433. // we have three possible running enviroments:
  434. // 1. 64 bit scecli -> do nothing
  435. // 2. 32 bit scecli running on 32 bit OS -> do nothing
  436. // 3. 32 bit scecli running on wow64 ->
  437. // a. if SCE_SETUP_64KEY is set -> do nothing
  438. // b. if SCE_SETUP_64KEY is not set -> set SCE_SETUP_32KEY
  439. //
  440. #ifndef _WIN64
  441. if( bGetWow64 ){
  442. bIsWow64 = GetIsWow64();
  443. bGetWow64 = FALSE;
  444. }
  445. if( bIsWow64 ){
  446. if( (nFlag & SCE_SETUP_64KEY) == 0){
  447. nFlag |= SCE_SETUP_32KEY;
  448. }
  449. }
  450. //
  451. // clear out noise going to the server side
  452. //
  453. nFlag &= ~(SCE_SETUP_64KEY);
  454. #endif
  455. RpcTryExcept {
  456. //
  457. // update the object
  458. //
  459. rc = SceRpcSetupUpdateObject(
  460. hSceSetupHandle,
  461. (wchar_t *)KeyFullName,
  462. (DWORD)SE_REGISTRY_KEY,
  463. nFlag,
  464. (wchar_t *)SDText
  465. );
  466. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  467. //
  468. // get exception code (DWORD)
  469. //
  470. rc = RpcExceptionCode();
  471. } RpcEndExcept;
  472. }
  473. }
  474. SceSetuppLogComponent(rc,
  475. SCESETUP_KEY,
  476. SCESETUP_UPDATE,
  477. KeyFullName ? KeyFullName : KeyPath,
  478. SDText,
  479. NULL);
  480. if ( KeyFullName )
  481. LocalFree(KeyFullName);
  482. if ( pNI )
  483. LocalFree(pNI);
  484. return(rc);
  485. }
  486. DWORD
  487. WINAPI
  488. SceSetupMoveSecurityFile(
  489. IN PWSTR FileToSetSecurity,
  490. IN PWSTR FileToSaveInDB OPTIONAL,
  491. IN PWSTR SDText OPTIONAL
  492. )
  493. {
  494. if ( !FileToSetSecurity ) {
  495. return(ERROR_INVALID_PARAMETER);
  496. }
  497. //
  498. // if I am in setup, query the security policy/user rights for any
  499. // policy changes within setup (such as NT4 PDC upgrade where the policy
  500. // filter will fail to save the change)
  501. //
  502. DWORD dwInSetup=0;
  503. DWORD rc = ERROR_SUCCESS;
  504. ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
  505. TEXT("System\\Setup"),
  506. TEXT("SystemSetupInProgress"),
  507. &dwInSetup
  508. );
  509. if ( dwInSetup ) {
  510. rc = ScepSetupOpenSecurityDatabase(FALSE);
  511. if ( NO_ERROR == rc ) {
  512. RpcTryExcept {
  513. //
  514. // move the object
  515. //
  516. rc = SceRpcSetupMoveFile(
  517. hSceSetupHandle,
  518. (wchar_t *)FileToSetSecurity,
  519. (wchar_t *)FileToSaveInDB,
  520. (wchar_t *)SDText
  521. );
  522. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  523. //
  524. // get exception code (DWORD)
  525. //
  526. rc = RpcExceptionCode();
  527. } RpcEndExcept;
  528. }
  529. if ( FileToSaveInDB == NULL &&
  530. rc != NO_ERROR ) {
  531. //
  532. // error occured to delete this file,
  533. // do not report error
  534. //
  535. rc = NO_ERROR;
  536. }
  537. SceSetuppLogComponent(rc,
  538. SCESETUP_FILE,
  539. SCESETUP_MOVE,
  540. FileToSetSecurity,
  541. SDText,
  542. FileToSaveInDB
  543. );
  544. } else {
  545. SceSetuppLogComponent(rc,
  546. SCESETUP_FILE,
  547. SCESETUP_MOVE,
  548. FileToSetSecurity,
  549. NULL,
  550. L"Operation aborted - not in setup"
  551. );
  552. }
  553. return(rc);
  554. }
  555. DWORD
  556. WINAPI
  557. SceSetupUnwindSecurityFile(
  558. IN PWSTR FileFullName,
  559. IN PSECURITY_DESCRIPTOR pSDBackup
  560. )
  561. /*
  562. Routine Description:
  563. This routine reset security settings for the file in SCE database (unwind)
  564. used by two-phase copy file process in setupapi.
  565. Arguments:
  566. FileFullName - The full path name for the file to undo.
  567. pSDBackup - The backup security descriptor
  568. Return Value:
  569. WIN32 error code for the status of this operation
  570. */
  571. {
  572. if ( !FileFullName || !pSDBackup ) {
  573. return(ERROR_INVALID_PARAMETER);
  574. }
  575. DWORD dwInSetup=0;
  576. DWORD rc = ERROR_SUCCESS;
  577. ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
  578. TEXT("System\\Setup"),
  579. TEXT("SystemSetupInProgress"),
  580. &dwInSetup
  581. );
  582. if ( dwInSetup ) {
  583. rc = ScepSetupOpenSecurityDatabase(FALSE);
  584. PWSTR TextSD=NULL;
  585. DWORD TextSize;
  586. if ( NO_ERROR == rc ) {
  587. rc = ConvertSecurityDescriptorToText(
  588. pSDBackup,
  589. 0xF, // all security component
  590. &TextSD,
  591. &TextSize
  592. );
  593. }
  594. if ( NO_ERROR == rc && TextSD ) {
  595. RpcTryExcept {
  596. //
  597. // update security in the database only
  598. //
  599. rc = SceRpcSetupUpdateObject(
  600. hSceSetupHandle,
  601. (wchar_t *)FileFullName,
  602. (DWORD)SE_FILE_OBJECT,
  603. SCESETUP_UPDATE_DB_ONLY,
  604. (wchar_t *)TextSD
  605. );
  606. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  607. //
  608. // get exception code (DWORD)
  609. //
  610. rc = RpcExceptionCode();
  611. } RpcEndExcept;
  612. }
  613. if ( TextSD ) {
  614. LocalFree(TextSD);
  615. }
  616. }
  617. return(rc);
  618. }
  619. DWORD
  620. WINAPI
  621. SceSetupGenerateTemplate(
  622. IN LPTSTR SystemName OPTIONAL,
  623. IN LPTSTR JetDbName OPTIONAL,
  624. IN BOOL bFromMergedTable,
  625. IN LPTSTR InfTemplateName,
  626. IN LPTSTR LogFileName OPTIONAL,
  627. IN AREA_INFORMATION Area
  628. )
  629. /*
  630. Routine Description:
  631. This routine generate a INF format template from the SCE database specified
  632. by JetDbName, or the default SCE database if JetDbName is NULL.
  633. Arguments:
  634. JetDbName - the SCE database name (optional) to get information from.
  635. If NULL, the default security database is used.
  636. InfTemplateName - the inf template name to generate
  637. LogFileName - the log file name (optional)
  638. Area - the security area to generate
  639. Return Value:
  640. WIN32 error code for the status of this operation
  641. */
  642. {
  643. DWORD rc;
  644. handle_t binding_h;
  645. NTSTATUS NtStatus;
  646. PSCE_ERROR_LOG_INFO pErrlog=NULL;
  647. //
  648. // verify the InfTemplateName for invalid path error
  649. // or access denied error
  650. //
  651. rc = ScepVerifyTemplateName(InfTemplateName, &pErrlog);
  652. if ( NO_ERROR == rc ) {
  653. //
  654. // RPC bind to the server
  655. //
  656. NtStatus = ScepBindSecureRpc(
  657. SystemName,
  658. L"scerpc",
  659. 0,
  660. &binding_h
  661. );
  662. if ( NT_SUCCESS(NtStatus) ) {
  663. SCEPR_CONTEXT Context;
  664. RpcTryExcept {
  665. //
  666. // pass to the server site to generate template
  667. //
  668. rc = SceRpcGenerateTemplate(
  669. binding_h,
  670. (wchar_t *)JetDbName,
  671. (wchar_t *)LogFileName,
  672. (PSCEPR_CONTEXT)&Context
  673. );
  674. if ( SCESTATUS_SUCCESS == rc) {
  675. //
  676. // a context handle is opened to generate this template
  677. //
  678. rc = SceCopyBaseProfile(
  679. (PVOID)Context,
  680. bFromMergedTable ? SCE_ENGINE_SCP : SCE_ENGINE_SMP,
  681. (wchar_t *)InfTemplateName,
  682. Area,
  683. &pErrlog
  684. );
  685. ScepSetupWriteError(LogFileName, pErrlog);
  686. ScepFreeErrorLog(pErrlog);
  687. //
  688. // close the context
  689. //
  690. SceRpcCloseDatabase(&Context);
  691. }
  692. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  693. //
  694. // get exception code (DWORD)
  695. //
  696. rc = RpcExceptionCode();
  697. } RpcEndExcept;
  698. } else {
  699. rc = RtlNtStatusToDosError( NtStatus );
  700. }
  701. if ( binding_h ) {
  702. //
  703. // Free the binding handle
  704. //
  705. RpcpUnbindRpc( binding_h );
  706. }
  707. } else {
  708. ScepSetupWriteError(LogFileName, pErrlog);
  709. ScepFreeErrorLog(pErrlog);
  710. }
  711. return(rc);
  712. }
  713. DWORD
  714. ScepMoveRegistryValue(
  715. IN HKEY hKey,
  716. IN PWSTR KeyFrom,
  717. IN PWSTR ValueFrom,
  718. IN PWSTR KeyTo OPTIONAL,
  719. IN PWSTR ValueTo OPTIONAL
  720. )
  721. /*
  722. Some registry values are moved to new locations on NT5. This routine is to migrate
  723. the registry values from their old location on NT4 (KeyFrom, ValueFrom) to their
  724. new location on NT5 (KeyTo, ValueTo).
  725. If destination key or value is not specified, the registry value is moved in the same
  726. key or with different value name. Both KeyTo and ValueTo can't be NULL at the same
  727. time.
  728. */
  729. {
  730. if ( hKey == NULL || KeyFrom == NULL || ValueFrom == NULL ||
  731. (KeyTo == NULL && ValueTo == NULL) ) {
  732. return(ERROR_INVALID_PARAMETER);
  733. }
  734. DWORD rc=ERROR_SUCCESS;
  735. HKEY hKey1=NULL;
  736. HKEY hKey2=NULL;
  737. DWORD RegType=0;
  738. DWORD dSize=0;
  739. //
  740. // open the destination to see if the value already exist
  741. //
  742. if ( KeyTo ) {
  743. rc = RegOpenKeyEx(hKey,
  744. KeyTo,
  745. 0,
  746. KEY_READ | KEY_WRITE,
  747. &hKey2);
  748. if ( ERROR_SUCCESS == rc ) {
  749. //
  750. // open the origin
  751. //
  752. rc = RegOpenKeyEx(hKey,
  753. KeyFrom,
  754. 0,
  755. KEY_READ,
  756. &hKey1);
  757. }
  758. } else {
  759. //
  760. // if a reg value is moved to the same key as origin,
  761. // open the key with appropriate access
  762. //
  763. rc = RegOpenKeyEx(hKey,
  764. KeyFrom,
  765. 0,
  766. KEY_READ | KEY_WRITE,
  767. &hKey2);
  768. hKey1 = hKey2;
  769. }
  770. if ( ERROR_SUCCESS == rc ) {
  771. // query destination
  772. rc = RegQueryValueEx(hKey2,
  773. ValueTo ? ValueTo : ValueFrom,
  774. 0,
  775. &RegType,
  776. NULL,
  777. &dSize
  778. );
  779. if ( ERROR_FILE_NOT_FOUND == rc ) {
  780. //
  781. // only move value if the destination doesn't have the value
  782. //
  783. rc = RegQueryValueEx(hKey1,
  784. ValueFrom,
  785. 0,
  786. &RegType,
  787. NULL,
  788. &dSize
  789. );
  790. if ( ERROR_SUCCESS == rc ) {
  791. PWSTR pValue = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (dSize+1)*sizeof(TCHAR));
  792. if ( pValue != NULL ) {
  793. rc = RegQueryValueEx(hKey1,
  794. ValueFrom,
  795. 0,
  796. &RegType,
  797. (BYTE *)pValue,
  798. &dSize
  799. );
  800. if ( ERROR_SUCCESS == rc ) {
  801. //
  802. // set the value to its new location
  803. //
  804. rc = RegSetValueEx( hKey2,
  805. ValueTo ? ValueTo : ValueFrom,
  806. 0,
  807. RegType,
  808. (BYTE *)pValue,
  809. dSize
  810. );
  811. }
  812. ScepFree(pValue);
  813. }
  814. }
  815. }
  816. }
  817. if ( hKey1 && hKey1 != hKey2 ) {
  818. RegCloseKey(hKey1);
  819. }
  820. if ( hKey2 ) {
  821. RegCloseKey(hKey2);
  822. }
  823. return(rc);
  824. }
  825. DWORD
  826. WINAPI
  827. SceSetupSystemByInfName(
  828. IN PWSTR InfName,
  829. IN PCWSTR LogFileName OPTIONAL,
  830. IN AREA_INFORMATION Area,
  831. IN UINT nFlag,
  832. IN PSCE_NOTIFICATION_CALLBACK_ROUTINE pSceNotificationCallBack OPTIONAL,
  833. IN OUT PVOID pValue OPTIONAL
  834. )
  835. /*
  836. Routine Description:
  837. nFlag Operation
  838. SCESETUP_CONFIGURE_SECURITY overwrite security with the template info
  839. SCESETUP_UPDATE_SECURITY apply template on top of existing security
  840. (do not overwrite the security database)
  841. SCESETUP_QUERY_TICKS query total number of ticks for the operation
  842. Note: when nFlag is SCESETUP_QUERY_TICKS, pValue is PDWORD to output total number of ticks
  843. but when nFlag is the other two values, pValue is a input window handle used
  844. for setup's gauge window (required by the call back routine)
  845. */
  846. {
  847. DWORD rc;
  848. LONG Count=0;
  849. //
  850. // Initialize the SCP engine
  851. //
  852. if ( InfName == NULL ) {
  853. return(ERROR_INVALID_PARAMETER);
  854. }
  855. //
  856. // always configure security policy, user rights, but NO ds objects
  857. // (because this is in setup clean install, no DC available)
  858. //
  859. AREA_INFORMATION Area2;
  860. if ( (nFlag & SCESETUP_UPGRADE_SYSTEM) ||
  861. (nFlag & SCESETUP_UPDATE_FILE_KEY) ) {
  862. Area2 = 0;
  863. if ( nFlag & SCESETUP_UPGRADE_SYSTEM ) {
  864. Area2 = AREA_SECURITY_POLICY |
  865. AREA_PRIVILEGES;
  866. }
  867. if ( nFlag & SCESETUP_UPDATE_FILE_KEY ) {
  868. Area2 |= (Area & ~AREA_DS_OBJECTS);
  869. }
  870. } else {
  871. //
  872. // LSA/SAM are initialized by now (starting 1823)
  873. // configure security policies
  874. //
  875. Area2 = AREA_SECURITY_POLICY |
  876. AREA_PRIVILEGES |
  877. AREA_GROUP_MEMBERSHIP |
  878. (Area & ~AREA_DS_OBJECTS);
  879. // Area2 = (Area & ~AREA_DS_OBJECTS);
  880. }
  881. if ( nFlag & SCESETUP_QUERY_TICKS ) {
  882. //
  883. // only queries ticks from the inf file.
  884. // for the case of updating security, there might be existing objects in
  885. // the SCE database.
  886. //
  887. if ( pValue == NULL ) {
  888. return(ERROR_INVALID_PARAMETER);
  889. }
  890. Count = 0;
  891. HINF InfHandle;
  892. if ( !(nFlag & SCESETUP_UPGRADE_SYSTEM) ||
  893. (nFlag & SCESETUP_UPDATE_FILE_KEY) ) {
  894. InfHandle = SetupOpenInfFile(
  895. InfName,
  896. NULL,
  897. INF_STYLE_WIN4,
  898. NULL
  899. );
  900. if ( InfHandle != INVALID_HANDLE_VALUE ) {
  901. if ( Area2 & AREA_REGISTRY_SECURITY ) {
  902. Count += SetupGetLineCount(InfHandle, szRegistryKeys);
  903. }
  904. if ( Area2 & AREA_FILE_SECURITY ) {
  905. Count += SetupGetLineCount(InfHandle, szFileSecurity);
  906. }
  907. SetupCloseInfFile(InfHandle);
  908. } else {
  909. dwCallbackTotal = 0;
  910. return(GetLastError() );
  911. }
  912. }
  913. else {
  914. //Upgrade
  915. memset(szUpInfFile, 0, sizeof(WCHAR) * (MAX_PATH + 1));
  916. GetSystemWindowsDirectory(szUpInfFile, MAX_PATH);
  917. DWORD TsInstalled = 0;
  918. bIsNT5 = IsNT5();
  919. dwThisMachine = WhichNTProduct();
  920. switch (dwThisMachine) {
  921. case NtProductWinNt:
  922. wcscat(szUpInfFile, L"\\inf\\dwup.inf\0");
  923. break;
  924. case NtProductServer:
  925. //
  926. // determine if this is a terminal server in app mode
  927. //
  928. if ( bIsNT5 ) {
  929. //
  930. // on NT5, check the TSAppCompat value // TSEnabled value
  931. //
  932. ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
  933. TEXT("System\\CurrentControlSet\\Control\\Terminal Server"),
  934. TEXT("TSAppCompat"),
  935. &TsInstalled
  936. );
  937. if ( TsInstalled != 1 ) {
  938. //
  939. // Terminal server is enabled when the value is set to 0x1
  940. //
  941. TsInstalled = 0;
  942. }
  943. } else {
  944. //
  945. // on NT4, base on the ProductSuite value
  946. //
  947. PWSTR pSuite=NULL;
  948. DWORD RegType=0;
  949. DWORD Rcode;
  950. HKEY hKey=NULL;
  951. DWORD dSize=0;
  952. if(( Rcode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  953. TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"),
  954. 0,
  955. KEY_READ,
  956. &hKey
  957. )) == ERROR_SUCCESS ) {
  958. if(( Rcode = RegQueryValueEx(hKey,
  959. TEXT("ProductSuite"),
  960. 0,
  961. &RegType,
  962. NULL,
  963. &dSize
  964. )) == ERROR_SUCCESS ) {
  965. pSuite = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (dSize+1)*sizeof(TCHAR));
  966. if ( pSuite != NULL ) {
  967. Rcode = RegQueryValueEx(hKey,
  968. TEXT("ProductSuite"),
  969. 0,
  970. &RegType,
  971. (BYTE *)pSuite,
  972. &dSize
  973. );
  974. if ( Rcode == ERROR_SUCCESS ) {
  975. if ( RegType == REG_MULTI_SZ ) {
  976. //
  977. // check if the value contains "Terminal Server"
  978. //
  979. PWSTR pTemp=pSuite;
  980. while ( pTemp[0] != L'\0' ) {
  981. if ( lstrcmpi(TEXT("Terminal Server"),pTemp) == 0 ) {
  982. TsInstalled = 1;
  983. break;
  984. } else {
  985. pTemp += wcslen(pTemp)+1;
  986. }
  987. }
  988. } else if ( RegType == REG_SZ ) {
  989. if (lstrcmpi(TEXT("Terminal Server"), pSuite) == 0) {
  990. TsInstalled = 1;
  991. }
  992. }
  993. }
  994. ScepFree(pSuite);
  995. }
  996. }
  997. RegCloseKey( hKey );
  998. }
  999. }
  1000. if ( TsInstalled ) {
  1001. //
  1002. // if terminal server is installed, use the
  1003. // special terminal server template
  1004. //
  1005. wcscat(szUpInfFile, L"\\inf\\dsupt.inf\0");
  1006. } else {
  1007. wcscat(szUpInfFile, L"\\inf\\dsup.inf\0");
  1008. }
  1009. break;
  1010. case NtProductLanManNt:
  1011. if ( bIsNT5 ) {
  1012. wcscat(szUpInfFile, L"\\inf\\dcup5.inf\0");
  1013. }
  1014. else {
  1015. szUpInfFile[0] = L'\0';
  1016. }
  1017. break;
  1018. default:
  1019. szUpInfFile[0] = L'\0';
  1020. }
  1021. if (szUpInfFile[0] != L'\0') {
  1022. InfHandle = SetupOpenInfFile(
  1023. szUpInfFile,
  1024. NULL,
  1025. INF_STYLE_WIN4,
  1026. NULL
  1027. );
  1028. if ( InfHandle != INVALID_HANDLE_VALUE ) {
  1029. if ( Area2 & AREA_REGISTRY_SECURITY ) {
  1030. Count += SetupGetLineCount(InfHandle, szRegistryKeys);
  1031. }
  1032. if ( Area2 & AREA_FILE_SECURITY ) {
  1033. Count += SetupGetLineCount(InfHandle, szFileSecurity);
  1034. }
  1035. SetupCloseInfFile(InfHandle);
  1036. } else {
  1037. dwCallbackTotal = 0;
  1038. return(GetLastError() );
  1039. }
  1040. }
  1041. //
  1042. // migrate registry values
  1043. // should do this for both NT4 and NT5 upgrades since previous NT5
  1044. // may be upgraded from NT4
  1045. //
  1046. // Having the registry value in the right place will help to fix
  1047. // the tattoo problem in the new design
  1048. //
  1049. ScepMoveRegistryValue(
  1050. HKEY_LOCAL_MACHINE,
  1051. L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
  1052. L"DisableCAD",
  1053. L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
  1054. NULL
  1055. );
  1056. ScepMoveRegistryValue(
  1057. HKEY_LOCAL_MACHINE,
  1058. L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
  1059. L"DontDisplayLastUserName",
  1060. L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
  1061. NULL
  1062. );
  1063. ScepMoveRegistryValue(
  1064. HKEY_LOCAL_MACHINE,
  1065. L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
  1066. L"LegalNoticeCaption",
  1067. L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
  1068. NULL
  1069. );
  1070. ScepMoveRegistryValue(
  1071. HKEY_LOCAL_MACHINE,
  1072. L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
  1073. L"LegalNoticeText",
  1074. L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
  1075. NULL
  1076. );
  1077. ScepMoveRegistryValue(
  1078. HKEY_LOCAL_MACHINE,
  1079. L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
  1080. L"ShutdownWithoutLogon",
  1081. L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",
  1082. NULL
  1083. );
  1084. ScepMoveRegistryValue(
  1085. HKEY_LOCAL_MACHINE,
  1086. L"System\\CurrentControlSet\\Services\\Rdr\\Parameters",
  1087. L"EnableSecuritySignature",
  1088. L"System\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters",
  1089. NULL
  1090. );
  1091. ScepMoveRegistryValue(
  1092. HKEY_LOCAL_MACHINE,
  1093. L"System\\CurrentControlSet\\Services\\Rdr\\Parameters",
  1094. L"RequireSecuritySignature",
  1095. L"System\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters",
  1096. NULL
  1097. );
  1098. ScepMoveRegistryValue(
  1099. HKEY_LOCAL_MACHINE,
  1100. L"System\\CurrentControlSet\\Services\\Rdr\\Parameters",
  1101. L"EnablePlainTextPassword",
  1102. L"System\\CurrentControlSet\\Services\\LanmanWorkstation\\Parameters",
  1103. NULL
  1104. );
  1105. }
  1106. if ( Area2 & AREA_SECURITY_POLICY )
  1107. Count += TICKS_SECURITY_POLICY_DS + TICKS_SPECIFIC_POLICIES;
  1108. if ( Area2 & AREA_GROUP_MEMBERSHIP )
  1109. Count += TICKS_GROUPS;
  1110. if ( Area2 & AREA_PRIVILEGES )
  1111. Count += TICKS_PRIVILEGE;
  1112. if ( Area2 & AREA_SYSTEM_SERVICE )
  1113. Count += TICKS_GENERAL_SERVICES + TICKS_SPECIFIC_SERVICES;
  1114. if ( nFlag & SCESETUP_UPGRADE_SYSTEM ) {
  1115. Count += (4*TICKS_MIGRATION_SECTION+TICKS_MIGRATION_V11);
  1116. }
  1117. *(PDWORD)pValue = Count;
  1118. dwCallbackTotal = Count;
  1119. return(ERROR_SUCCESS);
  1120. }
  1121. //
  1122. // delete the temp policy filter files and registry value
  1123. //
  1124. ScepClearPolicyFilterTempFiles(TRUE);
  1125. //
  1126. // make sure the log file is not too big
  1127. //
  1128. DWORD dwLogSize=0;
  1129. HANDLE hFile = CreateFile(LogFileName,
  1130. GENERIC_READ | GENERIC_WRITE,
  1131. FILE_SHARE_READ,
  1132. NULL,
  1133. OPEN_ALWAYS, // OPEN_EXISTING
  1134. FILE_ATTRIBUTE_NORMAL,
  1135. NULL);
  1136. if ( INVALID_HANDLE_VALUE != hFile ) {
  1137. dwLogSize = GetFileSize(hFile, NULL);
  1138. CloseHandle(hFile);
  1139. }
  1140. if ( dwLogSize >= (0x1 << 23) ) {
  1141. DWORD nRequired = wcslen(LogFileName);
  1142. LPTSTR szTempName = (LPTSTR)LocalAlloc(0, (nRequired+1)*sizeof(TCHAR));
  1143. if ( szTempName ) {
  1144. wcscpy(szTempName, LogFileName);
  1145. szTempName[nRequired-3] = L'o';
  1146. szTempName[nRequired-2] = L'l';
  1147. szTempName[nRequired-1] = L'd';
  1148. CopyFile( LogFileName, szTempName, FALSE );
  1149. LocalFree(szTempName);
  1150. }
  1151. DeleteFile(LogFileName);
  1152. }
  1153. //
  1154. // configure the system now
  1155. //
  1156. rc = ScepSystemSecurityInSetup(
  1157. InfName,
  1158. LogFileName,
  1159. Area,
  1160. (nFlag & 0xFL), // block out other flags such as BIND_NO_AUTH
  1161. pSceNotificationCallBack,
  1162. pValue
  1163. );
  1164. if ( rc == ERROR_DATABASE_FAILURE ) {
  1165. //
  1166. // setup category error - log to eventlog
  1167. //
  1168. (void) InitializeEvents(L"SceCli");
  1169. LogEvent(MyModuleHandle,
  1170. STATUS_SEVERITY_ERROR,
  1171. SCEEVENT_ERROR_JET_DATABASE,
  1172. IDS_ERROR_OPEN_JET_DATABASE,
  1173. L"%windir%\\security\\database\\secedit.sdb"
  1174. );
  1175. (void) ShutdownEvents();
  1176. }
  1177. return rc;
  1178. }
  1179. DWORD
  1180. ScepSystemSecurityInSetup(
  1181. IN PWSTR InfName,
  1182. IN PCWSTR LogFileName OPTIONAL,
  1183. IN AREA_INFORMATION Area,
  1184. IN UINT nFlag,
  1185. IN PSCE_NOTIFICATION_CALLBACK_ROUTINE pSceNotificationCallBack OPTIONAL,
  1186. IN OUT PVOID pValue OPTIONAL
  1187. )
  1188. {
  1189. SCESTATUS rc;
  1190. DWORD ConfigOptions;
  1191. handle_t binding_h;
  1192. NTSTATUS NtStatus;
  1193. //
  1194. // always configure security policy, user rights, but NO ds objects
  1195. // (because this is in setup clean install, no DC available)
  1196. //
  1197. AREA_INFORMATION Area2;
  1198. if ( (nFlag & SCESETUP_UPGRADE_SYSTEM) ||
  1199. (nFlag & SCESETUP_UPDATE_FILE_KEY) ) {
  1200. /*
  1201. //
  1202. // should allow policy filter on W2K DC upgrade (dcup5)
  1203. // policy filter is ignored for non DCs in the filter code
  1204. // so it's not needed to add condition here
  1205. //
  1206. // turn off policy filter if this is upgrade
  1207. // clean install, policy filter has not been registered yet.
  1208. //
  1209. ScepRegSetIntValue(
  1210. HKEY_LOCAL_MACHINE,
  1211. SCE_ROOT_PATH,
  1212. TEXT("PolicyFilterOff"),
  1213. 1
  1214. );
  1215. */
  1216. ConfigOptions = SCE_UPDATE_DB | SCE_SERVICE_NO_REALTIME_ENFORCE;
  1217. Area2 = 0;
  1218. if ( nFlag & SCESETUP_UPGRADE_SYSTEM ) {
  1219. Area2 = AREA_SECURITY_POLICY |
  1220. AREA_PRIVILEGES;
  1221. }
  1222. if ( nFlag & SCESETUP_UPDATE_FILE_KEY ) {
  1223. Area2 |= (Area & ~AREA_DS_OBJECTS);
  1224. }
  1225. } else if ( nFlag & SCESETUP_BACKUP_SECURITY ) {
  1226. ConfigOptions = SCE_UPDATE_DB | SCE_SERVICE_NO_REALTIME_ENFORCE;
  1227. Area2 = Area;
  1228. } else {
  1229. ConfigOptions = SCE_OVERWRITE_DB;
  1230. //
  1231. // LSA/SAM are initialized by now (starting 1823)
  1232. // configure security policies
  1233. //
  1234. Area2 = AREA_SECURITY_POLICY |
  1235. AREA_PRIVILEGES |
  1236. AREA_GROUP_MEMBERSHIP |
  1237. (Area & ~AREA_DS_OBJECTS);
  1238. // Area2 = (Area & ~AREA_DS_OBJECTS);
  1239. }
  1240. //
  1241. // a callback routine is passed in
  1242. //
  1243. ScepSetCallback((PVOID)pSceNotificationCallBack,
  1244. (HANDLE)pValue,
  1245. SCE_SETUP_CALLBACK
  1246. );
  1247. //
  1248. // should we close the database opened by single
  1249. // object update ?
  1250. // ScepSetupCloseSecurityDatabase();
  1251. //
  1252. // RPC bind to the server
  1253. //
  1254. NtStatus = ScepBindRpc(
  1255. NULL,
  1256. L"scerpc",
  1257. L"security=impersonation dynamic false",
  1258. &binding_h
  1259. );
  1260. /*
  1261. if ( nFlag & SCESETUP_BIND_NO_AUTH ) {
  1262. NtStatus = ScepBindRpc(
  1263. NULL,
  1264. L"scerpc",
  1265. L"security=impersonation dynamic false",
  1266. &binding_h
  1267. );
  1268. } else {
  1269. NtStatus = ScepBindSecureRpc(
  1270. NULL,
  1271. L"scerpc",
  1272. L"security=impersonation dynamic false",
  1273. &binding_h
  1274. );
  1275. }*/
  1276. if (NT_SUCCESS(NtStatus)){
  1277. //
  1278. // if there is notification handle, set the notify bit
  1279. //
  1280. if ( pSceNotificationCallBack ) {
  1281. ConfigOptions |= SCE_CALLBACK_DELTA;
  1282. }
  1283. LPVOID pebClient = GetEnvironmentStrings();
  1284. DWORD ebSize = ScepGetEnvStringSize(pebClient);
  1285. RpcTryExcept {
  1286. DWORD dWarn=0;
  1287. if ( nFlag & SCESETUP_RECONFIG_SECURITY ) {
  1288. ConfigOptions = SCE_UPDATE_DB;
  1289. Area2 = AREA_FILE_SECURITY;//AREA_ALL;
  1290. rc = SceRpcConfigureSystem(
  1291. binding_h,
  1292. (wchar_t *)InfName,
  1293. NULL,
  1294. (wchar_t *)LogFileName,
  1295. ConfigOptions | SCE_DEBUG_LOG,
  1296. (AREAPR)Area2,
  1297. ebSize,
  1298. (UCHAR *)pebClient,
  1299. &dWarn
  1300. );
  1301. }
  1302. else if ( (ConfigOptions & SCE_UPDATE_DB) &&
  1303. (nFlag & SCESETUP_UPGRADE_SYSTEM) ) {
  1304. //
  1305. // save a flag to indicate this is an upgrade
  1306. //
  1307. if ( ScepRegSetIntValue(
  1308. HKEY_LOCAL_MACHINE,
  1309. SCE_ROOT_PATH,
  1310. TEXT("SetupUpgraded"),
  1311. 1
  1312. ) != ERROR_SUCCESS) {
  1313. //
  1314. // try again to create the key and then set the value
  1315. // don't worry about error this time around
  1316. //
  1317. HKEY hKey = NULL;
  1318. DWORD dwValue = 1;
  1319. if ( ERROR_SUCCESS == RegCreateKeyEx (HKEY_LOCAL_MACHINE,
  1320. SCE_ROOT_PATH,
  1321. 0,
  1322. NULL,
  1323. REG_OPTION_NON_VOLATILE,
  1324. KEY_WRITE | KEY_SET_VALUE,
  1325. NULL,
  1326. &hKey,
  1327. NULL) ) {
  1328. RegSetValueEx( hKey,
  1329. TEXT("SetupUpgraded"),
  1330. 0,
  1331. REG_DWORD,
  1332. (BYTE *)&dwValue,
  1333. 4
  1334. );
  1335. RegCloseKey(hKey);
  1336. }
  1337. }
  1338. //
  1339. // Migrate databases if necessary
  1340. // if NT4 upgrade, create the database
  1341. // this call will also empty the local policy table if necessary
  1342. // ignore this error
  1343. //
  1344. if ( dwThisMachine == NtProductLanManNt &&
  1345. !bIsNT5 ) {
  1346. //
  1347. // NT4 DC upgrade. Should snapshot account policy into the database
  1348. // because SAM won't be available in dcpormo (later on)
  1349. //
  1350. rc = SceRpcAnalyzeSystem(
  1351. binding_h,
  1352. NULL,
  1353. NULL,
  1354. (wchar_t *)LogFileName,
  1355. AREA_SECURITY_POLICY,
  1356. ConfigOptions | SCE_DEBUG_LOG | SCE_NO_ANALYZE | SCE_RE_ANALYZE,
  1357. ebSize,
  1358. (UCHAR *)pebClient,
  1359. &dWarn
  1360. );
  1361. } else {
  1362. //
  1363. // everything else, just create/migrate the database
  1364. //
  1365. rc = SceRpcAnalyzeSystem(
  1366. binding_h,
  1367. NULL,
  1368. NULL,
  1369. (wchar_t *)LogFileName,
  1370. 0,
  1371. ConfigOptions | SCE_DEBUG_LOG | SCE_NO_ANALYZE,
  1372. ebSize,
  1373. (UCHAR *)pebClient,
  1374. &dWarn
  1375. );
  1376. }
  1377. rc = SCESTATUS_SUCCESS;
  1378. if ( nFlag & SCESETUP_UPDATE_FILE_KEY ) {
  1379. Area2 = (Area & ~(AREA_DS_OBJECTS | AREA_SECURITY_POLICY | AREA_PRIVILEGES) );
  1380. rc = SceRpcConfigureSystem(
  1381. binding_h,
  1382. (wchar_t *)InfName,
  1383. NULL,
  1384. (wchar_t *)LogFileName,
  1385. ConfigOptions | SCE_DEBUG_LOG,
  1386. (AREAPR)Area2,
  1387. ebSize,
  1388. (UCHAR *)pebClient,
  1389. &dWarn
  1390. );
  1391. }
  1392. if ( !(nFlag & SCESETUP_BIND_NO_AUTH) ) {
  1393. if ( szUpInfFile[0] != L'\0' ) {
  1394. if (dwThisMachine == NtProductServer || dwThisMachine == NtProductWinNt) {
  1395. Area2 = AREA_ALL;
  1396. }
  1397. else {
  1398. Area2 = AREA_FILE_SECURITY | AREA_REGISTRY_SECURITY |
  1399. AREA_PRIVILEGES | AREA_SECURITY_POLICY;
  1400. // DS is not running, do not configure account policies.
  1401. // ConfigOptions |= SCE_NO_DOMAIN_POLICY;
  1402. }
  1403. rc = SceRpcConfigureSystem(
  1404. binding_h,
  1405. (wchar_t *)szUpInfFile,
  1406. NULL,
  1407. (wchar_t *)LogFileName,
  1408. ConfigOptions | SCE_DEBUG_LOG,
  1409. (AREAPR)Area2,
  1410. ebSize,
  1411. (UCHAR *)pebClient,
  1412. &dWarn
  1413. );
  1414. }
  1415. // should add Authenticated Users to Users group on DC too
  1416. // if (dwThisMachine == NtProductServer || dwThisMachine == NtProductWinNt) {
  1417. if (!ScepAddAuthUserToLocalGroup()) {
  1418. LogEventAndReport(MyModuleHandle,
  1419. (wchar_t *)LogFileName,
  1420. STATUS_SEVERITY_WARNING,
  1421. SCEEVENT_WARNING_BACKUP_SECURITY,
  1422. IDS_ERR_ADD_AUTH_USER );
  1423. }
  1424. // }
  1425. }
  1426. } else {
  1427. //
  1428. // clean install, the upgraded flag should be 0
  1429. // no need to set it; clear the log
  1430. //
  1431. if ( LogFileName ) {
  1432. DeleteFile(LogFileName);
  1433. }
  1434. rc = SceRpcConfigureSystem(
  1435. binding_h,
  1436. (wchar_t *)InfName,
  1437. NULL,
  1438. (wchar_t *)LogFileName,
  1439. ConfigOptions | SCE_DEBUG_LOG,
  1440. (AREAPR)Area2,
  1441. ebSize,
  1442. (UCHAR *)pebClient,
  1443. &dWarn
  1444. );
  1445. }
  1446. rc = ScepSceStatusToDosError(rc);
  1447. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  1448. //
  1449. // get exception code (DWORD)
  1450. //
  1451. rc = RpcExceptionCode();
  1452. } RpcEndExcept;
  1453. if(pebClient)
  1454. {
  1455. FreeEnvironmentStrings((LPTSTR)pebClient);
  1456. }
  1457. } else {
  1458. rc = RtlNtStatusToDosError(NtStatus);
  1459. }
  1460. if ( binding_h ) {
  1461. //
  1462. // Free the binding handle
  1463. //
  1464. RpcpUnbindRpc( binding_h );
  1465. }
  1466. ScepSetCallback(NULL, NULL, 0);
  1467. dwCallbackTotal = 0;
  1468. /*
  1469. //
  1470. // should allow policy filter on W2K DC upgrade (dcup5)
  1471. // policy filter is ignored for non DCs in the filter code
  1472. // so it's not needed to add condition here
  1473. //
  1474. if ( (nFlag & SCESETUP_UPGRADE_SYSTEM) ||
  1475. (nFlag & SCESETUP_UPDATE_FILE_KEY) ) {
  1476. DWORD rCode = ScepRegDeleteValue(
  1477. HKEY_LOCAL_MACHINE,
  1478. SCE_ROOT_PATH,
  1479. TEXT("PolicyFilterOff")
  1480. );
  1481. if ( rCode != ERROR_SUCCESS &&
  1482. rCode != ERROR_FILE_NOT_FOUND &&
  1483. rCode != ERROR_PATH_NOT_FOUND ) {
  1484. // if can't delete the value, set the value to 0
  1485. ScepRegSetIntValue( HKEY_LOCAL_MACHINE,
  1486. SCE_ROOT_PATH,
  1487. TEXT("PolicyFilterOff"),
  1488. 0
  1489. );
  1490. }
  1491. }
  1492. */
  1493. return(rc);
  1494. }
  1495. DWORD
  1496. WINAPI
  1497. SceDcPromoteSecurity(
  1498. IN DWORD dwPromoteOptions,
  1499. IN PSCE_PROMOTE_CALLBACK_ROUTINE pScePromoteCallBack OPTIONAL
  1500. )
  1501. {
  1502. return SceDcPromoteSecurityEx(NULL, dwPromoteOptions, pScePromoteCallBack);
  1503. }
  1504. DWORD
  1505. WINAPI
  1506. SceDcPromoteSecurityEx(
  1507. IN HANDLE ClientToken,
  1508. IN DWORD dwPromoteOptions,
  1509. IN PSCE_PROMOTE_CALLBACK_ROUTINE pScePromoteCallBack OPTIONAL
  1510. )
  1511. /*
  1512. Routine Description:
  1513. This routine promote security for a domain controller when a server is
  1514. promoted to a DC.
  1515. Arguments:
  1516. dwPromoteOptions - options for the promotion, for example, create a new domain
  1517. or joining an existing domain
  1518. pScePromoteCallBack - the call back pointer
  1519. Return Value:
  1520. WIN32 error code
  1521. */
  1522. {
  1523. BOOL bDeleteLog;
  1524. if ( (dwPromoteOptions & SCE_PROMOTE_FLAG_REPLICA) ||
  1525. (dwPromoteOptions & SCE_PROMOTE_FLAG_DEMOTE) ) {
  1526. bDeleteLog = TRUE;
  1527. } else {
  1528. bDeleteLog = FALSE;
  1529. }
  1530. //
  1531. // delete temporary filter file generated in setup if it hasn't been
  1532. // processed by policy prop
  1533. // because we are setting up a new product.
  1534. // Note, this is a special case for NT4 DC upgrade
  1535. //
  1536. ScepClearPolicyFilterTempFiles(TRUE);
  1537. //
  1538. // configure security for both replica and first domain case.
  1539. //
  1540. DWORD rc32 = ScepDcPromoSharedInfo(ClientToken,
  1541. bDeleteLog, // delete log
  1542. TRUE, // not set security
  1543. dwPromoteOptions,
  1544. pScePromoteCallBack
  1545. );
  1546. TCHAR Buffer[MAX_PATH+1];
  1547. TCHAR szNewName[MAX_PATH+51];
  1548. Buffer[0] = L'\0';
  1549. GetSystemWindowsDirectory(Buffer, MAX_PATH);
  1550. Buffer[MAX_PATH] = L'\0';
  1551. szNewName[0] = L'\0';
  1552. //
  1553. // make sure the log file is re-created
  1554. //
  1555. wcscpy(szNewName, Buffer);
  1556. wcscat(szNewName, L"\\security\\logs\\scedcpro.log\0");
  1557. DWORD rcSave = rc32;
  1558. //
  1559. // generate the updated database (for emergency repair)
  1560. // even if there is an error configuring security
  1561. //
  1562. if ( dwPromoteOptions & SCE_PROMOTE_FLAG_DEMOTE ) {
  1563. rc32 = SceSetupBackupSecurity(NULL);
  1564. }
  1565. else {
  1566. rc32 = SceSetupBackupSecurity(szNewName);
  1567. }
  1568. //
  1569. // re-register the notify dll (seclogon.dll) so that
  1570. // at next logon after reboot, the group policy object
  1571. // can be created.
  1572. //
  1573. // if it's a replica created, EFS policy should come from
  1574. // the domain so no need to create group policy object
  1575. //
  1576. if ( !(dwPromoteOptions & SCE_PROMOTE_FLAG_REPLICA) &&
  1577. !(dwPromoteOptions & SCE_PROMOTE_FLAG_DEMOTE) ) {
  1578. (void) InitializeEvents(L"SceCli");
  1579. HINSTANCE hNotifyDll = LoadLibrary(TEXT("sclgntfy.dll"));
  1580. if ( hNotifyDll) {
  1581. PFREGISTERSERVER pfRegisterServer = (PFREGISTERSERVER)GetProcAddress(
  1582. hNotifyDll,
  1583. "DllRegisterServer");
  1584. if ( pfRegisterServer ) {
  1585. //
  1586. // do not care errors
  1587. //
  1588. (void) (*pfRegisterServer)();
  1589. LogEvent(MyModuleHandle,
  1590. STATUS_SEVERITY_INFORMATIONAL,
  1591. SCEEVENT_INFO_REGISTER,
  1592. 0,
  1593. TEXT("sclgntfy.dll")
  1594. );
  1595. } else {
  1596. LogEvent(MyModuleHandle,
  1597. STATUS_SEVERITY_WARNING,
  1598. SCEEVENT_WARNING_REGISTER,
  1599. IDS_ERROR_GET_PROCADDR,
  1600. GetLastError(),
  1601. TEXT("DllRegisterServer in sclgntfy.dll")
  1602. );
  1603. }
  1604. FreeLibrary(hNotifyDll);
  1605. } else {
  1606. LogEvent(MyModuleHandle,
  1607. STATUS_SEVERITY_WARNING,
  1608. SCEEVENT_WARNING_REGISTER,
  1609. IDS_ERROR_LOADDLL,
  1610. GetLastError(),
  1611. TEXT("sclgntfy.dll")
  1612. );
  1613. }
  1614. (void) ShutdownEvents();
  1615. }
  1616. if ( rcSave )
  1617. return(rcSave);
  1618. else
  1619. return(rc32);
  1620. }
  1621. DWORD
  1622. WINAPI
  1623. SceDcPromoCreateGPOsInSysvol(
  1624. IN LPTSTR DomainDnsName,
  1625. IN LPTSTR SysvolRoot,
  1626. IN DWORD dwPromoteOptions,
  1627. IN PSCE_PROMOTE_CALLBACK_ROUTINE pScePromoteCallBack OPTIONAL
  1628. )
  1629. {
  1630. return SceDcPromoCreateGPOsInSysvolEx(NULL, DomainDnsName, SysvolRoot,
  1631. dwPromoteOptions, pScePromoteCallBack
  1632. );
  1633. }
  1634. DWORD
  1635. WINAPI
  1636. SceDcPromoCreateGPOsInSysvolEx(
  1637. IN HANDLE ClientToken,
  1638. IN LPTSTR DomainDnsName,
  1639. IN LPTSTR SysvolRoot,
  1640. IN DWORD dwPromoteOptions,
  1641. IN PSCE_PROMOTE_CALLBACK_ROUTINE pScePromoteCallBack OPTIONAL
  1642. )
  1643. {
  1644. //
  1645. // create default policy object for domain and domain controllers ou
  1646. // if it's not an replica
  1647. //
  1648. if ( NULL == DomainDnsName || NULL == SysvolRoot ) {
  1649. return ERROR_INVALID_PARAMETER;
  1650. }
  1651. DWORD rc32=ERROR_SUCCESS;
  1652. TCHAR Buffer[MAX_PATH+1];
  1653. TCHAR szGenName[MAX_PATH+51];
  1654. Buffer[0] = L'\0';
  1655. GetSystemWindowsDirectory(Buffer, MAX_PATH);
  1656. Buffer[MAX_PATH] = L'\0';
  1657. if ( !(dwPromoteOptions & SCE_PROMOTE_FLAG_REPLICA) ) {
  1658. rc32 = ScepDcPromoSharedInfo(ClientToken,
  1659. TRUE, // delete log
  1660. FALSE, // not set security
  1661. dwPromoteOptions,
  1662. pScePromoteCallBack
  1663. );
  1664. if ( rc32 == ERROR_SUCCESS ) {
  1665. //
  1666. // now create the GPOs in sysvol
  1667. //
  1668. (void) InitializeEvents(L"SceCli");
  1669. TCHAR szNewName[MAX_PATH+51];
  1670. wcscpy(szNewName, Buffer);
  1671. wcscat(szNewName, L"\\security\\logs\\scedcpro.log\0");
  1672. wcscpy(szGenName, Buffer);
  1673. wcscat(szGenName, L"\\security\\FirstDGPO.inf\0");
  1674. intptr_t hFile;
  1675. struct _wfinddata_t FileInfo;
  1676. hFile = _wfindfirst(szGenName, &FileInfo);
  1677. if ( hFile == -1 ) {
  1678. rc32 = ERROR_OBJECT_NOT_FOUND;
  1679. LogEventAndReport(MyModuleHandle,
  1680. szNewName,
  1681. STATUS_SEVERITY_ERROR,
  1682. SCEEVENT_ERROR_CREATE_GPO,
  1683. IDS_ERROR_GETGPO_FILE_PATH,
  1684. rc32,
  1685. szGenName
  1686. );
  1687. } else {
  1688. _findclose(hFile);
  1689. wcscpy(szGenName, Buffer);
  1690. wcscat(szGenName, L"\\security\\FirstOGPO.inf\0");
  1691. hFile = _wfindfirst(szGenName, &FileInfo);
  1692. if ( hFile == -1 ) {
  1693. rc32 = ERROR_OBJECT_NOT_FOUND;
  1694. LogEventAndReport(MyModuleHandle,
  1695. szNewName,
  1696. STATUS_SEVERITY_ERROR,
  1697. SCEEVENT_ERROR_CREATE_GPO,
  1698. IDS_ERROR_GETGPO_FILE_PATH,
  1699. rc32,
  1700. szGenName
  1701. );
  1702. } else {
  1703. _findclose(hFile);
  1704. if ( FALSE == pCreateDefaultGPOsInSysvol( DomainDnsName,
  1705. SysvolRoot,
  1706. dwPromoteOptions,
  1707. szNewName ) ) {
  1708. rc32 = GetLastError();
  1709. }
  1710. }
  1711. }
  1712. (void) ShutdownEvents();
  1713. }
  1714. }
  1715. //
  1716. // make sure the temp files are deleted
  1717. //
  1718. wcscpy(szGenName, Buffer);
  1719. wcscat(szGenName, L"\\security\\FirstDGPO.inf\0");
  1720. DeleteFile(szGenName);
  1721. wcscpy(szGenName, Buffer);
  1722. wcscat(szGenName, L"\\security\\FirstOGPO.inf\0");
  1723. DeleteFile(szGenName);
  1724. return rc32;
  1725. }
  1726. DWORD
  1727. ScepDcPromoSharedInfo(
  1728. IN HANDLE ClientToken,
  1729. IN BOOL bDeleteLog,
  1730. IN BOOL bSetSecurity,
  1731. IN DWORD dwPromoteOptions,
  1732. IN PSCE_PROMOTE_CALLBACK_ROUTINE pScePromoteCallBack OPTIONAL
  1733. )
  1734. {
  1735. SCESTATUS rc;
  1736. DWORD rc32=NO_ERROR;
  1737. TCHAR Buffer[MAX_PATH+1];
  1738. TCHAR szGenName[MAX_PATH+51];
  1739. TCHAR szNewName[MAX_PATH+51];
  1740. handle_t binding_h;
  1741. NTSTATUS NtStatus;
  1742. ScepRegSetIntValue(
  1743. HKEY_LOCAL_MACHINE,
  1744. SCE_ROOT_PATH,
  1745. TEXT("PolicyFilterOff"),
  1746. 1
  1747. );
  1748. ScepRegSetIntValue(
  1749. HKEY_LOCAL_MACHINE,
  1750. SCE_ROOT_PATH,
  1751. TEXT("PolicyPropOff"),
  1752. 1
  1753. );
  1754. //
  1755. // a callback routine is passed in
  1756. //
  1757. ScepSetCallback((PVOID)pScePromoteCallBack,
  1758. NULL,
  1759. SCE_DCPROMO_CALLBACK
  1760. );
  1761. //
  1762. // should we close the database opened by single
  1763. // object update ?
  1764. // ScepSetupCloseSecurityDatabase();
  1765. //
  1766. // RPC bind to the server
  1767. //
  1768. NtStatus = ScepBindRpc(
  1769. NULL,
  1770. L"scerpc",
  1771. L"security=impersonation dynamic false", // 0
  1772. &binding_h
  1773. );
  1774. /*
  1775. NtStatus = ScepBindSecureRpc(
  1776. NULL,
  1777. L"scerpc",
  1778. 0,
  1779. &binding_h
  1780. );
  1781. */
  1782. if (NT_SUCCESS(NtStatus)){
  1783. //
  1784. // if there is notification handle, set the notify bit
  1785. //
  1786. DWORD ConfigOptions = SCE_UPDATE_DB | SCE_DEBUG_LOG;
  1787. if ( pScePromoteCallBack ) {
  1788. ConfigOptions |= SCE_CALLBACK_DELTA;
  1789. }
  1790. //
  1791. // the following calls shouldn't fail because Buffer is big enough
  1792. //
  1793. Buffer[0] = L'\0';
  1794. GetSystemWindowsDirectory(Buffer, MAX_PATH);
  1795. Buffer[MAX_PATH] = L'\0';
  1796. //
  1797. // if it's not set security (then it's create GPOs)
  1798. // make sure FirstOGPO and FirstDGPO are initialized properly
  1799. //
  1800. if ( bSetSecurity == FALSE ) {
  1801. //
  1802. // this code should be only called for non replica promotion
  1803. //
  1804. wcscpy(szNewName, Buffer);
  1805. if ( dwPromoteOptions & SCE_PROMOTE_FLAG_UPGRADE ) {
  1806. //
  1807. // upgrade from NT4 DC to NT5 DC
  1808. //
  1809. wcscat(szNewName, L"\\inf\\dcup.inf\0");
  1810. } else {
  1811. wcscat(szNewName, L"\\inf\\defltdc.inf\0");
  1812. }
  1813. wcscpy(szGenName, Buffer);
  1814. wcscat(szGenName, L"\\security\\FirstOGPO.inf\0");
  1815. // DeleteFile(szGenName);
  1816. CopyFile(szNewName, szGenName, FALSE);
  1817. //
  1818. // delete the sections do not belong to local policy object
  1819. //
  1820. WritePrivateProfileSection(
  1821. szSystemAccess,
  1822. NULL,
  1823. (LPCTSTR)szGenName);
  1824. WritePrivateProfileSection(
  1825. szGroupMembership,
  1826. NULL,
  1827. (LPCTSTR)szGenName);
  1828. WritePrivateProfileSection(
  1829. szAccountProfiles,
  1830. NULL,
  1831. (LPCTSTR)szGenName);
  1832. WritePrivateProfileSection(
  1833. szRegistryKeys,
  1834. NULL,
  1835. (LPCTSTR)szGenName);
  1836. WritePrivateProfileSection(
  1837. szFileSecurity,
  1838. NULL,
  1839. (LPCTSTR)szGenName);
  1840. WritePrivateProfileSection(
  1841. szDSSecurity,
  1842. NULL,
  1843. (LPCTSTR)szGenName);
  1844. WritePrivateProfileSection(
  1845. L"LanManServer",
  1846. NULL,
  1847. (LPCTSTR)szGenName);
  1848. WritePrivateProfileSection(
  1849. szServiceGeneral,
  1850. NULL,
  1851. (LPCTSTR)szGenName);
  1852. WritePrivateProfileSection(
  1853. szKerberosPolicy,
  1854. NULL,
  1855. (LPCTSTR)szGenName);
  1856. /*
  1857. WritePrivateProfileSection(
  1858. szRegistryValues,
  1859. NULL,
  1860. (LPCTSTR)szGenName);
  1861. */
  1862. WritePrivateProfileSection(
  1863. szAuditSystemLog,
  1864. NULL,
  1865. (LPCTSTR)szGenName);
  1866. WritePrivateProfileSection(
  1867. szAuditSecurityLog,
  1868. NULL,
  1869. (LPCTSTR)szGenName);
  1870. WritePrivateProfileSection(
  1871. szAuditApplicationLog,
  1872. NULL,
  1873. (LPCTSTR)szGenName);
  1874. wcscpy(szGenName, Buffer);
  1875. wcscat(szGenName, L"\\security\\FirstDGPO.inf\0");
  1876. //
  1877. // prepare the temp domain and local policy template
  1878. // write default kerberos policy into the temp domain template
  1879. //
  1880. szNewName[0] = L'\0';
  1881. wcscpy(szNewName, Buffer);
  1882. wcscat(szNewName, L"\\inf\\Dcfirst.inf\0");
  1883. CopyFile(szNewName, szGenName, FALSE);
  1884. }
  1885. //
  1886. // make sure the log file is re-created
  1887. //
  1888. wcscpy(szNewName, Buffer);
  1889. wcscat(szNewName, L"\\security\\logs\\scedcpro.log\0");
  1890. if ( bDeleteLog ) {
  1891. DeleteFile(szNewName);
  1892. }
  1893. //
  1894. // choose the template to use
  1895. //
  1896. szGenName[0] = L'\0';
  1897. wcscpy(szGenName, Buffer);
  1898. if ( dwPromoteOptions & SCE_PROMOTE_FLAG_UPGRADE ) {
  1899. //
  1900. // upgrade from NT4 DC to NT5 DC
  1901. //
  1902. wcscat(szGenName, L"\\inf\\dcup.inf\0");
  1903. } else if ( dwPromoteOptions & SCE_PROMOTE_FLAG_DEMOTE ) {
  1904. //
  1905. // demote from DC to server
  1906. //
  1907. wcscat(szGenName, L"\\inf\\defltsv.inf\0");
  1908. } else{
  1909. wcscat(szGenName, L"\\inf\\defltdc.inf\0");
  1910. }
  1911. LPVOID pebClient = GetEnvironmentStrings();
  1912. DWORD ebSize = ScepGetEnvStringSize(pebClient);
  1913. //
  1914. // impersonate
  1915. //
  1916. BOOL bImpersonated = FALSE;
  1917. if ( ClientToken ) {
  1918. if ( !ImpersonateLoggedOnUser(ClientToken) ) {
  1919. LogEventAndReport(MyModuleHandle,
  1920. (wchar_t *)szNewName,
  1921. 0,
  1922. 0,
  1923. IDS_ERROR_PROMOTE_IMPERSONATE,
  1924. GetLastError()
  1925. );
  1926. } else {
  1927. bImpersonated = TRUE;
  1928. }
  1929. }
  1930. szCallbackPrefix[0] = L'\0';
  1931. LoadString( MyModuleHandle,
  1932. bSetSecurity ? SCECLI_CALLBACK_PREFIX : SCECLI_CREATE_GPO_PREFIX,
  1933. szCallbackPrefix,
  1934. MAX_PATH
  1935. );
  1936. szCallbackPrefix[MAX_PATH-1] = L'\0';
  1937. if ( szCallbackPrefix[0] == L'\0' ) {
  1938. //
  1939. // in case loadString fails
  1940. //
  1941. if ( bSetSecurity ) {
  1942. wcscpy(szCallbackPrefix, L"Securing ");
  1943. } else {
  1944. wcscpy(szCallbackPrefix, L"Creating ");
  1945. }
  1946. }
  1947. //
  1948. // revert
  1949. //
  1950. if ( ClientToken && bImpersonated ) {
  1951. if ( !RevertToSelf() ) {
  1952. LogEventAndReport(MyModuleHandle,
  1953. (wchar_t *)szNewName,
  1954. 0,
  1955. 0,
  1956. IDS_ERROR_PROMOTE_REVERT,
  1957. GetLastError()
  1958. );
  1959. }
  1960. }
  1961. //
  1962. // configure security
  1963. //
  1964. DWORD dWarn;
  1965. AREA_INFORMATION Area;
  1966. rc = SCESTATUS_SUCCESS;
  1967. RpcTryExcept {
  1968. //
  1969. // also make sure the builtin accounts for NT5 DC are
  1970. // created if they are not there (which will be created in reboot after dcpromo)
  1971. //
  1972. LPTSTR pTemplateFile;
  1973. if ( bSetSecurity == FALSE ) {
  1974. Area = AREA_PRIVILEGES;
  1975. if ( dwPromoteOptions & SCE_PROMOTE_FLAG_UPGRADE ) {
  1976. //
  1977. // upgrade from NT4 DC to NT5 DC, need copy the current policy setting
  1978. //
  1979. Area |= AREA_SECURITY_POLICY;
  1980. }
  1981. ConfigOptions |= (SCE_COPY_LOCAL_POLICY |
  1982. SCE_NO_CONFIG |
  1983. SCE_DCPROMO_WAIT |
  1984. SCE_NO_DOMAIN_POLICY );
  1985. pTemplateFile = NULL; // szGenName;
  1986. } else {
  1987. //
  1988. // flag it so that special registry values (such as LmCompatibilityLevel) can be handled
  1989. //
  1990. ScepRegSetIntValue(
  1991. HKEY_LOCAL_MACHINE,
  1992. SCE_ROOT_PATH,
  1993. TEXT("PromoteUpgradeInProgress"),
  1994. (dwPromoteOptions & SCE_PROMOTE_FLAG_UPGRADE) ? 1 : 0
  1995. );
  1996. if ( dwPromoteOptions & SCE_PROMOTE_FLAG_DEMOTE ) {
  1997. //
  1998. // security policy, privileges, and group membership must be configured
  1999. // at reboot (in policy propagation) so these settings must
  2000. // be imported to the tattoo table first (when SCE_DC_DEMOTE is set)
  2001. // Plus SAM will be recreated at reboot
  2002. //
  2003. Area = AREA_SECURITY_POLICY | AREA_PRIVILEGES | AREA_GROUP_MEMBERSHIP;
  2004. ConfigOptions |= SCE_NO_CONFIG | SCE_DCPROMO_WAIT | SCE_DC_DEMOTE;
  2005. }
  2006. else {
  2007. //
  2008. // remove "Power Users" explcitly
  2009. // since privileges are not configured anymore
  2010. //
  2011. ScepDcPromoRemoveUserRights();
  2012. if ( dwPromoteOptions & SCE_PROMOTE_FLAG_UPGRADE ) {
  2013. // NT4 DC upgrade.
  2014. // import AREA_SECURITY_POLICY from dsup.inf
  2015. // so that registry values gets secured correctly
  2016. // on NT4 DC upgrades.
  2017. //
  2018. DWORD dwSize = (wcslen(TEXT("\\inf\\dsup.inf")) + wcslen(Buffer) + 1)*sizeof(WCHAR);
  2019. PWSTR pszTempName = (PWSTR) ScepAlloc(LMEM_ZEROINIT, dwSize);
  2020. if(pszTempName){
  2021. Area = AREA_SECURITY_POLICY;
  2022. wcscpy(pszTempName, Buffer);
  2023. wcscat(pszTempName, TEXT("\\inf\\dsup.inf"));
  2024. rc = SceRpcConfigureSystem(binding_h,
  2025. (wchar_t *)pszTempName,
  2026. NULL,
  2027. (wchar_t *)szNewName,
  2028. ConfigOptions | SCE_NO_CONFIG | SCE_NO_DOMAIN_POLICY,
  2029. (AREAPR)Area,
  2030. ebSize,
  2031. (UCHAR *)pebClient,
  2032. &dWarn
  2033. );
  2034. ScepFree(pszTempName);
  2035. pszTempName = NULL;
  2036. }
  2037. else{
  2038. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2039. }
  2040. }
  2041. Area = AREA_FILE_SECURITY | AREA_REGISTRY_SECURITY |
  2042. AREA_SYSTEM_SERVICE | AREA_SECURITY_POLICY;
  2043. ConfigOptions |= ( SCE_NO_DOMAIN_POLICY |
  2044. SCE_SERVICE_NO_REALTIME_ENFORCE );
  2045. //
  2046. // user rights need to be configured for first DC as well as replica
  2047. // because there are new user rights that are not defined in group policies.
  2048. //
  2049. Area |= AREA_PRIVILEGES;
  2050. ConfigOptions |= (SCE_DCPROMO_WAIT | SCE_CREATE_BUILTIN_ACCOUNTS);
  2051. }
  2052. pTemplateFile = szGenName;
  2053. }
  2054. if(SCESTATUS_SUCCESS == rc){
  2055. rc = SceRpcConfigureSystem(
  2056. binding_h,
  2057. (wchar_t *)pTemplateFile,
  2058. NULL,
  2059. (wchar_t *)szNewName,
  2060. ConfigOptions,
  2061. (AREAPR)Area,
  2062. ebSize,
  2063. (UCHAR *)pebClient,
  2064. &dWarn
  2065. );
  2066. }
  2067. rc32 = ScepSceStatusToDosError(rc);
  2068. if ( bSetSecurity == TRUE ) {
  2069. //
  2070. // reset the flag
  2071. //
  2072. ScepRegDeleteValue(
  2073. HKEY_LOCAL_MACHINE,
  2074. SCE_ROOT_PATH,
  2075. TEXT("PromoteUpgradeInProgress")
  2076. );
  2077. }
  2078. if ( rc32 == NO_ERROR && (dwPromoteOptions & SCE_PROMOTE_FLAG_DEMOTE) ) {
  2079. //
  2080. // Now we need to import the file/registry/services
  2081. // permissions from dsup.inf (vs. getting them
  2082. // from "defltsv.inf") because we are using "0" mode
  2083. // in dsup.inf which allows protected acls for components
  2084. // to be preserved, thus not break on demotion.
  2085. // Also, on demotion we need to import "syscomp.inf"
  2086. // so we can get the Consol apps lock down
  2087. //
  2088. TCHAR szTempName[MAX_PATH + 51] = {0};
  2089. wcscpy(szTempName, Buffer);
  2090. wcscat(szTempName, TEXT("\\inf\\dsup.inf"));
  2091. //
  2092. // remove the SCE_DC_DEMOTE flag so we don't delete the existing
  2093. // security in the database.
  2094. //
  2095. ConfigOptions &= ~(SCE_DC_DEMOTE);
  2096. //
  2097. // Areas with acls
  2098. //
  2099. Area = AREA_FILE_SECURITY | AREA_REGISTRY_SECURITY | AREA_SYSTEM_SERVICE;
  2100. //
  2101. // import "dsup.inf"
  2102. //
  2103. rc = SceRpcConfigureSystem(
  2104. binding_h,
  2105. (wchar_t *)szTempName,
  2106. NULL,
  2107. (wchar_t *)szNewName,
  2108. ConfigOptions,
  2109. (AREAPR)Area,
  2110. ebSize,
  2111. (UCHAR *)pebClient,
  2112. &dWarn
  2113. );
  2114. if(SCESTATUS_SUCCESS == rc){
  2115. //
  2116. // Now "syscomp.inf"
  2117. //
  2118. wcscpy(szTempName, Buffer);
  2119. wcscat(szTempName, TEXT("\\inf\\syscomp.inf"));
  2120. //
  2121. // only file security section
  2122. //
  2123. Area = AREA_FILE_SECURITY;
  2124. //
  2125. // import "syscomp.inf"
  2126. //
  2127. rc = SceRpcConfigureSystem(
  2128. binding_h,
  2129. (wchar_t *)szTempName,
  2130. NULL,
  2131. (wchar_t *)szNewName,
  2132. ConfigOptions,
  2133. (AREAPR)Area,
  2134. ebSize,
  2135. (UCHAR *)pebClient,
  2136. &dWarn
  2137. );
  2138. if(SCESTATUS_SUCCESS == rc){
  2139. //
  2140. // can't reset account policy since SAM is going away (re-created)
  2141. //
  2142. Area = AREA_FILE_SECURITY | AREA_REGISTRY_SECURITY | AREA_SYSTEM_SERVICE;
  2143. ConfigOptions = SCE_DEBUG_LOG | SCE_DCPROMO_WAIT | SCE_NO_DOMAIN_POLICY | SCE_SERVICE_NO_REALTIME_ENFORCE;
  2144. if ( pScePromoteCallBack ) {
  2145. ConfigOptions |= SCE_CALLBACK_DELTA;
  2146. }
  2147. rc = SceRpcConfigureSystem(
  2148. binding_h,
  2149. NULL,
  2150. NULL,
  2151. (wchar_t *)szNewName,
  2152. ConfigOptions,
  2153. (AREAPR)Area,
  2154. ebSize,
  2155. (UCHAR *)pebClient,
  2156. &dWarn
  2157. );
  2158. }
  2159. }
  2160. rc32 = ScepSceStatusToDosError(rc);
  2161. //
  2162. // reset the previousPolicyArea so that at reboot after demotion
  2163. // the above policy will get reset
  2164. //
  2165. ScepRegSetIntValue(
  2166. HKEY_LOCAL_MACHINE,
  2167. GPT_SCEDLL_NEW_PATH,
  2168. TEXT("PreviousPolicyAreas"),
  2169. AREA_SECURITY_POLICY | AREA_PRIVILEGES | AREA_GROUP_MEMBERSHIP
  2170. );
  2171. }
  2172. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2173. //
  2174. // get exception code (DWORD)
  2175. //
  2176. rc32 = RpcExceptionCode();
  2177. LogEventAndReport(MyModuleHandle,
  2178. (wchar_t *)szNewName,
  2179. STATUS_SEVERITY_WARNING,
  2180. SCEEVENT_WARNING_PROMOTE_SECURITY,
  2181. IDS_ERROR_PROMOTE_SECURITY,
  2182. rc32
  2183. );
  2184. } RpcEndExcept;
  2185. //
  2186. // Free the binding handle
  2187. //
  2188. RpcpUnbindRpc( binding_h );
  2189. if(pebClient)
  2190. {
  2191. FreeEnvironmentStrings((LPTSTR)pebClient);
  2192. }
  2193. } else {
  2194. rc32 = RtlNtStatusToDosError(NtStatus);
  2195. }
  2196. ScepSetCallback(NULL, NULL, 0);
  2197. rc = ScepRegDeleteValue(
  2198. HKEY_LOCAL_MACHINE,
  2199. SCE_ROOT_PATH,
  2200. TEXT("PolicyFilterOff")
  2201. );
  2202. if ( rc != ERROR_SUCCESS &&
  2203. rc != ERROR_FILE_NOT_FOUND &&
  2204. rc != ERROR_PATH_NOT_FOUND ) {
  2205. // if can't delete the value, set the value to 0
  2206. ScepRegSetIntValue( HKEY_LOCAL_MACHINE,
  2207. SCE_ROOT_PATH,
  2208. TEXT("PolicyFilterOff"),
  2209. 0
  2210. );
  2211. }
  2212. rc = ScepRegDeleteValue(
  2213. HKEY_LOCAL_MACHINE,
  2214. SCE_ROOT_PATH,
  2215. TEXT("PolicyPropOff")
  2216. );
  2217. if ( rc != ERROR_SUCCESS &&
  2218. rc != ERROR_FILE_NOT_FOUND &&
  2219. rc != ERROR_PATH_NOT_FOUND ) {
  2220. // if can't delete the value, set the value to 0
  2221. ScepRegSetIntValue( HKEY_LOCAL_MACHINE,
  2222. SCE_ROOT_PATH,
  2223. TEXT("PolicyPropOff"),
  2224. 0
  2225. );
  2226. }
  2227. if ( dwPromoteOptions & SCE_PROMOTE_FLAG_DEMOTE ) {
  2228. ScepRegSetIntValue(
  2229. HKEY_LOCAL_MACHINE,
  2230. SCE_ROOT_PATH,
  2231. TEXT("DemoteInProgress"),
  2232. 1
  2233. );
  2234. }
  2235. return(rc32);
  2236. }
  2237. NTSTATUS
  2238. ScepDcPromoRemoveUserRights()
  2239. {
  2240. NTSTATUS NtStatus;
  2241. LSA_HANDLE PolicyHandle=NULL;
  2242. SID_IDENTIFIER_AUTHORITY ia=SECURITY_NT_AUTHORITY;
  2243. SID_IDENTIFIER_AUTHORITY ia2=SECURITY_WORLD_SID_AUTHORITY;
  2244. PSID AccountSid=NULL;
  2245. //
  2246. // open LSA policy
  2247. //
  2248. NtStatus = ScepOpenLsaPolicy(
  2249. MAXIMUM_ALLOWED, //GENERIC_ALL,
  2250. &PolicyHandle,
  2251. TRUE
  2252. );
  2253. if ( NT_SUCCESS(NtStatus) ) {
  2254. //
  2255. // remove Power Users account totally
  2256. //
  2257. NtStatus = RtlAllocateAndInitializeSid (&ia,
  2258. 2,
  2259. SECURITY_BUILTIN_DOMAIN_RID,
  2260. DOMAIN_ALIAS_RID_POWER_USERS,
  2261. 0, 0, 0, 0, 0, 0,
  2262. &AccountSid);
  2263. if ( NT_SUCCESS(NtStatus) ) {
  2264. NtStatus = LsaRemoveAccountRights(
  2265. PolicyHandle,
  2266. AccountSid,
  2267. TRUE, // remove all rights
  2268. NULL,
  2269. 0
  2270. );
  2271. RtlFreeSid(AccountSid);
  2272. }
  2273. //
  2274. // Users
  2275. //
  2276. ScepDcPromoRemoveTwoRights(PolicyHandle,
  2277. &ia,
  2278. 2,
  2279. SECURITY_BUILTIN_DOMAIN_RID,
  2280. DOMAIN_ALIAS_RID_USERS
  2281. );
  2282. //
  2283. // Guests
  2284. //
  2285. ScepDcPromoRemoveTwoRights(PolicyHandle,
  2286. &ia,
  2287. 2,
  2288. SECURITY_BUILTIN_DOMAIN_RID,
  2289. DOMAIN_ALIAS_RID_GUESTS
  2290. );
  2291. //
  2292. // Authenticated Users
  2293. //
  2294. ScepDcPromoRemoveTwoRights(PolicyHandle,
  2295. &ia,
  2296. 1,
  2297. SECURITY_AUTHENTICATED_USER_RID,
  2298. 0
  2299. );
  2300. //
  2301. // Everyone
  2302. //
  2303. ScepDcPromoRemoveTwoRights(PolicyHandle,
  2304. &ia2,
  2305. 1,
  2306. SECURITY_WORLD_RID,
  2307. 0
  2308. );
  2309. LsaClose(PolicyHandle);
  2310. }
  2311. return NtStatus;
  2312. }
  2313. NTSTATUS
  2314. ScepDcPromoRemoveTwoRights(
  2315. IN LSA_HANDLE PolicyHandle,
  2316. IN SID_IDENTIFIER_AUTHORITY *pIA,
  2317. IN UCHAR SubAuthCount,
  2318. IN DWORD Rid1,
  2319. IN DWORD Rid2
  2320. )
  2321. {
  2322. //
  2323. // remove "logon locally" and "shutdown system" from the following accounts
  2324. //
  2325. LSA_UNICODE_STRING UserRightRemove[2];
  2326. RtlInitUnicodeString(&(UserRightRemove[0]), SE_INTERACTIVE_LOGON_NAME);
  2327. RtlInitUnicodeString(&(UserRightRemove[1]), SE_SHUTDOWN_NAME);
  2328. PSID AccountSid=NULL;
  2329. NTSTATUS NtStatus;
  2330. NtStatus = RtlAllocateAndInitializeSid (pIA,
  2331. SubAuthCount,
  2332. Rid1,
  2333. Rid2,
  2334. 0, 0, 0, 0, 0, 0,
  2335. &AccountSid);
  2336. if ( NT_SUCCESS(NtStatus) ) {
  2337. NtStatus = LsaRemoveAccountRights(
  2338. PolicyHandle,
  2339. AccountSid,
  2340. FALSE,
  2341. UserRightRemove,
  2342. 2
  2343. );
  2344. RtlFreeSid(AccountSid);
  2345. }
  2346. return(NtStatus);
  2347. }
  2348. //
  2349. // private APIs
  2350. //
  2351. DWORD
  2352. ScepSetupOpenSecurityDatabase(
  2353. IN BOOL bSystemOrAdmin
  2354. )
  2355. {
  2356. if ( hSceSetupHandle != NULL ) {
  2357. return ERROR_SUCCESS;
  2358. }
  2359. //
  2360. // get the default template name (on local system because setup only
  2361. // runs on local system
  2362. //
  2363. SCESTATUS rc;
  2364. BOOL bAdminLogon;
  2365. PWSTR DefProfile=NULL;
  2366. //
  2367. // don't care if error occurs to detect who is currently logged on
  2368. // setup always work on local computer so no remoate is supported here
  2369. //
  2370. if ( bSystemOrAdmin ) {
  2371. bAdminLogon = TRUE;
  2372. } else {
  2373. ScepIsAdminLoggedOn(&bAdminLogon, FALSE);
  2374. }
  2375. rc = ScepGetProfileSetting(
  2376. L"DefaultProfile",
  2377. bAdminLogon,
  2378. &DefProfile
  2379. );
  2380. if ( rc != NO_ERROR ) // return is Win32 error code
  2381. return(rc);
  2382. if (DefProfile == NULL ) {
  2383. return(ERROR_FILE_NOT_FOUND);
  2384. }
  2385. handle_t binding_h;
  2386. NTSTATUS NtStatus;
  2387. //
  2388. // RPC bind to the server (secure is not required)
  2389. //
  2390. NtStatus = ScepBindRpc(
  2391. NULL,
  2392. L"scerpc",
  2393. 0,
  2394. &binding_h
  2395. );
  2396. /*
  2397. NtStatus = ScepBindSecureRpc(
  2398. NULL,
  2399. L"scerpc",
  2400. 0,
  2401. &binding_h
  2402. );
  2403. */
  2404. if (NT_SUCCESS(NtStatus)){
  2405. RpcTryExcept {
  2406. //
  2407. // should create file if it does not exist
  2408. //
  2409. rc = SceRpcOpenDatabase(
  2410. binding_h,
  2411. (wchar_t *)DefProfile,
  2412. SCE_OPEN_OPTION_TATTOO,
  2413. &hSceSetupHandle
  2414. );
  2415. rc = ScepSceStatusToDosError(rc);
  2416. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  2417. //
  2418. // get exception code (DWORD)
  2419. //
  2420. rc = RpcExceptionCode();
  2421. } RpcEndExcept;
  2422. //
  2423. // Free the binding handle
  2424. //
  2425. RpcpUnbindRpc( binding_h );
  2426. } else {
  2427. rc = RtlNtStatusToDosError( NtStatus );
  2428. }
  2429. ScepFree( DefProfile );
  2430. return(rc);
  2431. }
  2432. DWORD
  2433. ScepSetupCloseSecurityDatabase()
  2434. {
  2435. DWORD rc;
  2436. if ( hSceSetupHandle != NULL ) {
  2437. //
  2438. // close the database, without terminating the jet engine
  2439. //
  2440. rc = ScepSceStatusToDosError(
  2441. SceCloseProfile((PVOID *)&hSceSetupHandle) );
  2442. if ( rc != ERROR_SUCCESS ) {
  2443. //
  2444. // not valid handle, or can't close the database
  2445. //
  2446. return(rc);
  2447. }
  2448. }
  2449. //
  2450. // free other environments, if any
  2451. //
  2452. hSceSetupHandle = NULL;
  2453. return(ERROR_SUCCESS);
  2454. }
  2455. //
  2456. // the RPC callback
  2457. //
  2458. SCEPR_STATUS
  2459. SceClientCallback(
  2460. IN DWORD ncbTicks,
  2461. IN DWORD ncbTotalTicks,
  2462. IN AREAPR cbArea,
  2463. IN wchar_t *szcbName OPTIONAL
  2464. )
  2465. /*
  2466. Routine Description:
  2467. The RPC client callback routine which is called from the server when
  2468. the callback flag is set. This routine is registered in scerpc.idl.
  2469. The callbacks are registered to SCE as arguments when calling from setup
  2470. or from dcpromo, for progress indicating.
  2471. Arguments:
  2472. ncbTicks - the ticks has passed since last call back
  2473. szcbName - the item name to call back
  2474. Return Value:
  2475. SCEPR_STATUS
  2476. */
  2477. {
  2478. //
  2479. // the static variables holding callback pointer to client
  2480. //
  2481. if ( theCallBack != NULL ) {
  2482. switch ( CallbackType ) {
  2483. case SCE_SETUP_CALLBACK:
  2484. //
  2485. // callback to setup
  2486. //
  2487. if ( ncbTicks != (DWORD)-1 ) {
  2488. PSCE_NOTIFICATION_CALLBACK_ROUTINE pcb;
  2489. pcb = (PSCE_NOTIFICATION_CALLBACK_ROUTINE)theCallBack;
  2490. DWORD cbCount;
  2491. if ( dwCallbackTotal >= ncbTicks ) {
  2492. dwCallbackTotal -= ncbTicks;
  2493. cbCount = ncbTicks;
  2494. } else {
  2495. cbCount = dwCallbackTotal;
  2496. dwCallbackTotal = 0;
  2497. }
  2498. if ( cbCount > 0 ) {
  2499. __try {
  2500. //
  2501. // calls the client procedure with the prarmeters.
  2502. //
  2503. if ( !((*pcb)(hCallbackWnd,
  2504. SCESETUP_NOTIFICATION_TICKS,
  2505. 0,
  2506. ncbTicks)) ) {
  2507. return SCESTATUS_SERVICE_NOT_SUPPORT;
  2508. }
  2509. } __except(EXCEPTION_EXECUTE_HANDLER) {
  2510. return(SCESTATUS_INVALID_PARAMETER);
  2511. }
  2512. }
  2513. }
  2514. break;
  2515. case SCE_DCPROMO_CALLBACK:
  2516. //
  2517. // callback to dcpromo
  2518. //
  2519. if ( szcbName ) {
  2520. PSCE_PROMOTE_CALLBACK_ROUTINE pcb;
  2521. pcb = (PSCE_PROMOTE_CALLBACK_ROUTINE)theCallBack;
  2522. __try {
  2523. //
  2524. // callback to dcpromo process
  2525. //
  2526. PWSTR Buffer = (PWSTR)ScepAlloc(LPTR, (wcslen(szCallbackPrefix)+wcslen(szcbName)+1)*sizeof(WCHAR));
  2527. if ( Buffer ) {
  2528. if (wcsstr(szCallbackPrefix, L"%s")) {
  2529. //
  2530. // LoadString succeeded
  2531. //
  2532. swprintf(Buffer, szCallbackPrefix, szcbName);
  2533. }
  2534. else {
  2535. wcscpy(Buffer, szCallbackPrefix);
  2536. wcscat(Buffer, szcbName);
  2537. }
  2538. if ( (*pcb)(Buffer) != ERROR_SUCCESS ) {
  2539. ScepFree(Buffer);
  2540. Buffer = NULL;
  2541. return SCESTATUS_SERVICE_NOT_SUPPORT;
  2542. }
  2543. ScepFree(Buffer);
  2544. Buffer = NULL;
  2545. } else {
  2546. return SCESTATUS_NOT_ENOUGH_RESOURCE;
  2547. }
  2548. } __except(EXCEPTION_EXECUTE_HANDLER) {
  2549. return(SCESTATUS_INVALID_PARAMETER);
  2550. }
  2551. }
  2552. break;
  2553. case SCE_AREA_CALLBACK:
  2554. //
  2555. // callback to SCE UI for area progress
  2556. //
  2557. PSCE_AREA_CALLBACK_ROUTINE pcb;
  2558. pcb = (PSCE_AREA_CALLBACK_ROUTINE)theCallBack;
  2559. __try {
  2560. //
  2561. // callback to UI process
  2562. //
  2563. if ( !((*pcb)(hCallbackWnd,
  2564. (AREA_INFORMATION)cbArea,
  2565. ncbTotalTicks,
  2566. ncbTicks)) ) {
  2567. return SCESTATUS_SERVICE_NOT_SUPPORT;
  2568. }
  2569. } __except(EXCEPTION_EXECUTE_HANDLER) {
  2570. return(SCESTATUS_INVALID_PARAMETER);
  2571. }
  2572. break;
  2573. }
  2574. }
  2575. return(SCESTATUS_SUCCESS);
  2576. }
  2577. SCESTATUS
  2578. ScepSetupWriteError(
  2579. IN LPTSTR LogFileName,
  2580. IN PSCE_ERROR_LOG_INFO pErrlog
  2581. )
  2582. /* ++
  2583. Routine Description:
  2584. This routine outputs the error message in each node of the SCE_ERROR_LOG_INFO
  2585. list to the log file
  2586. Arguments:
  2587. LogFileName - the log file name
  2588. pErrlog - the error list
  2589. Return value:
  2590. None
  2591. -- */
  2592. {
  2593. if ( !pErrlog ) {
  2594. return(SCESTATUS_SUCCESS);
  2595. }
  2596. HANDLE hFile=INVALID_HANDLE_VALUE;
  2597. if ( LogFileName ) {
  2598. hFile = CreateFile(LogFileName,
  2599. GENERIC_WRITE,
  2600. FILE_SHARE_READ,
  2601. NULL,
  2602. OPEN_ALWAYS,
  2603. FILE_ATTRIBUTE_NORMAL,
  2604. NULL);
  2605. if (hFile != INVALID_HANDLE_VALUE) {
  2606. DWORD dwBytesWritten;
  2607. SetFilePointer (hFile, 0, NULL, FILE_BEGIN);
  2608. BYTE TmpBuf[3];
  2609. TmpBuf[0] = 0xFF;
  2610. TmpBuf[1] = 0xFE;
  2611. TmpBuf[2] = 0;
  2612. WriteFile (hFile, (LPCVOID)TmpBuf, 2,
  2613. &dwBytesWritten,
  2614. NULL);
  2615. SetFilePointer (hFile, 0, NULL, FILE_END);
  2616. }
  2617. }
  2618. PSCE_ERROR_LOG_INFO pErr;
  2619. for ( pErr=pErrlog; pErr != NULL; pErr = pErr->next ) {
  2620. if ( pErr->buffer != NULL ) {
  2621. ScepSetupWriteOneError( hFile, pErr->rc, pErr->buffer );
  2622. }
  2623. }
  2624. if ( INVALID_HANDLE_VALUE != hFile ) {
  2625. CloseHandle(hFile);
  2626. }
  2627. return(SCESTATUS_SUCCESS);
  2628. }
  2629. SCESTATUS
  2630. ScepSetupWriteOneError(
  2631. IN HANDLE hFile,
  2632. IN DWORD rc,
  2633. IN LPTSTR buf
  2634. )
  2635. {
  2636. LPVOID lpMsgBuf=NULL;
  2637. if ( !buf ) {
  2638. return(SCESTATUS_SUCCESS);
  2639. }
  2640. if ( rc != NO_ERROR ) {
  2641. //
  2642. // get error description of rc
  2643. //
  2644. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  2645. NULL,
  2646. rc,
  2647. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  2648. (LPTSTR)&lpMsgBuf,
  2649. 0,
  2650. NULL
  2651. );
  2652. }
  2653. if ( INVALID_HANDLE_VALUE != hFile ) {
  2654. //
  2655. // The log file is initialized
  2656. //
  2657. if ( lpMsgBuf != NULL )
  2658. ScepWriteVariableUnicodeLog( hFile, TRUE, L"%s %s", (PWSTR)lpMsgBuf, buf );
  2659. else
  2660. ScepWriteSingleUnicodeLog(hFile, TRUE, buf);
  2661. }
  2662. if ( lpMsgBuf != NULL )
  2663. LocalFree(lpMsgBuf);
  2664. return(SCESTATUS_SUCCESS);
  2665. }
  2666. DWORD
  2667. SceSetuppLogComponent(
  2668. IN DWORD ErrCode,
  2669. IN SCESETUP_OBJECT_TYPE ObjType,
  2670. IN SCESETUP_OPERATION_TYPE OptType,
  2671. IN PWSTR Name,
  2672. IN PWSTR SDText OPTIONAL,
  2673. IN PWSTR SecondName OPTIONAL
  2674. )
  2675. {
  2676. //
  2677. // check if this log should be generated
  2678. //
  2679. DWORD dwDebugLog=0;
  2680. ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
  2681. TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Secedit"),
  2682. TEXT("SetupCompDebugLevel"),
  2683. &dwDebugLog
  2684. );
  2685. if ( dwDebugLog == 0 ) {
  2686. return(ERROR_SUCCESS);
  2687. }
  2688. //
  2689. // build the component log file name %windir%\security\logs\scecomp.log
  2690. //
  2691. WCHAR LogName[MAX_PATH+51];
  2692. GetSystemWindowsDirectory(LogName, MAX_PATH);
  2693. LogName[MAX_PATH] = L'\0';
  2694. wcscat(LogName, L"\\security\\logs\\scecomp.log\0");
  2695. HANDLE hFile = CreateFile(LogName,
  2696. GENERIC_WRITE,
  2697. FILE_SHARE_READ,
  2698. NULL,
  2699. OPEN_ALWAYS,
  2700. FILE_ATTRIBUTE_NORMAL,
  2701. NULL);
  2702. if ( INVALID_HANDLE_VALUE != hFile ) {
  2703. DWORD dwBytesWritten;
  2704. SetFilePointer (hFile, 0, NULL, FILE_BEGIN);
  2705. BYTE TmpBuf[3];
  2706. TmpBuf[0] = 0xFF;
  2707. TmpBuf[1] = 0xFE;
  2708. TmpBuf[2] = 0;
  2709. WriteFile (hFile, (LPCVOID)TmpBuf, 2,
  2710. &dwBytesWritten,
  2711. NULL);
  2712. SetFilePointer (hFile, 0, NULL, FILE_END);
  2713. //
  2714. // print a time stamp
  2715. //
  2716. LARGE_INTEGER CurrentTime;
  2717. LARGE_INTEGER SysTime;
  2718. TIME_FIELDS TimeFields;
  2719. NTSTATUS NtStatus;
  2720. NtStatus = NtQuerySystemTime(&SysTime);
  2721. RtlSystemTimeToLocalTime (&SysTime,&CurrentTime);
  2722. if ( NT_SUCCESS(NtStatus) &&
  2723. (CurrentTime.LowPart != 0 || CurrentTime.HighPart != 0) ) {
  2724. memset(&TimeFields, 0, sizeof(TIME_FIELDS));
  2725. RtlTimeToTimeFields (
  2726. &CurrentTime,
  2727. &TimeFields
  2728. );
  2729. if ( TimeFields.Month > 0 && TimeFields.Month <= 12 &&
  2730. TimeFields.Day > 0 && TimeFields.Day <= 31 &&
  2731. TimeFields.Year > 1600 ) {
  2732. ScepWriteVariableUnicodeLog(hFile, FALSE,
  2733. L"%02d/%02d/%04d %02d:%02d:%02d",
  2734. TimeFields.Month, TimeFields.Day, TimeFields.Year,
  2735. TimeFields.Hour, TimeFields.Minute, TimeFields.Second);
  2736. } else {
  2737. ScepWriteVariableUnicodeLog(hFile, FALSE, L"%08x08x",
  2738. CurrentTime.HighPart, CurrentTime.LowPart);
  2739. }
  2740. } else {
  2741. ScepWriteSingleUnicodeLog(hFile, FALSE, L"Unknown time");
  2742. }
  2743. //
  2744. // print operation status code
  2745. //
  2746. if ( ErrCode ) {
  2747. ScepWriteVariableUnicodeLog(hFile, FALSE, L"\tError=%d", ErrCode);
  2748. } else {
  2749. ScepWriteSingleUnicodeLog(hFile, FALSE, L"\tSucceed");
  2750. }
  2751. //
  2752. // printf operation type
  2753. //
  2754. switch (OptType) {
  2755. case SCESETUP_UPDATE:
  2756. ScepWriteSingleUnicodeLog(hFile, FALSE, L"\tUpdate");
  2757. break;
  2758. case SCESETUP_MOVE:
  2759. ScepWriteSingleUnicodeLog(hFile, FALSE, L"\tMove");
  2760. break;
  2761. default:
  2762. ScepWriteSingleUnicodeLog(hFile, FALSE, L"\tUnknown");
  2763. break;
  2764. }
  2765. //
  2766. // print object type
  2767. //
  2768. switch (ObjType) {
  2769. case SCESETUP_FILE:
  2770. ScepWriteSingleUnicodeLog(hFile, TRUE, L"\tFile");
  2771. break;
  2772. case SCESETUP_KEY:
  2773. ScepWriteSingleUnicodeLog(hFile, TRUE, L"\tKey");
  2774. break;
  2775. case SCESETUP_SERVICE:
  2776. ScepWriteSingleUnicodeLog(hFile, TRUE, L"\tService");
  2777. break;
  2778. default:
  2779. ScepWriteSingleUnicodeLog(hFile, TRUE, L"\tUnknown");
  2780. break;
  2781. }
  2782. __try {
  2783. //
  2784. // print the name(s)
  2785. //
  2786. ScepWriteSingleUnicodeLog(hFile, FALSE, L"\t");
  2787. if ( SecondName && Name ) {
  2788. // Name\tSecondName\n
  2789. ScepWriteSingleUnicodeLog(hFile, FALSE, Name);
  2790. ScepWriteSingleUnicodeLog(hFile, FALSE, L"\t");
  2791. ScepWriteSingleUnicodeLog(hFile, TRUE, SecondName);
  2792. } else if ( Name ) {
  2793. ScepWriteSingleUnicodeLog(hFile, TRUE, Name);
  2794. }
  2795. //
  2796. // print the SDDL string
  2797. //
  2798. if ( SDText ) {
  2799. ScepWriteSingleUnicodeLog(hFile, FALSE, L"\tSecurity=");
  2800. ScepWriteSingleUnicodeLog(hFile, TRUE, SDText);
  2801. }
  2802. } __except(EXCEPTION_EXECUTE_HANDLER) {
  2803. return(ERROR_INVALID_PARAMETER);
  2804. }
  2805. CloseHandle(hFile);
  2806. } else {
  2807. return(GetLastError());
  2808. }
  2809. return(ERROR_SUCCESS);
  2810. }
  2811. DWORD
  2812. WINAPI
  2813. SceSetupBackupSecurity(
  2814. IN LPTSTR LogFileName OPTIONAL // default to %windir%\security\logs\backup.log
  2815. )
  2816. {
  2817. TCHAR Buffer[MAX_PATH+1];
  2818. DWORD rc32;
  2819. TCHAR szGenName[MAX_PATH*2], szNewName[MAX_PATH+51];
  2820. DWORD eProductType;
  2821. eProductType = WhichNTProduct();
  2822. Buffer[0] = L'\0';
  2823. GetSystemWindowsDirectory(Buffer, MAX_PATH);
  2824. Buffer[MAX_PATH] = L'\0';
  2825. szNewName[0] = L'\0';
  2826. if ( LogFileName == NULL ) {
  2827. wcscpy(szNewName, Buffer);
  2828. wcscat(szNewName, L"\\security\\logs\\backup.log\0");
  2829. }
  2830. (void) InitializeEvents(L"SceCli");
  2831. //
  2832. // if I am in setup, query the security policy/user rights for any
  2833. // policy changes within setup (such as NT4 PDC upgrade where the policy
  2834. // filter will fail to save the change)
  2835. //
  2836. DWORD dwInSetup=0;
  2837. DWORD dwUpgraded=0;
  2838. ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
  2839. TEXT("System\\Setup"),
  2840. TEXT("SystemSetupInProgress"),
  2841. &dwInSetup
  2842. );
  2843. if ( dwInSetup ) {
  2844. //
  2845. // delete the temp local group policy template
  2846. //
  2847. wcscpy(szGenName, Buffer);
  2848. wcscat(szGenName, L"\\system32\\grouppolicy\\machine\\microsoft\\windows nt\\secedit\\gpttmpl.inf\0");
  2849. DeleteFile(szGenName);
  2850. ScepRegQueryIntValue(
  2851. HKEY_LOCAL_MACHINE,
  2852. SCE_ROOT_PATH,
  2853. TEXT("SetupUpgraded"),
  2854. (DWORD *)&dwUpgraded
  2855. );
  2856. /*
  2857. if ( dwUpgraded ) {
  2858. //
  2859. // in GUI setup, snapshot the system security/user rights
  2860. // query the upgrade flag, only query the system (again) when
  2861. // it's upgraded, because for the case of NT4 PDC upgrade to NT5
  2862. // any back office apps installed in GUI setup (user rights) won't
  2863. // get saved to the GPO storage correctly (ProductType is wrong)
  2864. //
  2865. rc32 = ScepSystemSecurityInSetup(
  2866. szNewName, // not used
  2867. LogFileName ? LogFileName : szNewName,
  2868. 0,
  2869. SCESETUP_UPGRADE_SYSTEM | SCESETUP_BIND_NO_AUTH,
  2870. NULL,
  2871. NULL
  2872. );
  2873. if ( NO_ERROR != rc32 ) {
  2874. LogEventAndReport(MyModuleHandle,
  2875. LogFileName ? LogFileName : szNewName,
  2876. 0,
  2877. 0,
  2878. IDS_ERROR_SNAPSHOT_SECURITY,
  2879. rc32
  2880. );
  2881. } else {
  2882. LogEventAndReport(MyModuleHandle,
  2883. LogFileName ? LogFileName : szNewName,
  2884. 0,
  2885. 0,
  2886. IDS_SNAPSHOT_SECURITY_POLICY
  2887. );
  2888. }
  2889. }
  2890. //
  2891. // reset the value
  2892. //
  2893. ScepRegSetIntValue(
  2894. HKEY_LOCAL_MACHINE,
  2895. SCE_ROOT_PATH,
  2896. TEXT("SetupUpgraded"),
  2897. 0
  2898. );
  2899. */
  2900. }
  2901. //
  2902. // open the database
  2903. //
  2904. rc32 = ScepSetupOpenSecurityDatabase(TRUE);
  2905. BOOL bUpgradeNt5 = (BOOL)(dwUpgraded && IsNT5());
  2906. if ( NO_ERROR == rc32 ) {
  2907. wcscpy(szGenName, Buffer);
  2908. wcscat(szGenName, L"\\security\\setup.inf\0");
  2909. //
  2910. // generate the updated database (for emergency repair)
  2911. // %windir%\security\templates\setup security.inf
  2912. //
  2913. PSCE_ERROR_LOG_INFO pErrlog=NULL;
  2914. rc32 = ScepSceStatusToDosError(
  2915. SceCopyBaseProfile(
  2916. (PVOID)hSceSetupHandle,
  2917. SCE_ENGINE_SMP,
  2918. (wchar_t *)szGenName,
  2919. dwInSetup ?
  2920. AREA_ALL :
  2921. (AREA_REGISTRY_SECURITY |
  2922. AREA_FILE_SECURITY |
  2923. AREA_SYSTEM_SERVICE),
  2924. &pErrlog
  2925. ));
  2926. ScepSetupWriteError(LogFileName ? LogFileName : szNewName, pErrlog);
  2927. ScepFreeErrorLog(pErrlog);
  2928. if ( rc32 != NO_ERROR ) {
  2929. LogEventAndReport(MyModuleHandle,
  2930. LogFileName ? LogFileName : szNewName,
  2931. STATUS_SEVERITY_ERROR,
  2932. SCEEVENT_ERROR_BACKUP_SECURITY,
  2933. IDS_ERROR_GENERATE,
  2934. rc32,
  2935. szGenName,
  2936. LogFileName ? LogFileName : szNewName
  2937. );
  2938. }
  2939. if (NO_ERROR == rc32 && bUpgradeNt5) {
  2940. //
  2941. // when upgrading from win2k, update (merge) "setup security.inf" or "DC security.inf"
  2942. // with the information in the backup security template
  2943. //
  2944. rc32 = ScepUpdateBackupSecurity(szGenName,
  2945. Buffer,
  2946. (NtProductLanManNt == eProductType)?TRUE:FALSE
  2947. );
  2948. }
  2949. //
  2950. // check if we should trigger a policy propagation manually
  2951. //
  2952. DWORD dwResetOption=0;
  2953. if ( dwInSetup && dwUpgraded )
  2954. dwResetOption |= SCE_RESET_POLICY_ENFORCE_ATREBOOT;
  2955. //
  2956. // remove local policies from the database
  2957. // for NT4 DC upgrade case, keep the local policy setting until dcpromo
  2958. //
  2959. if ( dwInSetup && dwUpgraded && !IsNT5() &&
  2960. NtProductLanManNt == eProductType )
  2961. dwResetOption |= SCE_RESET_POLICY_KEEP_LOCAL;
  2962. //
  2963. // if it's after dcpromo, need to empty tattoo table
  2964. // if LogFileName is NULL and it's not in setup, it's in DC demotion in which case
  2965. // we want to leave the tattoo table (w/ reset settings)
  2966. //
  2967. if ( !dwInSetup && (LogFileName != NULL) )
  2968. dwResetOption |= SCE_RESET_POLICY_TATTOO;
  2969. DWORD rCode = SceRpcSetupResetLocalPolicy(
  2970. (PVOID)hSceSetupHandle,
  2971. AREA_ALL,
  2972. NULL,
  2973. dwResetOption
  2974. );
  2975. LogEventAndReport(MyModuleHandle,
  2976. LogFileName ? LogFileName : szNewName,
  2977. 0,
  2978. 0,
  2979. IDS_ERROR_REMOVE_DEFAULT_POLICY,
  2980. rCode,
  2981. dwResetOption
  2982. );
  2983. //
  2984. // close the context
  2985. //
  2986. ScepSetupCloseSecurityDatabase();
  2987. if ( NO_ERROR == rc32 ){
  2988. //
  2989. // template is always generated, copy it to %windir%\security\templates and
  2990. // to %windir%\repair
  2991. //
  2992. szNewName[0] = L'0';
  2993. //
  2994. // Load string for the description
  2995. //
  2996. LoadString( MyModuleHandle,
  2997. dwInSetup ? IDS_BACKUP_OUTBOX_DESCRIPTION : IDS_BACKUP_DC_DESCRIPTION,
  2998. szNewName,
  2999. MAX_PATH
  3000. );
  3001. //
  3002. // re-write descriptoin for there backup files.
  3003. //
  3004. WritePrivateProfileSection(
  3005. L"Profile Description",
  3006. NULL,
  3007. (LPCTSTR)szGenName);
  3008. if ( szNewName[0] ) {
  3009. WritePrivateProfileString(
  3010. L"Profile Description",
  3011. L"Description",
  3012. szNewName,
  3013. (LPCTSTR)szGenName);
  3014. }
  3015. //
  3016. // copy the file to its destination
  3017. //
  3018. szNewName[0] = L'0';
  3019. wcscpy(szNewName, Buffer);
  3020. if ( (!dwInSetup && (LogFileName == NULL)) ||
  3021. (dwInSetup && (NtProductLanManNt != eProductType))){
  3022. wcscat(szNewName, L"\\security\\templates\\setup security.inf\0");
  3023. }
  3024. else{
  3025. wcscat(szNewName, L"\\security\\templates\\DC security.inf\0");
  3026. }
  3027. if ( CopyFile( szGenName, szNewName, FALSE ) ) {
  3028. LogEvent(MyModuleHandle,
  3029. STATUS_SEVERITY_INFORMATIONAL,
  3030. SCEEVENT_INFO_BACKUP_SECURITY,
  3031. 0,
  3032. szNewName
  3033. );
  3034. wcscpy(szNewName, Buffer);
  3035. if ( (!dwInSetup && (LogFileName == NULL)) ||
  3036. (dwInSetup && (NtProductLanManNt != eProductType))){
  3037. wcscat(szNewName, L"\\repair\\secsetup.inf\0");
  3038. } else {
  3039. wcscat(szNewName, L"\\repair\\secDC.inf\0");
  3040. }
  3041. CopyFile( szGenName, szNewName, FALSE );
  3042. } else {
  3043. rc32 = GetLastError();
  3044. wcscpy(szNewName, Buffer);
  3045. if ( (!dwInSetup && (LogFileName == NULL)) ||
  3046. (dwInSetup && (NtProductLanManNt != eProductType))){
  3047. wcscat(szNewName, L"\\repair\\secsetup.inf\0");
  3048. } else {
  3049. wcscat(szNewName, L"\\repair\\secDC.inf\0");
  3050. }
  3051. if ( CopyFile( szGenName, szNewName, FALSE ) ) {
  3052. LogEvent(MyModuleHandle,
  3053. STATUS_SEVERITY_WARNING,
  3054. SCEEVENT_WARNING_BACKUP_SECURITY,
  3055. 0,
  3056. szNewName
  3057. );
  3058. rc32 = ERROR_SUCCESS;
  3059. } else {
  3060. rc32 = GetLastError();
  3061. LogEvent(MyModuleHandle,
  3062. STATUS_SEVERITY_ERROR,
  3063. SCEEVENT_ERROR_BACKUP_SECURITY,
  3064. IDS_ERROR_BACKUP,
  3065. rc32
  3066. );
  3067. }
  3068. }
  3069. DeleteFile(szGenName);
  3070. }
  3071. } else {
  3072. LogEventAndReport(MyModuleHandle,
  3073. LogFileName ? LogFileName : szNewName,
  3074. STATUS_SEVERITY_ERROR,
  3075. SCEEVENT_ERROR_BACKUP_SECURITY,
  3076. IDS_ERROR_OPEN_DATABASE,
  3077. rc32
  3078. );
  3079. }
  3080. if ( dwInSetup ) {
  3081. dwThisMachine = eProductType;
  3082. if ((dwThisMachine == NtProductServer || dwThisMachine == NtProductWinNt) ||
  3083. ((dwThisMachine == NtProductLanManNt) && IsNT5())) {
  3084. //
  3085. // reconfigure file
  3086. //
  3087. TCHAR szLogName[MAX_PATH+51], szTempName[MAX_PATH+51];
  3088. wcscpy(szLogName, Buffer);
  3089. wcscat(szLogName, L"\\security\\logs\\scesetup.log\0");
  3090. wcscpy(szTempName, Buffer);
  3091. wcscat(szTempName, L"\\inf\\syscomp.inf\0");
  3092. rc32 = ScepSystemSecurityInSetup(
  3093. szTempName,
  3094. szLogName,
  3095. 0,
  3096. SCESETUP_RECONFIG_SECURITY | SCESETUP_BIND_NO_AUTH,
  3097. NULL,
  3098. NULL
  3099. );
  3100. if ( NO_ERROR != rc32 ) {
  3101. LogEventAndReport(MyModuleHandle,
  3102. szLogName,
  3103. 0,
  3104. 0,
  3105. IDS_ERR_RECONFIG_FILES,
  3106. rc32
  3107. );
  3108. }
  3109. //
  3110. // append syscomp.inf to "setup security.inf" or
  3111. // "DC security.inf"
  3112. //
  3113. PVOID hProfile = NULL;
  3114. PSCE_PROFILE_INFO pReConfFile = NULL;
  3115. SCESTATUS rcSce = SCESTATUS_SUCCESS;
  3116. //
  3117. // first export the syscomp.inf data from the database
  3118. // so we can get the enviroment variables resolved
  3119. // which allows us to do a successful merge with
  3120. // setup/DC security.inf
  3121. //
  3122. wcscpy(szTempName, Buffer);
  3123. wcscat(szTempName, L"\\security\\templates\\syscomp.inf\0");
  3124. //
  3125. // open the database
  3126. //
  3127. rcSce = ScepSetupOpenSecurityDatabase(TRUE);
  3128. if(SCESTATUS_SUCCESS == rcSce){
  3129. //
  3130. // export syscomp data to a temp file
  3131. //
  3132. rcSce = SceCopyBaseProfile((PVOID)hSceSetupHandle,
  3133. SCE_ENGINE_SMP,
  3134. (wchar_t *)szTempName,
  3135. AREA_FILE_SECURITY,
  3136. NULL
  3137. );
  3138. if(SCESTATUS_SUCCESS == rcSce){
  3139. //
  3140. // open the temp file and read the file section
  3141. //
  3142. rcSce = SceOpenProfile(szTempName,
  3143. SCE_INF_FORMAT,
  3144. &hProfile
  3145. );
  3146. if(SCESTATUS_SUCCESS == rcSce){
  3147. rcSce = SceGetSecurityProfileInfo(hProfile,
  3148. SCE_ENGINE_SCP,
  3149. AREA_FILE_SECURITY,
  3150. &pReConfFile,
  3151. NULL
  3152. );
  3153. if(SCESTATUS_SUCCESS == rcSce){
  3154. //
  3155. // append the data to setup/DC security.inf
  3156. //
  3157. wcscpy(szTempName, Buffer);
  3158. if(dwThisMachine == NtProductLanManNt){
  3159. wcscat(szTempName, L"\\security\\templates\\DC security.inf\0");
  3160. }
  3161. else{
  3162. wcscat(szTempName, L"\\security\\templates\\setup security.inf\0");
  3163. }
  3164. rcSce = SceAppendSecurityProfileInfo(szTempName,
  3165. AREA_FILE_SECURITY,
  3166. pReConfFile,
  3167. NULL
  3168. );
  3169. SceFreeProfileMemory(pReConfFile);
  3170. }
  3171. SceCloseProfile(&hProfile);
  3172. }
  3173. //
  3174. // delete the temp file
  3175. //
  3176. wcscpy(szTempName, Buffer);
  3177. wcscat(szTempName, L"\\security\\templates\\syscomp.inf\0");
  3178. DeleteFile(szTempName);
  3179. }
  3180. //
  3181. // remove local policies from the database
  3182. //
  3183. (void)SceRpcSetupResetLocalPolicy(
  3184. (PVOID)hSceSetupHandle,
  3185. AREA_FILE_SECURITY,
  3186. NULL,
  3187. 0
  3188. );
  3189. ScepSetupCloseSecurityDatabase();
  3190. }
  3191. if(SCESTATUS_SUCCESS != rcSce){
  3192. rc32 = ScepSceStatusToDosError(rcSce);
  3193. wcscpy(szTempName, Buffer);
  3194. wcscat(szTempName, L"\\security\\templates\\setup security.inf\0");
  3195. LogEventAndReport(MyModuleHandle,
  3196. szLogName,
  3197. STATUS_SEVERITY_ERROR,
  3198. SCEEVENT_ERROR_BACKUP_SECURITY,
  3199. IDS_ERROR_MERGE_BACKUP_SECURITY,
  3200. rc32,
  3201. szTempName
  3202. );
  3203. }
  3204. }
  3205. }
  3206. (void) ShutdownEvents();
  3207. return(rc32);
  3208. }
  3209. SCESTATUS
  3210. ScepUpdateBackupSecurity(
  3211. IN PCTSTR pszSetupInf,
  3212. IN PCTSTR pszWindowsFolder,
  3213. IN BOOL bIsDC
  3214. )
  3215. /*
  3216. Routine Description:
  3217. This routine updates the exisitng setup security.inf or DC security.inf
  3218. (depends on if the code runs on a domain controler) based on the information
  3219. in the passed in security template.
  3220. All areas except file security, registry key security and services security
  3221. are "merged" but sections for file and registry keys are only taken from the
  3222. new security template file, because in setup upgrade,
  3223. all system files/keys/services are re-ACL'ed properly.
  3224. Note, this routine should only be called when ugpraded from W2K.
  3225. Arguments:
  3226. pszSetupInf - the full path name of the temporary setup security template exported from system db
  3227. pszWindowsFolder - the windows root path
  3228. bIsDC - TRUE - this is a domain controller
  3229. Return Value:
  3230. SCE error
  3231. */
  3232. {
  3233. TCHAR szTempName[MAX_PATH + 51] = {0};
  3234. TCHAR szNewTemplateName[MAX_PATH + 51] = {0};
  3235. PVOID hProfile = NULL;
  3236. PSCE_PROFILE_INFO pSetupSecurity = NULL;
  3237. SCESTATUS rcSce = SCESTATUS_SUCCESS;
  3238. //
  3239. // validate parameters
  3240. //
  3241. if(!pszSetupInf || !pszWindowsFolder){
  3242. return SCESTATUS_INVALID_PARAMETER;
  3243. }
  3244. //
  3245. // find which template to update
  3246. //
  3247. wcscpy(szTempName, pszWindowsFolder);
  3248. if(bIsDC){
  3249. //
  3250. // if DC, update DC Security.inf
  3251. //
  3252. wcscat(szTempName, TEXT("\\security\\templates\\DC security.inf"));
  3253. } else {
  3254. //
  3255. // if not DC, update Setup Security.inf
  3256. //
  3257. wcscat(szTempName, TEXT("\\security\\templates\\setup security.inf"));
  3258. }
  3259. //
  3260. // first copy the template to a temp scratch file
  3261. //
  3262. wcscpy(szNewTemplateName, pszWindowsFolder);
  3263. wcscat(szNewTemplateName, TEXT("\\security\\NewSecurity.inf"));
  3264. if(!CopyFile(szTempName, szNewTemplateName, FALSE)){
  3265. rcSce = ScepDosErrorToSceStatus(GetLastError());
  3266. goto ExitHandler;
  3267. }
  3268. //
  3269. // Second, Read all the information of what we secured during
  3270. // setup
  3271. //
  3272. //
  3273. // Open the template that was exported from the database table
  3274. // we used to secure the system during setup
  3275. //
  3276. rcSce = SceOpenProfile(pszSetupInf,
  3277. SCE_INF_FORMAT,
  3278. &hProfile
  3279. );
  3280. if(SCESTATUS_SUCCESS != rcSce){
  3281. goto ExitHandler;
  3282. }
  3283. //
  3284. // read out all the information
  3285. //
  3286. rcSce = SceGetSecurityProfileInfo(hProfile,
  3287. SCE_ENGINE_SCP,
  3288. AREA_ALL,
  3289. &pSetupSecurity,
  3290. NULL
  3291. );
  3292. if(SCESTATUS_SUCCESS != rcSce){
  3293. goto ExitHandler;
  3294. }
  3295. //
  3296. // then append all section except Files, Registry and services sections
  3297. // to the scratch template ("setup security" or "DC security" copy)
  3298. //
  3299. rcSce = SceAppendSecurityProfileInfo(szNewTemplateName,
  3300. AREA_SECURITY_POLICY |
  3301. AREA_GROUP_MEMBERSHIP |
  3302. AREA_PRIVILEGES,
  3303. pSetupSecurity,
  3304. NULL
  3305. );
  3306. if(SCESTATUS_SUCCESS != rcSce){
  3307. goto ExitHandler;
  3308. }
  3309. //
  3310. // then overwrite the files, registry and services sections.
  3311. // because all the information we need is in the upgrade template
  3312. // and there is not need to merge those with the old info.
  3313. //
  3314. rcSce = SceWriteSecurityProfileInfo(szNewTemplateName,
  3315. AREA_SYSTEM_SERVICE |
  3316. AREA_FILE_SECURITY |
  3317. AREA_REGISTRY_SECURITY,
  3318. pSetupSecurity,
  3319. NULL
  3320. );
  3321. if(SCESTATUS_SUCCESS != rcSce){
  3322. goto ExitHandler;
  3323. }
  3324. //
  3325. // if all that succeeded then copy back the scartch template
  3326. // to its original template
  3327. //
  3328. if(!CopyFile(szNewTemplateName, pszSetupInf, FALSE)){
  3329. rcSce = ScepDosErrorToSceStatus(GetLastError());
  3330. goto ExitHandler;
  3331. }
  3332. ExitHandler:
  3333. //
  3334. // clean up
  3335. //
  3336. if(hProfile){
  3337. SceCloseProfile(&hProfile);
  3338. }
  3339. if(pSetupSecurity){
  3340. SceFreeProfileMemory(pSetupSecurity);
  3341. }
  3342. DeleteFile(szNewTemplateName);
  3343. return ScepSceStatusToDosError(rcSce);
  3344. }
  3345. DWORD
  3346. WINAPI
  3347. SceSetupConfigureServices(
  3348. IN UINT SetupProductType
  3349. )
  3350. {
  3351. TCHAR Buffer[MAX_PATH+1];
  3352. DWORD rc32 = SCESTATUS_SUCCESS;
  3353. TCHAR szNewName[MAX_PATH+51];
  3354. Buffer[0] = L'\0';
  3355. GetSystemWindowsDirectory(Buffer, MAX_PATH);
  3356. Buffer[MAX_PATH] = L'\0';
  3357. szNewName[0] = L'\0';
  3358. wcscpy(szNewName, Buffer);
  3359. wcscat(szNewName, L"\\security\\logs\\backup.log\0");
  3360. //
  3361. // if I am in setup, query the security policy/user rights for any
  3362. // policy changes within setup (such as NT4 PDC upgrade where the policy
  3363. // filter will fail to save the change)
  3364. //
  3365. DWORD dwInSetup=0;
  3366. DWORD dwUpgraded=0;
  3367. ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
  3368. TEXT("System\\Setup"),
  3369. TEXT("SystemSetupInProgress"),
  3370. &dwInSetup
  3371. );
  3372. if ( dwInSetup ) {
  3373. //
  3374. // in GUI setup, snapshot the system security/user rights
  3375. // query the upgrade flag, only query the system (again) when
  3376. // it's upgraded, because for the case of NT4 PDC upgrade to NT5
  3377. // any back office apps installed in GUI setup (user rights) won't
  3378. // get saved to the GPO storage correctly (ProductType is wrong)
  3379. //
  3380. ScepRegQueryIntValue(
  3381. HKEY_LOCAL_MACHINE,
  3382. SCE_ROOT_PATH,
  3383. TEXT("SetupUpgraded"),
  3384. (DWORD *)&dwUpgraded
  3385. );
  3386. if ( !dwUpgraded ) {
  3387. //
  3388. // configure service area
  3389. //
  3390. rc32 = ScepSystemSecurityInSetup(
  3391. (SetupProductType == PRODUCT_WORKSTATION) ? L"defltwk.inf" : L"defltsv.inf",
  3392. szNewName,
  3393. AREA_SYSTEM_SERVICE,
  3394. SCESETUP_BACKUP_SECURITY | SCESETUP_BIND_NO_AUTH,
  3395. NULL,
  3396. NULL
  3397. );
  3398. }
  3399. }
  3400. return(rc32);
  3401. }
  3402. BOOL
  3403. pCreateDefaultGPOsInSysvol(
  3404. IN LPTSTR DomainDnsName,
  3405. IN LPTSTR szSysvolPath,
  3406. IN DWORD Options,
  3407. IN LPTSTR LogFileName
  3408. )
  3409. /*++
  3410. Routine Description:
  3411. Creates the default domain-wide account policy object and the default
  3412. policy object for local policies in sysvol.
  3413. The GUID to use is queried from registry.
  3414. Arguments:
  3415. DomainDnsName - the new domain's DNS name, e.g., JINDOM4.ntdev.microsoft.com
  3416. Options - the promotion options
  3417. LogFileName - the log file for debug info
  3418. Return:
  3419. WIN32 error
  3420. --*/
  3421. {
  3422. /*
  3423. //
  3424. // get sysvol share location
  3425. //
  3426. TCHAR szSysvolPath[MAX_PATH+1];
  3427. szSysvolPath[0] = L'\0';
  3428. GetEnvironmentVariable( L"SYSVOL",
  3429. szSysvolPath,
  3430. MAX_PATH);
  3431. */
  3432. //
  3433. // create \\?\%sysvol%\sysvol\<DnsName>\Policies directory
  3434. // the \\?\ is for the case of longer than MAX_PATH chars
  3435. //
  3436. DWORD Len = 4 + wcslen(szSysvolPath) + wcslen(TEXT("\\sysvol\\Policies\\")) +
  3437. wcslen(DomainDnsName);
  3438. PWSTR pszPoliciesPath = (PWSTR)ScepAlloc(LPTR, (Len+wcslen(TEXT("\\{}\\MACHINE"))+
  3439. STR_GUID_LEN+1)*sizeof(WCHAR));
  3440. if ( !pszPoliciesPath ) {
  3441. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3442. return FALSE;
  3443. }
  3444. swprintf(pszPoliciesPath, L"\\\\?\\%s\\sysvol\\%s\\Policies\0", szSysvolPath, DomainDnsName);
  3445. DWORD Win32rc = ScepSceStatusToDosError(
  3446. ScepCreateDirectory(
  3447. pszPoliciesPath,
  3448. TRUE,
  3449. NULL
  3450. ));
  3451. if ( ERROR_SUCCESS == Win32rc ) {
  3452. //
  3453. // create sub directory for the first GPO GUID1 and machine, user, GPT.ini
  3454. //
  3455. if ( pCreateSysvolContainerForGPO(STR_DEFAULT_DOMAIN_GPO_GUID,
  3456. pszPoliciesPath,
  3457. Len) ) {
  3458. //
  3459. // when it's returned success from the previous
  3460. // pszPoliciesPath is already changed to the machine's root
  3461. // with the guid info.
  3462. //
  3463. if ( pCreateOneGroupPolicyObject(
  3464. pszPoliciesPath,
  3465. TRUE, // domain level
  3466. LogFileName) ) {
  3467. //
  3468. // create sub directory for the second GPO
  3469. //
  3470. if ( pCreateSysvolContainerForGPO(STR_DEFAULT_DOMAIN_CONTROLLER_GPO_GUID,
  3471. pszPoliciesPath,
  3472. Len) ) {
  3473. //
  3474. // when it's returned success from the previous
  3475. // pszPoliciesPath is already changed to the machine's root
  3476. // with the guid info.
  3477. //
  3478. if ( pCreateOneGroupPolicyObject(
  3479. pszPoliciesPath,
  3480. FALSE, // not domain level
  3481. LogFileName) ) {
  3482. //
  3483. // log a entry to the log
  3484. //
  3485. LogEventAndReport(MyModuleHandle,
  3486. LogFileName,
  3487. 0,
  3488. 0,
  3489. IDS_SUCCESS_DEFAULT_GPO,
  3490. L"in sysvol"
  3491. );
  3492. } else {
  3493. Win32rc = GetLastError();
  3494. }
  3495. } else {
  3496. Win32rc = GetLastError();
  3497. LogEventAndReport(MyModuleHandle,
  3498. LogFileName,
  3499. STATUS_SEVERITY_ERROR,
  3500. SCEEVENT_ERROR_CREATE_GPO,
  3501. IDS_ERROR_CREATE_DIRECTORY,
  3502. Win32rc,
  3503. STR_DEFAULT_DOMAIN_CONTROLLER_GPO_GUID
  3504. );
  3505. }
  3506. } else {
  3507. Win32rc = GetLastError();
  3508. }
  3509. } else {
  3510. Win32rc = GetLastError();
  3511. LogEventAndReport(MyModuleHandle,
  3512. LogFileName,
  3513. STATUS_SEVERITY_ERROR,
  3514. SCEEVENT_ERROR_CREATE_GPO,
  3515. IDS_ERROR_CREATE_DIRECTORY,
  3516. Win32rc,
  3517. STR_DEFAULT_DOMAIN_GPO_GUID
  3518. );
  3519. }
  3520. } else {
  3521. LogEventAndReport(MyModuleHandle,
  3522. LogFileName,
  3523. STATUS_SEVERITY_ERROR,
  3524. SCEEVENT_ERROR_CREATE_GPO,
  3525. IDS_ERROR_CREATE_DIRECTORY,
  3526. Win32rc,
  3527. pszPoliciesPath
  3528. );
  3529. }
  3530. ScepFree(pszPoliciesPath);
  3531. SetLastError( Win32rc );
  3532. //
  3533. // if this function fails, it will fail DCPROMO and the sysvol directory
  3534. // should be cleaned up by dcpromo/ntfrs
  3535. //
  3536. return ( ERROR_SUCCESS == Win32rc );
  3537. }
  3538. BOOL
  3539. pCreateSysvolContainerForGPO(
  3540. IN LPCTSTR strGuid,
  3541. IN LPTSTR szPath,
  3542. IN DWORD dwStart
  3543. )
  3544. {
  3545. swprintf(szPath+dwStart, L"\\{%s}\\USER", strGuid);
  3546. DWORD Win32rc = ScepSceStatusToDosError(
  3547. ScepCreateDirectory(
  3548. szPath,
  3549. TRUE,
  3550. NULL
  3551. ));
  3552. if ( ERROR_SUCCESS == Win32rc ) {
  3553. //
  3554. // the directory for the GUID is created
  3555. // now create the GPT.INI
  3556. //
  3557. swprintf(szPath+dwStart, L"\\{%s}\\GPT.INI", strGuid);
  3558. WritePrivateProfileString (TEXT("General"), TEXT("Version"), TEXT("1"),
  3559. szPath); // does it work with prefix "\\?\" ?
  3560. //
  3561. // create the machine directory
  3562. // since all the parent directories are already created by the call
  3563. // to create USER directory, there is no need to loop again
  3564. // call CreateDirectory directly
  3565. //
  3566. swprintf(szPath+dwStart, L"\\{%s}\\MACHINE", strGuid);
  3567. SECURITY_ATTRIBUTES sa;
  3568. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  3569. sa.lpSecurityDescriptor = NULL;
  3570. sa.bInheritHandle = FALSE;
  3571. if ( CreateDirectory(
  3572. szPath,
  3573. &sa
  3574. ) == FALSE ) {
  3575. if ( GetLastError() != ERROR_ALREADY_EXISTS ) {
  3576. Win32rc = GetLastError();
  3577. }
  3578. }
  3579. }
  3580. SetLastError(Win32rc);
  3581. return (ERROR_SUCCESS == Win32rc);
  3582. }
  3583. BOOL
  3584. pCreateOneGroupPolicyObject(
  3585. IN PWSTR pszGPOSysPath,
  3586. IN BOOL bDomainLevel,
  3587. IN PWSTR LogFileName
  3588. )
  3589. /*++
  3590. Routine Description:
  3591. Creates a group policy object in sysvol.
  3592. Arguments:
  3593. pszGPOSysPath- the GPO's sysvol path (up to root of machine)
  3594. bDomainLevel - create the object for domain level if TRUE, otherwise,
  3595. create the GPO for "domain controllers" OU
  3596. LogFileName - the dcpromo log file to track info
  3597. Return:
  3598. TRUE - success
  3599. FALSE - fail, use GetLastError()
  3600. --*/
  3601. {
  3602. //
  3603. // create the default domain policy object
  3604. //
  3605. LPTSTR SceTemplateName = (LPTSTR) LocalAlloc(LPTR,(lstrlen(pszGPOSysPath)+
  3606. lstrlen(GPTSCE_TEMPLATE)+2)*sizeof(TCHAR));
  3607. DWORD Win32rc;
  3608. if (SceTemplateName) {
  3609. //
  3610. // build the template path first
  3611. //
  3612. lstrcpy(SceTemplateName,pszGPOSysPath);
  3613. lstrcat(SceTemplateName,L"\\");
  3614. lstrcat(SceTemplateName, GPTSCE_TEMPLATE);
  3615. //
  3616. // Create the template directory if there isn't one already
  3617. //
  3618. Win32rc = ScepSceStatusToDosError(
  3619. ScepCreateDirectory(
  3620. SceTemplateName,
  3621. FALSE,
  3622. NULL
  3623. ));
  3624. if ( ERROR_SUCCESS == Win32rc ) {
  3625. TCHAR pszGPOTempName[MAX_PATH+51];
  3626. pszGPOTempName[0] = L'\0';
  3627. GetSystemWindowsDirectory(pszGPOTempName, MAX_PATH);
  3628. pszGPOTempName[MAX_PATH] = L'\0';
  3629. if ( bDomainLevel ) {
  3630. //
  3631. // create the default domain GPO
  3632. // copy template from %windir%\security\FirstDGPO.inf
  3633. //
  3634. wcscat(pszGPOTempName, L"\\security\\FirstDGPO.inf\0");
  3635. } else {
  3636. //
  3637. // create the default GPO for "domain controllers" OU
  3638. // copy template from %windir%\security\FirstOGPO.inf
  3639. //
  3640. wcscat(pszGPOTempName, L"\\security\\FirstOGPO.inf\0");
  3641. }
  3642. DWORD rc=ERROR_SUCCESS;
  3643. HINF hInf=NULL;
  3644. AREA_INFORMATION Area = AREA_SECURITY_POLICY | AREA_PRIVILEGES;
  3645. PSCE_PROFILE_INFO pSceInfo=NULL;
  3646. rc = SceInfpOpenProfile(
  3647. pszGPOTempName,
  3648. &hInf
  3649. );
  3650. if ( SCESTATUS_SUCCESS == rc ) {
  3651. //
  3652. // do not do sid->name->sid translation in DCPromo (bug 462994)
  3653. //
  3654. gbClientInDcPromo = TRUE;
  3655. //
  3656. // load informatin from the template
  3657. //
  3658. rc = SceInfpGetSecurityProfileInfo(
  3659. hInf,
  3660. Area,
  3661. &pSceInfo,
  3662. NULL
  3663. );
  3664. gbClientInDcPromo = FALSE;
  3665. if ( SCESTATUS_SUCCESS != rc ) {
  3666. LogEventAndReport(MyModuleHandle,
  3667. LogFileName,
  3668. STATUS_SEVERITY_ERROR,
  3669. SCEEVENT_ERROR_CREATE_GPO,
  3670. IDS_ERROR_GETGPO_FILE_PATH,
  3671. rc,
  3672. pszGPOTempName
  3673. );
  3674. }
  3675. SceInfpCloseProfile(hInf);
  3676. } else {
  3677. LogEventAndReport(MyModuleHandle,
  3678. LogFileName,
  3679. STATUS_SEVERITY_ERROR,
  3680. SCEEVENT_ERROR_CREATE_GPO,
  3681. IDS_ERROR_GETGPO_FILE_PATH,
  3682. rc,
  3683. pszGPOTempName
  3684. );
  3685. }
  3686. if ( ERROR_SUCCESS == rc && pSceInfo ) {
  3687. //
  3688. // Write to GPO instead of copy, this way the GPO will be unicode.
  3689. //
  3690. //??? pSceInfo->Type = SCE_ENGINE_SMP;
  3691. rc = SceWriteSecurityProfileInfo(SceTemplateName,
  3692. Area,
  3693. (PSCE_PROFILE_INFO)pSceInfo,
  3694. NULL
  3695. );
  3696. if ( SCESTATUS_SUCCESS != rc ) {
  3697. LogEventAndReport(MyModuleHandle,
  3698. LogFileName,
  3699. STATUS_SEVERITY_ERROR,
  3700. SCEEVENT_ERROR_CREATE_GPO,
  3701. IDS_ERROR_GETGPO_FILE_PATH,
  3702. rc,
  3703. pszGPOTempName
  3704. );
  3705. }
  3706. }
  3707. if ( pSceInfo != NULL ) {
  3708. SceFreeProfileMemory(pSceInfo);
  3709. }
  3710. #if 0
  3711. if ( !CopyFile( pszGPOTempName,
  3712. SceTemplateName,
  3713. FALSE ) ) {
  3714. Win32rc = GetLastError();
  3715. LogEventAndReport(MyModuleHandle,
  3716. LogFileName,
  3717. STATUS_SEVERITY_ERROR,
  3718. SCEEVENT_ERROR_CREATE_GPO,
  3719. IDS_ERROR_COPY_TEMPLATE,
  3720. Win32rc,
  3721. SceTemplateName
  3722. );
  3723. }
  3724. #endif
  3725. DeleteFile(pszGPOTempName);
  3726. } else {
  3727. LogEventAndReport(MyModuleHandle,
  3728. LogFileName,
  3729. STATUS_SEVERITY_ERROR,
  3730. SCEEVENT_ERROR_CREATE_GPO,
  3731. IDS_ERROR_CREATE_DIRECTORY,
  3732. Win32rc,
  3733. SceTemplateName
  3734. );
  3735. }
  3736. LocalFree(SceTemplateName);
  3737. } else {
  3738. Win32rc = ERROR_NOT_ENOUGH_MEMORY;
  3739. LogEventAndReport(
  3740. MyModuleHandle,
  3741. LogFileName,
  3742. STATUS_SEVERITY_ERROR,
  3743. SCEEVENT_ERROR_CREATE_GPO,
  3744. IDS_ERROR_NO_MEMORY
  3745. );
  3746. }
  3747. SetLastError(Win32rc);
  3748. return ( ERROR_SUCCESS == Win32rc);
  3749. }
  3750. //NT_PRODUCT_TYPE
  3751. DWORD
  3752. WhichNTProduct()
  3753. {
  3754. HKEY hKey;
  3755. DWORD dwBufLen=32;
  3756. TCHAR szProductType[32];
  3757. LONG lRet;
  3758. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  3759. TEXT("SYSTEM\\CurrentControlSet\\Control\\ProductOptions"),
  3760. 0,
  3761. KEY_QUERY_VALUE,
  3762. &hKey) != ERROR_SUCCESS) {
  3763. // return Unknown
  3764. return PRODUCT_UNKNOWN;
  3765. }
  3766. lRet = RegQueryValueEx(hKey,
  3767. TEXT("ProductType"),
  3768. NULL,
  3769. NULL,
  3770. (LPBYTE)szProductType,
  3771. &dwBufLen);
  3772. RegCloseKey(hKey);
  3773. if(lRet != ERROR_SUCCESS) {
  3774. // return Unknown
  3775. return PRODUCT_UNKNOWN;
  3776. }
  3777. // check product options, in order of likelihood
  3778. if (lstrcmpi(TEXT("WINNT"), szProductType) == 0) {
  3779. return NtProductWinNt;
  3780. }
  3781. if (lstrcmpi(TEXT("SERVERNT"), szProductType) == 0) {
  3782. return NtProductServer;
  3783. }
  3784. if (lstrcmpi(TEXT("LANMANNT"), szProductType) == 0) {
  3785. return NtProductLanManNt;
  3786. }
  3787. // return Unknown
  3788. return PRODUCT_UNKNOWN;
  3789. }
  3790. BOOL
  3791. ScepAddAuthUserToLocalGroup()
  3792. {
  3793. //
  3794. // Attempt to add Authenticated Users and Interactive back into Users group.
  3795. //
  3796. DWORD rc1;
  3797. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  3798. PSID AuthenticatedUsers = NULL;
  3799. PSID Interactive = NULL;
  3800. WCHAR Name[36];
  3801. BOOL b;
  3802. LOCALGROUP_MEMBERS_INFO_0 lgrmi0[2];
  3803. HMODULE hMod = GetModuleHandle(L"scecli.dll");
  3804. LoadString(hMod, IDS_NAME_USERS, Name, 36);
  3805. b = AllocateAndInitializeSid (
  3806. &NtAuthority,
  3807. 1,
  3808. SECURITY_AUTHENTICATED_USER_RID,
  3809. 0, 0, 0, 0, 0, 0, 0,
  3810. &AuthenticatedUsers
  3811. );
  3812. if (b) {
  3813. lgrmi0[0].lgrmi0_sid = AuthenticatedUsers;
  3814. b = AllocateAndInitializeSid (
  3815. &NtAuthority,
  3816. 1,
  3817. SECURITY_INTERACTIVE_RID,
  3818. 0, 0, 0, 0, 0, 0, 0,
  3819. &Interactive
  3820. );
  3821. if (b) {
  3822. lgrmi0[1].lgrmi0_sid = Interactive;
  3823. rc1 = NetLocalGroupAddMembers(
  3824. NULL,
  3825. Name,
  3826. 0,
  3827. (PBYTE) lgrmi0,
  3828. 2
  3829. );
  3830. }
  3831. else {
  3832. if ( AuthenticatedUsers ) {
  3833. FreeSid( AuthenticatedUsers );
  3834. }
  3835. return FALSE;
  3836. }
  3837. if ( AuthenticatedUsers ) {
  3838. FreeSid( AuthenticatedUsers );
  3839. }
  3840. if ( Interactive ) {
  3841. FreeSid( Interactive );
  3842. }
  3843. if ( rc1 != ERROR_SUCCESS && rc1 != ERROR_MEMBER_IN_ALIAS ) {
  3844. return FALSE;
  3845. }
  3846. }
  3847. else {
  3848. return FALSE;
  3849. }
  3850. return TRUE;
  3851. }
  3852. DWORD
  3853. SceSysPrep()
  3854. {
  3855. SCESTATUS rc=0;
  3856. handle_t binding_h=NULL;
  3857. NTSTATUS NtStatus;
  3858. //
  3859. // open system database
  3860. //
  3861. rc = ScepSetupOpenSecurityDatabase(TRUE);
  3862. rc = ScepSceStatusToDosError(rc);
  3863. if ( ERROR_SUCCESS == rc ) {
  3864. RpcTryExcept {
  3865. // reset policy
  3866. // all tables
  3867. rc = SceRpcSetupResetLocalPolicy(
  3868. (PVOID)hSceSetupHandle,
  3869. AREA_ALL,
  3870. NULL,
  3871. SCE_RESET_POLICY_SYSPREP
  3872. );
  3873. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  3874. //
  3875. // get exception code (DWORD)
  3876. //
  3877. rc = RpcExceptionCode();
  3878. } RpcEndExcept;
  3879. //
  3880. // close the database
  3881. //
  3882. ScepSetupCloseSecurityDatabase();
  3883. }
  3884. HKEY hKey;
  3885. DWORD Interval;
  3886. DWORD RegType;
  3887. DWORD DataSize;
  3888. if ( ERROR_SUCCESS == rc ) {
  3889. //
  3890. // update local policy version #
  3891. // so policy will be propagated at reboot
  3892. //
  3893. ScepEnforcePolicyPropagation();
  3894. }
  3895. //
  3896. // re-register seclogon.dll to recreate EFS recovery policy
  3897. // at first logon
  3898. //
  3899. HINSTANCE hNotifyDll = LoadLibrary(TEXT("sclgntfy.dll"));
  3900. if ( hNotifyDll) {
  3901. PFREGISTERSERVER pfRegisterServer = (PFREGISTERSERVER)GetProcAddress(
  3902. hNotifyDll,
  3903. "DllRegisterServer");
  3904. if ( pfRegisterServer ) {
  3905. //
  3906. // do not care errors - shouldn't fail
  3907. //
  3908. (void) (*pfRegisterServer)();
  3909. }
  3910. FreeLibrary(hNotifyDll);
  3911. }
  3912. if(( rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  3913. EFS_NOTIFY_PATH,
  3914. 0,
  3915. MAXIMUM_ALLOWED,
  3916. &hKey
  3917. )) == ERROR_SUCCESS ) {
  3918. //
  3919. // set a flag to registry
  3920. // this shouldn't fail since admin logon
  3921. //
  3922. Interval = 1;
  3923. rc = RegSetValueEx( hKey,
  3924. TEXT("SystemCloned"),
  3925. 0,
  3926. REG_DWORD,
  3927. (BYTE *)&Interval,
  3928. 4
  3929. );
  3930. RegCloseKey( hKey );
  3931. }
  3932. return(rc);
  3933. }
  3934. DWORD ScepCompareDaclWithStringSD(
  3935. IN PCWSTR pcwszSD,
  3936. IN PACL pDacl,
  3937. OUT PBOOL pbDifferent)
  3938. {
  3939. DWORD dwRet = ERROR_SUCCESS;
  3940. BOOL bDaclPresent, bDaclDefaulted;
  3941. PSECURITY_DESCRIPTOR pSD = NULL;
  3942. PACL pDaclFromSD = NULL;
  3943. if ( !ConvertStringSecurityDescriptorToSecurityDescriptor(
  3944. pcwszSD,
  3945. SDDL_REVISION_1,
  3946. &pSD,
  3947. NULL) ) {
  3948. dwRet = GetLastError();
  3949. }
  3950. if ( ERROR_SUCCESS == dwRet ) {
  3951. if ( !GetSecurityDescriptorDacl(
  3952. pSD,
  3953. &bDaclPresent,
  3954. &pDaclFromSD,
  3955. &bDaclDefaulted) ) {
  3956. dwRet = GetLastError();
  3957. }
  3958. }
  3959. if ( ERROR_SUCCESS == dwRet ) {
  3960. dwRet = ScepCompareExplicitAcl(
  3961. SE_FILE_OBJECT,
  3962. TRUE, // IsContainer
  3963. pDaclFromSD,
  3964. pDacl,
  3965. pbDifferent);
  3966. }
  3967. if ( pSD )
  3968. LocalFree(pSD);
  3969. return dwRet;
  3970. }
  3971. DWORD
  3972. WINAPI
  3973. SceSetupRootSecurity()
  3974. /*
  3975. Description:
  3976. This function should be called in GUI setup after system security is
  3977. configured (SceSetupSystemSecurityByName). The function calls to NTMARTA
  3978. API to set security on the root of boot partition (where Windows is installed).
  3979. This task will take quite long time depending on the size of the drive.
  3980. Therefore, setup should call this function in a asynchronous thread.
  3981. This function will NOT set security on the root drive if one of the following
  3982. conditions is met:
  3983. 1) FAT partition
  3984. 2) Security on the root drive was modified by user in a previous install.
  3985. This is determined by comparing the security on the root drive to the
  3986. default security from NTFS format, NTFS convert tool on both NT4 and
  3987. Windows 2000 systems.
  3988. */
  3989. {
  3990. DWORD rc=NO_ERROR;
  3991. WCHAR szRootDir[MAX_PATH+1];
  3992. WCHAR szSetupInfFile[MAX_PATH+1];
  3993. WCHAR LogFileName[MAX_PATH+51];
  3994. UINT DriveType;
  3995. DWORD FileSystemFlags;
  3996. //
  3997. // get the time stamp
  3998. //
  3999. TCHAR pvBuffer[100];
  4000. pvBuffer[0] = L'\0';
  4001. ScepGetTimeStampString(pvBuffer);
  4002. szRootDir[0] = L'\0';
  4003. //
  4004. // get the root drive of Windows directory
  4005. //
  4006. if ( GetSystemWindowsDirectory( szRootDir, MAX_PATH ) == 0 ) {
  4007. return(GetLastError());
  4008. }
  4009. szRootDir[MAX_PATH] = L'\0';
  4010. wcscpy(LogFileName, szRootDir);
  4011. wcscat(LogFileName, L"\\security\\logs\\SceRoot.log");
  4012. //
  4013. // attempt to write root SDDL so that it is useful for FAT->NTFS conversion
  4014. // if default is different from hardcoded value, it will be overwritten later...
  4015. //
  4016. //
  4017. // insert the root security SDDL into %windir%\security\templates\setup security.inf
  4018. // this will be useful for the new API which implements convert behavior.
  4019. //
  4020. wcscpy(szSetupInfFile, szRootDir);
  4021. wcscat(szSetupInfFile, L"\\security\\templates\\setup security.inf");
  4022. // the first two letters are X:
  4023. szRootDir[2] = L'\\';
  4024. szRootDir[3] = L'\0';
  4025. //
  4026. // independent of future errors/file systemtypr etc., attempt to
  4027. // write default root acl to %windir%\security\templates\setup security.inf
  4028. // used in FAT->NTFS convert
  4029. //
  4030. PWSTR pszDefltInfStringToWrite = NULL;
  4031. DWORD rcDefltRootBackup = ERROR_SUCCESS;
  4032. rcDefltRootBackup = ScepBreakSDDLToMultiFields(
  4033. szRootDir,
  4034. SDDLRoot,
  4035. sizeof(SDDLRoot)+1,
  4036. 0,
  4037. &pszDefltInfStringToWrite
  4038. );
  4039. if ( rcDefltRootBackup == ERROR_SUCCESS && pszDefltInfStringToWrite) {
  4040. if ( !WritePrivateProfileString(szFileSecurity, L"0", pszDefltInfStringToWrite, szSetupInfFile) ) {
  4041. LogEventAndReport(MyModuleHandle,
  4042. (wchar_t *)LogFileName,
  4043. 0,
  4044. 0,
  4045. IDS_ROOT_ERROR_INFWRITE,
  4046. GetLastError(),
  4047. SDDLRoot
  4048. );
  4049. }
  4050. ScepFree(pszDefltInfStringToWrite);
  4051. }
  4052. else {
  4053. LogEventAndReport(MyModuleHandle,
  4054. (wchar_t *)LogFileName,
  4055. 0,
  4056. 0,
  4057. IDS_ROOT_ERROR_INFWRITE,
  4058. rcDefltRootBackup,
  4059. SDDLRoot
  4060. );
  4061. }
  4062. //
  4063. // log the time stamp
  4064. //
  4065. if ( pvBuffer[0] != L'\0' ) {
  4066. LogEventAndReport(MyModuleHandle,
  4067. (wchar_t *)LogFileName,
  4068. 0,
  4069. 0,
  4070. 0,
  4071. pvBuffer
  4072. );
  4073. }
  4074. //
  4075. // detect if the partition is FAT
  4076. //
  4077. DriveType = GetDriveType(szRootDir);
  4078. if ( DriveType == DRIVE_FIXED ||
  4079. DriveType == DRIVE_RAMDISK ) {
  4080. if ( GetVolumeInformation(szRootDir,
  4081. NULL,
  4082. 0,
  4083. NULL,
  4084. NULL,
  4085. &FileSystemFlags,
  4086. NULL,
  4087. 0
  4088. ) == TRUE ) {
  4089. if ( !(FileSystemFlags & FS_PERSISTENT_ACLS) ) {
  4090. //
  4091. // only set security on NTFS partition
  4092. //
  4093. LogEventAndReport(MyModuleHandle,
  4094. (wchar_t *)LogFileName,
  4095. 0,
  4096. 0,
  4097. IDS_ROOT_NON_NTFS,
  4098. szRootDir
  4099. );
  4100. return(rc);
  4101. }
  4102. } else {
  4103. //
  4104. // something is wrong
  4105. //
  4106. rc = GetLastError();
  4107. LogEventAndReport(MyModuleHandle,
  4108. (wchar_t *)LogFileName,
  4109. 0,
  4110. 0,
  4111. IDS_ROOT_ERROR_QUERY_VOLUME,
  4112. rc,
  4113. szRootDir
  4114. );
  4115. return rc;
  4116. }
  4117. } else {
  4118. //
  4119. // do not set security on remote drives
  4120. //
  4121. LogEventAndReport(MyModuleHandle,
  4122. (wchar_t *)LogFileName,
  4123. 0,
  4124. 0,
  4125. IDS_ROOT_NOT_FIXED_VOLUME,
  4126. szRootDir
  4127. );
  4128. return(rc);
  4129. }
  4130. PSECURITY_DESCRIPTOR pSDSet=NULL, pSDOld=NULL;
  4131. DWORD dwSize=0;
  4132. SECURITY_INFORMATION SeInfo=0;
  4133. PACL pDacl=NULL;
  4134. ACCESS_ALLOWED_ACE *pAce=NULL;
  4135. SID_IDENTIFIER_AUTHORITY Authority=SECURITY_WORLD_SID_AUTHORITY;
  4136. PSID pSid;
  4137. BYTE SidEveryone[20];
  4138. BOOLEAN tFlag;
  4139. BOOLEAN aclPresent;
  4140. SECURITY_DESCRIPTOR_CONTROL Control=0;
  4141. ULONG Revision;
  4142. NTSTATUS NtStatus;
  4143. BOOL bDefault;
  4144. LogEventAndReport(MyModuleHandle,
  4145. (wchar_t *)LogFileName,
  4146. 0,
  4147. 0,
  4148. IDS_ROOT_NTFS_VOLUME,
  4149. szRootDir
  4150. );
  4151. //
  4152. // It's NTFS volume. Let's convert the security descriptor
  4153. //
  4154. rc = ConvertTextSecurityDescriptor (SDDLRoot,
  4155. &pSDSet,
  4156. &dwSize,
  4157. &SeInfo
  4158. );
  4159. if ( rc != NO_ERROR ) {
  4160. LogEventAndReport(MyModuleHandle,
  4161. (wchar_t *)LogFileName,
  4162. 0,
  4163. 0,
  4164. IDS_ROOT_ERROR_CONVERT,
  4165. rc,
  4166. SDDLRoot
  4167. );
  4168. return(rc);
  4169. }
  4170. if ( !(SeInfo & DACL_SECURITY_INFORMATION) ) {
  4171. LogEventAndReport(MyModuleHandle,
  4172. (wchar_t *)LogFileName,
  4173. 0,
  4174. 0,
  4175. IDS_ROOT_INVALID_SDINFO,
  4176. SDDLRoot
  4177. );
  4178. LocalFree(pSDSet);
  4179. return(ERROR_INVALID_PARAMETER);
  4180. }
  4181. //
  4182. // It's NTFS volume. Now get existing security of the root drive
  4183. //
  4184. rc = GetNamedSecurityInfo(szRootDir,
  4185. SE_FILE_OBJECT,
  4186. DACL_SECURITY_INFORMATION,
  4187. NULL,
  4188. NULL,
  4189. &pDacl,
  4190. NULL,
  4191. &pSDOld
  4192. );
  4193. if ( rc == ERROR_SUCCESS && pDacl ) {
  4194. //
  4195. // Detect if permissions are the default from a clean install or upgrade (NT4 or win2k).
  4196. // There are several possible defaults to be found, DC vs srv and wks, and clean NT4 or
  4197. // win2k vs upgrades.
  4198. //
  4199. bDefault=FALSE;
  4200. if ( pDacl ) {
  4201. PCWSTR rpcwszOldDefaultDacl[] = {
  4202. SDDLOldRootDefault1, // everyone - full control (CIOI)
  4203. SDDLOldRootDefault2, // admin, system, creator/owner - full(CIOI); everyone - change(CIOI)
  4204. SDDLOldRootDefault3, // admin, system, creator/owner - full(CIOI); everyone, server op - change(CIOI)
  4205. };
  4206. int cOldDefaultDacls = ARRAYSIZE(rpcwszOldDefaultDacl);
  4207. for(int i=0; i<cOldDefaultDacls; i++)
  4208. {
  4209. BOOL bDifferent;
  4210. rc = ScepCompareDaclWithStringSD(
  4211. rpcwszOldDefaultDacl[i],
  4212. pDacl,
  4213. &bDifferent);
  4214. if ( ERROR_SUCCESS != rc)
  4215. break;
  4216. if ( FALSE == bDifferent) {
  4217. bDefault = TRUE;
  4218. break;
  4219. }
  4220. }
  4221. }
  4222. if ( ERROR_SUCCESS == rc )
  4223. {
  4224. if ( bDefault && pSDSet ) {
  4225. //
  4226. // only set security if it's default
  4227. //
  4228. RtlGetControlSecurityDescriptor (
  4229. pSDSet,
  4230. &Control,
  4231. &Revision
  4232. );
  4233. //
  4234. // Get DACL address
  4235. //
  4236. pDacl = NULL;
  4237. rc = RtlNtStatusToDosError(
  4238. RtlGetDaclSecurityDescriptor(
  4239. pSDSet,
  4240. &aclPresent,
  4241. &pDacl,
  4242. &tFlag));
  4243. if (rc == NO_ERROR && !aclPresent )
  4244. pDacl = NULL;
  4245. //
  4246. // if error occurs for this one, do not set. return
  4247. //
  4248. if ( rc == ERROR_SUCCESS ) {
  4249. //
  4250. // set permission
  4251. //
  4252. if ( Control & SE_DACL_PROTECTED ) {
  4253. SeInfo |= PROTECTED_DACL_SECURITY_INFORMATION;
  4254. }
  4255. pvBuffer[0] = L'\0';
  4256. ScepGetTimeStampString(pvBuffer);
  4257. LogEventAndReport(MyModuleHandle,
  4258. (wchar_t *)LogFileName,
  4259. 0,
  4260. 0,
  4261. IDS_ROOT_SECURITY_DEFAULT,
  4262. szRootDir,
  4263. pvBuffer
  4264. );
  4265. rc = SetNamedSecurityInfo(szRootDir,
  4266. SE_FILE_OBJECT,
  4267. SeInfo,
  4268. NULL,
  4269. NULL,
  4270. pDacl,
  4271. NULL
  4272. );
  4273. pvBuffer[0] = L'\0';
  4274. ScepGetTimeStampString(pvBuffer);
  4275. LogEventAndReport(MyModuleHandle,
  4276. (wchar_t *)LogFileName,
  4277. 0,
  4278. 0,
  4279. IDS_ROOT_MARTA_RETURN,
  4280. rc,
  4281. pvBuffer,
  4282. szRootDir
  4283. );
  4284. } else {
  4285. LogEventAndReport(MyModuleHandle,
  4286. (wchar_t *)LogFileName,
  4287. 0,
  4288. 0,
  4289. IDS_ROOT_ERROR_DACL,
  4290. rc
  4291. );
  4292. }
  4293. } else {
  4294. //
  4295. // convert the old security descriptor to text and log it
  4296. //
  4297. PWSTR pszOldSDDL=NULL;
  4298. PWSTR pszInfStringToWrite = NULL;
  4299. DWORD rcRootBackup = ERROR_SUCCESS;
  4300. ConvertSecurityDescriptorToText (
  4301. pSDOld,
  4302. DACL_SECURITY_INFORMATION,
  4303. &pszOldSDDL,
  4304. &dwSize
  4305. );
  4306. //
  4307. // also, overwrite this SDDL to %windir%\security\templates\setup security.inf
  4308. // since this is the "default" root security. This will be used later if
  4309. // SCE is invoked to do security configuration during NTFS->FAT->NTFS conversion.
  4310. //
  4311. if (pszOldSDDL) {
  4312. rcRootBackup = ScepBreakSDDLToMultiFields(
  4313. szRootDir,
  4314. pszOldSDDL,
  4315. dwSize,
  4316. 0,
  4317. &pszInfStringToWrite
  4318. );
  4319. if (rcRootBackup == ERROR_SUCCESS && pszInfStringToWrite) {
  4320. if ( !WritePrivateProfileString(szFileSecurity, L"0", pszInfStringToWrite, szSetupInfFile) ) {
  4321. LogEventAndReport(MyModuleHandle,
  4322. (wchar_t *)LogFileName,
  4323. 0,
  4324. 0,
  4325. IDS_ROOT_ERROR_INFWRITE,
  4326. GetLastError(),
  4327. pszOldSDDL
  4328. );
  4329. }
  4330. ScepFree(pszInfStringToWrite);
  4331. } else {
  4332. LogEventAndReport(MyModuleHandle,
  4333. (wchar_t *)LogFileName,
  4334. 0,
  4335. 0,
  4336. IDS_ROOT_ERROR_INFWRITE,
  4337. rcRootBackup,
  4338. pszOldSDDL
  4339. );
  4340. }
  4341. }
  4342. LogEventAndReport(MyModuleHandle,
  4343. (wchar_t *)LogFileName,
  4344. 0,
  4345. 0,
  4346. IDS_ROOT_SECURITY_MODIFIED,
  4347. szRootDir,
  4348. pszOldSDDL ? pszOldSDDL : L""
  4349. );
  4350. if ( pszOldSDDL ) {
  4351. LocalFree(pszOldSDDL);
  4352. }
  4353. }
  4354. } else {
  4355. LogEventAndReport(MyModuleHandle,
  4356. (wchar_t *)LogFileName,
  4357. 0,
  4358. 0,
  4359. IDS_ROOT_ERROR_COMPARE_SECURITY,
  4360. rc,
  4361. szRootDir
  4362. );
  4363. }
  4364. LocalFree(pSDOld);
  4365. } else {
  4366. LogEventAndReport(MyModuleHandle,
  4367. (wchar_t *)LogFileName,
  4368. 0,
  4369. 0,
  4370. IDS_ROOT_ERROR_QUERY_SECURITY,
  4371. rc,
  4372. szRootDir
  4373. );
  4374. }
  4375. LocalFree(pSDSet);
  4376. return(rc);
  4377. }
  4378. DWORD
  4379. WINAPI
  4380. SceEnforceSecurityPolicyPropagation()
  4381. {
  4382. return(ScepEnforcePolicyPropagation());
  4383. }
  4384. DWORD
  4385. WINAPI
  4386. SceConfigureConvertedFileSecurity(
  4387. IN PWSTR pszDriveName,
  4388. IN DWORD dwConvertDisposition
  4389. )
  4390. /*++
  4391. Routine Description:
  4392. Exported API called by convert.exe to configure setup style security for drives converted from FAT to NTFS.
  4393. Briefly, this API will
  4394. EITHER (dwConvertDisposition == 0)
  4395. convert the volume in question immediately (in an asynchronous thread after RPC'ing over to the server)
  4396. OR (dwConvertDisposition == 1)
  4397. will schedule a conversion to happen at the time of reboot (in an asynchronous thread during reboot).
  4398. Scheduling is done by entering pszDriveName(s) in a REG_MULTI_SZ registry value
  4399. SCE_ROOT_PATH\FatNtfsConvertedDrives.
  4400. Arguments:
  4401. pszDriveName - Name of the volume to be converted
  4402. dwConvertDisposition - 0 implies volume can be converted immediately
  4403. 1 implies volume cannot be converted immediately and is scheduled for conversion
  4404. Return:
  4405. win32 error code
  4406. --*/
  4407. {
  4408. DWORD rc = ERROR_SUCCESS;
  4409. if ( pszDriveName == NULL ||
  4410. wcslen(pszDriveName) == 0 ||
  4411. (dwConvertDisposition != 0 && dwConvertDisposition != 1) ) {
  4412. return ERROR_INVALID_PARAMETER;
  4413. }
  4414. //
  4415. // validate drive name - has to end in ":"
  4416. //
  4417. if ( pszDriveName [wcslen( pszDriveName ) - 1] != L':') {
  4418. return ERROR_INVALID_PARAMETER;
  4419. }
  4420. if (dwConvertDisposition == 0) {
  4421. //
  4422. // configure setup-style security immediately
  4423. // RPC over to scesrv
  4424. //
  4425. NTSTATUS NtStatus = NO_ERROR;
  4426. handle_t binding_h = NULL;
  4427. //
  4428. // RPC bind to the server - don't use secure RPC
  4429. //
  4430. NtStatus = ScepBindRpc(
  4431. NULL,
  4432. L"scerpc",
  4433. 0,
  4434. &binding_h
  4435. );
  4436. /*
  4437. NtStatus = ScepBindSecureRpc(
  4438. NULL,
  4439. L"scerpc",
  4440. 0,
  4441. &binding_h
  4442. );
  4443. */
  4444. if (NT_SUCCESS(NtStatus)) {
  4445. RpcTryExcept {
  4446. //
  4447. // make the RPC call
  4448. //
  4449. rc = SceRpcConfigureConvertedFileSecurityImmediately(
  4450. binding_h,
  4451. pszDriveName
  4452. );
  4453. } RpcExcept( I_RpcExceptionFilter( RpcExceptionCode()) ) {
  4454. //
  4455. // get exception code
  4456. //
  4457. rc = RpcExceptionCode();
  4458. } RpcEndExcept;
  4459. //
  4460. // Free the binding handle
  4461. //
  4462. RpcpUnbindRpc( binding_h );
  4463. } else {
  4464. rc = RtlNtStatusToDosError( NtStatus );
  4465. }
  4466. }
  4467. else if (dwConvertDisposition == 1) {
  4468. //
  4469. // schedule conversion for reboot time - i.e. enter into MULTI_SZ registry value
  4470. //
  4471. rc = ScepAppendCreateMultiSzRegValue(HKEY_LOCAL_MACHINE,
  4472. SCE_ROOT_PATH,
  4473. L"FatNtfsConvertedDrives",
  4474. pszDriveName
  4475. );
  4476. }
  4477. return rc;
  4478. }
  4479. DWORD
  4480. ScepBreakSDDLToMultiFields(
  4481. IN PWSTR pszObjName,
  4482. IN PWSTR pszSDDL,
  4483. IN DWORD dwSDDLsize,
  4484. IN BYTE ObjStatus,
  4485. OUT PWSTR *ppszAdjustedInfLine
  4486. )
  4487. /*++
  4488. Routine Description:
  4489. Inf files have a limitation w.r.t. line size - so break up SDDL if need be
  4490. Arguments:
  4491. pszObjName - name of the object
  4492. pszSDDL - SDDL string that might be velry long
  4493. dwSDDLsize - size of pszSDDL
  4494. ObjStatus - 0/1/2
  4495. ppszAdjustedInfLine - ptr to adjusted string
  4496. Return:
  4497. win32 error code
  4498. --*/
  4499. {
  4500. DWORD rc;
  4501. PWSTR Strvalue=NULL;
  4502. DWORD nFields;
  4503. DWORD *aFieldOffset=NULL;
  4504. DWORD i;
  4505. DWORD dwObjSize = 0;
  4506. if ( pszObjName == NULL ||
  4507. pszSDDL == NULL ||
  4508. ppszAdjustedInfLine == NULL )
  4509. return ERROR_INVALID_PARAMETER;
  4510. rc = SceInfpBreakTextIntoMultiFields(pszSDDL, dwSDDLsize, &nFields, &aFieldOffset);
  4511. if ( SCESTATUS_SUCCESS != rc ) {
  4512. rc = ScepSceStatusToDosError(rc);
  4513. goto Done;
  4514. }
  4515. //
  4516. // each extra field will use 3 more chars : ,"<field>"
  4517. //
  4518. dwObjSize = wcslen(pszObjName)+8 + dwSDDLsize;
  4519. if ( nFields ) {
  4520. dwObjSize += 3*nFields;
  4521. } else {
  4522. dwObjSize += 2;
  4523. }
  4524. //
  4525. // allocate the output buffer
  4526. //
  4527. Strvalue = (PWSTR)ScepAlloc(LMEM_ZEROINIT, (dwObjSize+1) * sizeof(WCHAR) );
  4528. if ( Strvalue == NULL ) {
  4529. rc = ERROR_NOT_ENOUGH_MEMORY;
  4530. goto Done;
  4531. }
  4532. //
  4533. // copy data into the buffer
  4534. //
  4535. if ( nFields == 0 || !aFieldOffset ) {
  4536. swprintf(Strvalue, L"\"%s\",%1d,\"%s\"", pszObjName, ObjStatus, pszSDDL);
  4537. } else {
  4538. //
  4539. // loop through the fields
  4540. //
  4541. swprintf(Strvalue, L"\"%s\",%1d\0", pszObjName, ObjStatus);
  4542. for ( i=0; i<nFields; i++ ) {
  4543. if ( aFieldOffset[i] < dwSDDLsize ) {
  4544. wcscat(Strvalue, L",\"");
  4545. if ( i == nFields-1 ) {
  4546. //
  4547. // the last field
  4548. //
  4549. wcscat(Strvalue, pszSDDL+aFieldOffset[i]);
  4550. } else {
  4551. wcsncat(Strvalue, pszSDDL+aFieldOffset[i],
  4552. aFieldOffset[i+1]-aFieldOffset[i]);
  4553. }
  4554. wcscat(Strvalue, L"\"");
  4555. }
  4556. }
  4557. }
  4558. *ppszAdjustedInfLine = Strvalue;
  4559. Done:
  4560. if ( aFieldOffset ) {
  4561. ScepFree(aFieldOffset);
  4562. }
  4563. return(rc);
  4564. }
  4565. #ifndef _WIN64
  4566. BOOL
  4567. GetIsWow64 (
  4568. VOID
  4569. )
  4570. /*++
  4571. Routine Description:
  4572. Determine if we're running on WOW64 or not.
  4573. Arguments:
  4574. none
  4575. Return value:
  4576. TRUE if running under WOW64 (and special Wow64 features available)
  4577. --*/
  4578. {
  4579. ULONG_PTR ul = 0;
  4580. NTSTATUS st;
  4581. //
  4582. // If this call succeeds and sets ul non-zero
  4583. // it's a 32-bit process running on Win64
  4584. //
  4585. st = NtQueryInformationProcess(NtCurrentProcess(),
  4586. ProcessWow64Information,
  4587. &ul,
  4588. sizeof(ul),
  4589. NULL);
  4590. if (NT_SUCCESS(st) && (0 != ul)) {
  4591. // 32-bit code running on Win64
  4592. return TRUE;
  4593. }
  4594. return FALSE;
  4595. }
  4596. #endif // _WIN64