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

5530 lines
152 KiB

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