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.

3198 lines
83 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. recovery.cpp
  5. Abstract:
  6. This module implements the callout from winlogon to set
  7. recovery policy.
  8. Author:
  9. Robert Reichel (RobertRe)
  10. Revision History:
  11. --*/
  12. //
  13. // Turn off lean and mean so we get wincrypt.h and winefs.h included
  14. //
  15. #undef WIN32_LEAN_AND_MEAN
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #include <nturtl.h>
  19. #include <ntlsa.h>
  20. #include <windows.h>
  21. #include <stdio.h>
  22. #include <lmcons.h>
  23. #include <cryptui.h>
  24. #include <winwlx.h>
  25. #include <malloc.h>
  26. #include <feclient.h>
  27. #include <efsstruc.h>
  28. #include <netlib.h>
  29. #include <secobj.h>
  30. #include <initguid.h>
  31. #include <gpedit.h>
  32. #include <wincrypt.h>
  33. #include <winreg.h>
  34. #include <dsrole.h>
  35. #include <winldap.h>
  36. #include <dsgetdc.h>
  37. #include <ntdsapi.h>
  38. #include "sclgntfy.hxx"
  39. #define YEARCOUNT (LONGLONG) 10000000*3600*24*365 // One Year's tick count
  40. typedef BOOL (WINAPI *PFREFRESHPOLICY)(BOOL);
  41. extern HINSTANCE g_hDllInstance;
  42. HANDLE hEventLog = NULL;
  43. TCHAR EventSourceName[] = TEXT("SclgNtfy");
  44. GUID guidExtension = { 0xb1be8d72, 0x6eac, 0x11d2, {0xa4, 0xea, 0x00, 0xc0, 0x4f, 0x79, 0xf8, 0x3a }};
  45. GUID guidRegExt = REGISTRY_EXTENSION_GUID;
  46. GUID guidSnapin = {0x53D6AB1B,0x2488,0x11d1,{0xA2,0x8C,0x00,0xC0,0x4F,0xB9,0x4F,0x17}}; // CLSID_CertificateManager
  47. //
  48. // Event handle
  49. //
  50. PTOKEN_USER
  51. GetTokenUser(
  52. HANDLE TokenHandle
  53. );
  54. BOOLEAN
  55. CreateSelfSignedRecoveryCertificate(
  56. IN BOOL bIsDC,
  57. OUT PCCERT_CONTEXT * pCertContext
  58. );
  59. BOOL
  60. EncodeAndAlloc(
  61. DWORD dwEncodingType,
  62. LPCSTR lpszStructType,
  63. const void * pvStructInfo,
  64. PBYTE * pbEncoded,
  65. PDWORD pcbEncoded
  66. );
  67. LPWSTR
  68. MakeDNName(
  69. VOID
  70. );
  71. DWORD
  72. CreatePublicKeyInformationCertificate(
  73. IN PSID pUserSid OPTIONAL,
  74. PBYTE pbCert,
  75. DWORD cbCert,
  76. OUT PEFS_PUBLIC_KEY_INFO * PublicKeyInformation
  77. );
  78. DWORD
  79. GetDefaultRecoveryPolicy(
  80. IN HANDLE hToken,
  81. IN BOOL bIsDC,
  82. OUT PUCHAR *pRecoveryPolicyBlob,
  83. OUT ULONG *PolicySize,
  84. OUT PCCERT_CONTEXT *ppCertContext
  85. );
  86. HRESULT
  87. CreateLocalMachinePolicy(
  88. IN PWLX_NOTIFICATION_INFO pInfo,
  89. IN BOOL bIsDC,
  90. OUT PUCHAR *pEfsBlob,
  91. OUT ULONG *pEfsSize,
  92. OUT PCCERT_CONTEXT *ppCertContext
  93. );
  94. typedef DWORD (WINAPI *PFNDSGETDCNAME)(LPCTSTR, LPCTSTR, GUID *, LPCTSTR, ULONG, PDOMAIN_CONTROLLER_INFO *);
  95. HRESULT
  96. CreateEFSDefaultPolicy(
  97. IN HANDLE hToken,
  98. IN PUCHAR *pEfsBlob,
  99. IN DWORD *pEfsSize,
  100. IN PCCERT_CONTEXT *ppCertContext,
  101. IN LPTSTR DomainName
  102. );
  103. DWORD
  104. MyLdapOpen(
  105. OUT PLDAP *pLdap
  106. );
  107. DWORD
  108. MyGetDsObjectRoot(
  109. IN PLDAP pLdap,
  110. OUT PWSTR *pDsRootName
  111. );
  112. HRESULT
  113. CreateGroupPolicyObjectInDomain(
  114. IN HANDLE hToken,
  115. IN PWSTR DomainNCName,
  116. IN PWSTR GPObjectName,
  117. IN PUCHAR EfsBlob,
  118. IN ULONG EfsSize,
  119. IN PCCERT_CONTEXT pCertContext,
  120. OUT LPGROUPPOLICYOBJECT *ppObject
  121. );
  122. DWORD
  123. CheckExistingEFSPolicy(
  124. IN PLDAP phLdap,
  125. IN LPTSTR DomainNCName,
  126. OUT BOOL *bExist
  127. );
  128. DWORD
  129. MyLdapClose(
  130. IN PLDAP *pLdap
  131. );
  132. LPWSTR
  133. GetCertDisplayInformation(
  134. IN PCCERT_CONTEXT pCertContext
  135. );
  136. BOOLEAN
  137. IsSelfSignedPolicyExpired(
  138. IN PRECOVERY_POLICY_1_1 RecoveryPolicy OPTIONAL
  139. );
  140. #define EFS_NOTIFY_PATH TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify\\EFS")
  141. extern "C"
  142. BOOL
  143. EfsRecInit(
  144. IN PVOID hmod,
  145. IN ULONG Reason,
  146. IN PCONTEXT Context
  147. )
  148. {
  149. return( TRUE );
  150. }
  151. /////////////////////////////////////////////////////////////////////////////
  152. // DllRegisterServer - Adds entries to the system registry
  153. STDAPI DllRegisterServerEFS(void)
  154. {
  155. HKEY hKey;
  156. LONG lResult;
  157. DWORD dwDisp;
  158. lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  159. EFS_NOTIFY_PATH,
  160. 0,
  161. NULL,
  162. REG_OPTION_NON_VOLATILE,
  163. KEY_WRITE,
  164. NULL,
  165. &hKey,
  166. &dwDisp
  167. );
  168. if (lResult != ERROR_SUCCESS)
  169. {
  170. return lResult;
  171. }
  172. RegSetValueEx( hKey,
  173. TEXT("Logon"),
  174. 0,
  175. REG_SZ,
  176. (LPBYTE)TEXT("WLEventLogon"),
  177. (lstrlen(TEXT("WLEventLogon")) + 1) * sizeof(TCHAR)
  178. );
  179. RegSetValueEx( hKey,
  180. TEXT("DllName"),
  181. 0,
  182. REG_EXPAND_SZ,
  183. (LPBYTE)TEXT("sclgntfy.dll"),
  184. (lstrlen(TEXT("sclgntfy.dll")) + 1) * sizeof(TCHAR)
  185. );
  186. //
  187. // increase the wait limit to 10 minutes
  188. //
  189. DWORD dwValue = 120;
  190. RegSetValueEx( hKey,
  191. TEXT("MaxWait"),
  192. 0,
  193. REG_DWORD,
  194. (LPBYTE)&dwValue,
  195. sizeof(DWORD)
  196. );
  197. RegCloseKey (hKey);
  198. return S_OK;
  199. }
  200. /////////////////////////////////////////////////////////////////////////////
  201. // DllUnregisterServer - Removes entries from the system registry
  202. STDAPI DllUnregisterServerEFS(void)
  203. {
  204. RegDeleteKey (HKEY_LOCAL_MACHINE, EFS_NOTIFY_PATH);
  205. return S_OK;
  206. }
  207. DWORD WINAPI
  208. EFSRecPolicyPostProcess(
  209. IN LPVOID Param
  210. )
  211. /*++
  212. Routine Description:
  213. Enumerate the volumes and do the possible recovery jobs caused by
  214. power outage or crash during encryption or decryption.
  215. Arguments:
  216. Param -- Standard parameter for thread. Not used.
  217. Return Value:
  218. Operation result.
  219. --*/
  220. {
  221. PEFS_POLICY_POST_PROCESS pPcType = (PEFS_POLICY_POST_PROCESS) Param;
  222. LPWSTR objName = NULL;
  223. LPWSTR popUpMsg = NULL;
  224. LPWSTR popUpTitle = NULL;
  225. DWORD dRet;
  226. DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1;
  227. if ( pPcType == NULL ) {
  228. return(ERROR_INVALID_PARAMETER);
  229. }
  230. if (!SetThreadDesktop( pPcType->ShellWnd )){
  231. return GetLastError();
  232. }
  233. if (!(pPcType->PCIsDC)) {
  234. //
  235. // Get the PC name
  236. //
  237. BOOL b = GetComputerName ( pPcType->ObjName, &nSize );
  238. if (b) {
  239. objName = pPcType->ObjName;
  240. }
  241. } else {
  242. objName = pPcType->ObjName;
  243. }
  244. dRet = FormatMessage(
  245. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  246. g_hDllInstance,
  247. EFS_POLICY_WARNING,
  248. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  249. (LPTSTR) &popUpMsg,
  250. 0,
  251. (va_list *)&objName
  252. );
  253. if (dRet) {
  254. dRet = FormatMessage(
  255. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY | 80,
  256. g_hDllInstance,
  257. EFS_POLICY_WARNING_TITLE,
  258. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  259. (LPTSTR) &popUpTitle,
  260. 0,
  261. NULL
  262. );
  263. if (dRet) {
  264. MessageBox(NULL, popUpMsg, popUpTitle, MB_OK | MB_ICONINFORMATION);
  265. LocalFree( popUpTitle );
  266. }
  267. LocalFree( popUpMsg );
  268. }
  269. //
  270. // free the buffer allocated
  271. //
  272. LocalFree(pPcType);
  273. return 0;
  274. }
  275. #if 0
  276. DWORD
  277. EFSRecPolicyPopup(
  278. IN DSROLE_MACHINE_ROLE MachineRole,
  279. IN LPTSTR DomainNameFlat OPTIONAL
  280. )
  281. {
  282. DWORD EFSRecPolicyThreadID;
  283. HANDLE EfsWarningThread;
  284. PEFS_POLICY_POST_PROCESS PcType = NULL;
  285. //
  286. // Pop the dialog warning the user that the recovery policy has been created.
  287. //
  288. PcType = (PEFS_POLICY_POST_PROCESS)LocalAlloc(LPTR, sizeof(EFS_POLICY_POST_PROCESS));
  289. if ( PcType == NULL ) {
  290. return(ERROR_NOT_ENOUGH_MEMORY);
  291. }
  292. if (MachineRole == DsRole_RolePrimaryDomainController ||
  293. MachineRole == DsRole_RoleBackupDomainController ) {
  294. //
  295. // The PC is a DC.
  296. //
  297. PcType->PCIsDC = TRUE;
  298. if ( DomainNameFlat) {
  299. wcscpy(PcType->ObjName,DomainNameFlat);
  300. } else {
  301. PcType->ObjName[0] = L'\0';
  302. }
  303. } else {
  304. PcType->PCIsDC = FALSE;
  305. PcType->ObjName[0] = L'\0';
  306. }
  307. DWORD rc=ERROR_SUCCESS;
  308. PcType->ShellWnd = GetThreadDesktop( GetCurrentThreadId() );
  309. if (PcType->ShellWnd) {
  310. EfsWarningThread = CreateThread( NULL,
  311. 0,
  312. EFSRecPolicyPostProcess,
  313. PcType,
  314. 0,
  315. &EFSRecPolicyThreadID
  316. );
  317. if (EfsWarningThread) {
  318. CloseHandle(EfsWarningThread);
  319. } else {
  320. //
  321. // free the buffer allocated
  322. //
  323. LocalFree(PcType);
  324. rc = GetLastError();
  325. }
  326. } else {
  327. //
  328. // free the buffer allocated
  329. //
  330. LocalFree(PcType);
  331. rc = GetLastError();
  332. }
  333. return rc;
  334. }
  335. #endif
  336. VOID WLEventLogon(
  337. PWLX_NOTIFICATION_INFO pInfo
  338. )
  339. {
  340. //
  341. // First, local EFS policy is always created on all products (wks, srv, DC)
  342. //
  343. DWORD rc;
  344. LONG lResult;
  345. HKEY hKey;
  346. DWORD IsCreated=0;
  347. //
  348. // even if we were unregistered, without a reboot, we still get this event.
  349. // use the EFS... key to see if we were deregistered, and if so, leave.
  350. //
  351. lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  352. EFS_NOTIFY_PATH,
  353. 0,
  354. MAXIMUM_ALLOWED,
  355. &hKey
  356. );
  357. if (lResult != ERROR_SUCCESS) {
  358. return;
  359. } else {
  360. //
  361. // query if a domain EFS policy was created before
  362. //
  363. DWORD RegType;
  364. DWORD nSize=sizeof(DWORD);
  365. RegQueryValueEx(
  366. hKey,
  367. L"EFSDomainGPOCreated",
  368. 0,
  369. &RegType,
  370. (LPBYTE)&IsCreated,
  371. &nSize
  372. );
  373. RegCloseKey( hKey );
  374. }
  375. if (IsCreated != 0) {
  376. //
  377. // The DC recovery policy is already set
  378. //
  379. DllUnregisterServerEFS();
  380. return;
  381. }
  382. //
  383. // check the current logon user. If not a member of administrators, quit
  384. //
  385. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  386. PSID AdminAccountSid;
  387. BOOL bIsMemberOfAdmins = FALSE;
  388. if ( NT_SUCCESS( RtlAllocateAndInitializeSid(
  389. &NtAuthority,
  390. 2,
  391. SECURITY_BUILTIN_DOMAIN_RID,
  392. DOMAIN_ALIAS_RID_ADMINS,
  393. 0, 0, 0, 0, 0, 0,
  394. &AdminAccountSid
  395. ) ) ) {
  396. HANDLE NewToken;
  397. if ( DuplicateToken( pInfo->hToken, SecurityImpersonation, &NewToken )) {
  398. if ( FALSE == CheckTokenMembership(
  399. NewToken,
  400. AdminAccountSid,
  401. &bIsMemberOfAdmins
  402. ) ) {
  403. //
  404. // error occured when checking membership, assume it is not a member
  405. //
  406. bIsMemberOfAdmins = FALSE;
  407. }
  408. CloseHandle(NewToken);
  409. }
  410. RtlFreeSid( AdminAccountSid);
  411. }
  412. if ( bIsMemberOfAdmins == FALSE ) {
  413. //
  414. // if it's not admin logon, or for some reason token membership can't
  415. // be checked, quit ???
  416. //
  417. return;
  418. }
  419. //
  420. // impersonate the token
  421. //
  422. if ( FALSE == ImpersonateLoggedOnUser(pInfo->hToken) ) {
  423. return;
  424. }
  425. //
  426. // initialize event log. If failed, will try later for each LogEvent call.
  427. //
  428. (void) InitializeEvents();
  429. //
  430. // check the machine role
  431. //
  432. PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pDsRole;
  433. rc = DsRoleGetPrimaryDomainInformation(
  434. NULL,
  435. DsRolePrimaryDomainInfoBasic,
  436. (PBYTE *)&pDsRole
  437. );
  438. if (rc != ERROR_SUCCESS) {
  439. //
  440. // Try again some other time? Deregister?
  441. // This isn't supposed to happen.
  442. //
  443. LogEvent(STATUS_SEVERITY_ERROR,
  444. GPOEVENT_ERROR_DSROLE,
  445. IDS_FAILED_GET_DSROLE,
  446. GetLastError()
  447. );
  448. (void) ShutdownEvents();
  449. RevertToSelf();
  450. return;
  451. }
  452. DSROLE_MACHINE_ROLE MachineRole = pDsRole->MachineRole;
  453. if (MachineRole != DsRole_RolePrimaryDomainController) {
  454. //
  455. // We don't create EFS recovery policy on non-PDC
  456. //
  457. (void) ShutdownEvents();
  458. DsRoleFreeMemory( pDsRole );
  459. RevertToSelf();
  460. DllUnregisterServerEFS();
  461. return;
  462. }
  463. //
  464. // create the EFS local policy if not exist
  465. //
  466. CoInitialize(NULL);
  467. HRESULT hr = ERROR_SUCCESS;
  468. PUCHAR EfsBlob=NULL;
  469. ULONG EfsSize=0;
  470. PCCERT_CONTEXT pCertContext=NULL;
  471. /*
  472. //
  473. // check/create EFS policy in the local machine object
  474. //
  475. hr = CreateLocalMachinePolicy(
  476. pInfo,
  477. ( MachineRole == DsRole_RolePrimaryDomainController ) ? TRUE : FALSE,
  478. &EfsBlob,
  479. &EfsSize,
  480. &pCertContext
  481. );
  482. if ( SUCCEEDED(hr) ) {
  483. //
  484. // local machine policy has been successfully created
  485. // delete the SystemClone flag if it exists (or set it to 0 if it can't be deleted)
  486. //
  487. lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  488. EFS_NOTIFY_PATH,
  489. 0,
  490. MAXIMUM_ALLOWED,
  491. &hKey
  492. );
  493. if (lResult == ERROR_SUCCESS) {
  494. lResult = RegDeleteValue (hKey, TEXT("SystemCloned") );
  495. if ( lResult == ERROR_ACCESS_DENIED ) {
  496. //
  497. // can't delete it, now set it to 0
  498. //
  499. DWORD dwClone = 0;
  500. RegSetValueEx( hKey,
  501. TEXT("SystemCloned"),
  502. 0,
  503. REG_DWORD,
  504. (LPBYTE)&dwClone,
  505. sizeof(DWORD)
  506. );
  507. }
  508. RegCloseKey( hKey );
  509. }
  510. //
  511. // detect the role of this computer and create the default EFS group
  512. // policies for domain controllers
  513. //
  514. // this code is also executed for replicas because if the user logs on
  515. // to replica first (before logging onto the PDC), we still want to
  516. // have EFS recovery policy created.
  517. //
  518. // if the replica is a READ ONLY replica (BDC), this call will fail
  519. //
  520. if ( (MachineRole == DsRole_RolePrimaryDomainController) &&
  521. ( IsCreated == 0) ) {
  522. //
  523. // Create the default group policy object and add it to the gPLink list.
  524. //
  525. if ( EfsBlob == NULL ) {
  526. EfsSize = 0;
  527. if ( pCertContext ) {
  528. //
  529. // free it first
  530. //
  531. CertFreeCertificateContext( pCertContext );
  532. pCertContext = NULL;
  533. }
  534. }
  535. */
  536. //
  537. // create both EFS default policy and domain account policy objects.
  538. //
  539. hr = CreateEFSDefaultPolicy(pInfo->hToken,
  540. &EfsBlob,
  541. &EfsSize,
  542. &pCertContext,
  543. pDsRole->DomainNameFlat);
  544. if ( SUCCEEDED(hr) ) {
  545. //
  546. // update the registry value EFSDomainGPOCreated
  547. //
  548. lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  549. EFS_NOTIFY_PATH,
  550. 0,
  551. MAXIMUM_ALLOWED,
  552. &hKey
  553. );
  554. if (lResult == ERROR_SUCCESS) {
  555. //
  556. // set the flag
  557. //
  558. IsCreated = 1;
  559. RegSetValueEx( hKey,
  560. L"EFSDomainGPOCreated",
  561. 0,
  562. REG_DWORD,
  563. (LPBYTE)&IsCreated,
  564. sizeof(DWORD)
  565. );
  566. RegCloseKey( hKey );
  567. }
  568. }
  569. /*
  570. } else {
  571. //
  572. // the domain GPO is already created, or
  573. //
  574. // If it's workstation or server (either standalone or member), local policy
  575. // (existing or just created) is enough.
  576. //
  577. //
  578. // If it's a backup domain controller (replica), no need to create any
  579. // default ( because either the one replicated from the primary domain
  580. // or the one created by server setup will take effect );
  581. //
  582. // !!! do nothing !!!
  583. }
  584. */
  585. if ( SUCCEEDED(hr) ) {
  586. DllUnregisterServerEFS();
  587. HINSTANCE hUserEnvDll = LoadLibrary(TEXT("userenv.dll"));
  588. PFREFRESHPOLICY pfRefreshPolicy=NULL;
  589. if ( hUserEnvDll) {
  590. pfRefreshPolicy = (PFREFRESHPOLICY)GetProcAddress(
  591. hUserEnvDll,
  592. "RefreshPolicy");
  593. if ( pfRefreshPolicy ) {
  594. //
  595. // do not care errors
  596. //
  597. (void) (*pfRefreshPolicy)(TRUE);
  598. } else {
  599. LogEvent(STATUS_SEVERITY_WARNING,
  600. GPOEVENT_WARNING_NOT_REFRESH,
  601. IDS_ERROR_GET_PROC_ADDR,
  602. GetLastError()
  603. );
  604. }
  605. FreeLibrary(hUserEnvDll);
  606. } else {
  607. LogEvent(STATUS_SEVERITY_WARNING,
  608. GPOEVENT_WARNING_NOT_REFRESH,
  609. IDS_ERROR_LOAD_USERENV,
  610. GetLastError()
  611. );
  612. }
  613. }
  614. // }
  615. if (pDsRole) {
  616. DsRoleFreeMemory( pDsRole );
  617. }
  618. (void) ShutdownEvents();
  619. //
  620. // uninitialize OLE
  621. //
  622. CoUninitialize();
  623. RevertToSelf();
  624. //
  625. // clean up buffers
  626. //
  627. if ( EfsBlob ) {
  628. free(EfsBlob);
  629. }
  630. if ( pCertContext ) {
  631. CertFreeCertificateContext( pCertContext );
  632. }
  633. }
  634. #if 0
  635. HRESULT
  636. CreateLocalMachinePolicy(
  637. IN PWLX_NOTIFICATION_INFO pInfo,
  638. IN BOOL bIsDC,
  639. OUT PUCHAR *pEfsBlob,
  640. OUT ULONG *pEfsSize,
  641. OUT PCCERT_CONTEXT *ppCertContext
  642. )
  643. {
  644. LPGROUPPOLICYOBJECT pGPO = NULL;
  645. HRESULT hr;
  646. HKEY hKeyPolicyRoot;
  647. HKEY hKey;
  648. DWORD rc=ERROR_SUCCESS;
  649. //
  650. // create Policy Object instance
  651. //
  652. hr = CoCreateInstance( CLSID_GroupPolicyObject,
  653. NULL,
  654. CLSCTX_SERVER,
  655. IID_IGroupPolicyObject,
  656. (PVOID *)&pGPO
  657. );
  658. if (SUCCEEDED(hr) && pGPO) {
  659. //
  660. // open LPO and load policy into registry
  661. // if LPO does not exist, create it (under system context now)
  662. //
  663. hr = pGPO->OpenLocalMachineGPO( TRUE );
  664. if (SUCCEEDED(hr)) {
  665. //
  666. // get the registry key for the root of machine policy object
  667. //
  668. hr = pGPO->GetRegistryKey( GPO_SECTION_MACHINE,
  669. &hKeyPolicyRoot
  670. );
  671. if (SUCCEEDED(hr)) {
  672. //
  673. // open EFS recovery policy base key in the registry
  674. //
  675. BOOL fContinue = TRUE;
  676. DWORD dwDisposition;
  677. if ( (rc = RegCreateKeyEx(
  678. hKeyPolicyRoot,
  679. CERT_EFSBLOB_REGPATH,
  680. 0,
  681. TEXT("REG_SZ"),
  682. REG_OPTION_NON_VOLATILE,
  683. KEY_ALL_ACCESS,
  684. NULL,
  685. &hKey,
  686. &dwDisposition
  687. )) == ERROR_SUCCESS ) {
  688. //
  689. // check to see if there is EFS blob
  690. // if not, create it.
  691. //
  692. DWORD RegType;
  693. DWORD EfsSize;
  694. PUCHAR pEfsOldBlob=NULL;
  695. BOOL bIsExpired=FALSE;
  696. rc = RegQueryValueEx(
  697. hKey,
  698. CERT_EFSBLOB_VALUE_NAME,
  699. 0,
  700. &RegType,
  701. NULL,
  702. &EfsSize
  703. );
  704. if ( rc == ERROR_SUCCESS && EfsSize > 0 ) {
  705. //
  706. // query if this machine is cloned
  707. //
  708. HKEY hKeyClone;
  709. rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  710. EFS_NOTIFY_PATH,
  711. 0,
  712. MAXIMUM_ALLOWED,
  713. &hKeyClone
  714. );
  715. if (rc == ERROR_SUCCESS) {
  716. DWORD nSize=sizeof(DWORD);
  717. DWORD dwClone=0;
  718. RegQueryValueEx(
  719. hKeyClone,
  720. L"SystemCloned",
  721. 0,
  722. &RegType,
  723. (LPBYTE)&dwClone,
  724. &nSize
  725. );
  726. RegCloseKey( hKeyClone );
  727. if ( dwClone > 0 ) {
  728. bIsExpired = TRUE;
  729. }
  730. }
  731. if ( !bIsExpired ) {
  732. //
  733. // EFS recovery policy already exists
  734. // query the blob and check if this policy needs to be
  735. // upgraded (change expiration date)
  736. //
  737. pEfsOldBlob = (PUCHAR)LocalAlloc(LPTR, EfsSize+1);
  738. if ( pEfsOldBlob ) {
  739. rc = RegQueryValueEx(
  740. hKey,
  741. CERT_EFSBLOB_VALUE_NAME,
  742. 0,
  743. &RegType,
  744. pEfsOldBlob,
  745. &EfsSize
  746. );
  747. if ( rc == ERROR_SUCCESS ) {
  748. //
  749. // check if the policy should be recreated.
  750. //
  751. bIsExpired = IsSelfSignedPolicyExpired((PRECOVERY_POLICY_1_1)pEfsOldBlob);
  752. }
  753. LocalFree(pEfsOldBlob);
  754. pEfsOldBlob = NULL;
  755. } else {
  756. rc = ERROR_NOT_ENOUGH_MEMORY;
  757. }
  758. }
  759. }
  760. if ( rc != ERROR_SUCCESS || EfsSize == 0 || bIsExpired ) {
  761. //
  762. // the EFSBlob registry value does not exis
  763. // this means that local EFS policy should be created
  764. //
  765. *pEfsSize = 0;
  766. rc = GetDefaultRecoveryPolicy(pInfo->hToken,
  767. bIsDC,
  768. pEfsBlob,
  769. pEfsSize,
  770. ppCertContext
  771. );
  772. if ( ERROR_SUCCESS == rc && *ppCertContext ) {
  773. //
  774. // add to the cert store of this GPO first
  775. //
  776. CERT_SYSTEM_STORE_RELOCATE_PARA paraRelocate;
  777. paraRelocate.hKeyBase = hKeyPolicyRoot;
  778. paraRelocate.pwszSystemStore = L"EFS";
  779. HCERTSTORE hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
  780. 0,
  781. NULL,
  782. CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY |
  783. CERT_SYSTEM_STORE_RELOCATE_FLAG,
  784. (void *)&paraRelocate
  785. );
  786. if ( hCertStore ) {
  787. if ( bIsExpired ) {
  788. //
  789. // delete all old certs from the store first
  790. //
  791. PCCERT_CONTEXT pEnumCertContext = CertEnumCertificatesInStore(
  792. hCertStore,
  793. NULL
  794. );
  795. PCCERT_CONTEXT pCertContextDelete=NULL;
  796. while ( pEnumCertContext ) {
  797. //
  798. // duplicate the cert context
  799. //
  800. pCertContextDelete = CertDuplicateCertificateContext( pEnumCertContext );
  801. //
  802. // enumerate the next certificate context
  803. //
  804. pEnumCertContext = CertEnumCertificatesInStore(
  805. hCertStore,
  806. pEnumCertContext
  807. );
  808. if ( pCertContextDelete ) {
  809. //
  810. // delete the cert from store
  811. //
  812. CertDeleteCertificateFromStore( pCertContextDelete );
  813. //
  814. // no need to free the cert context
  815. // because it's freed by the previous call (even under error case)
  816. //
  817. pCertContextDelete = NULL;
  818. }
  819. }
  820. }
  821. if ( !CertAddCertificateContextToStore(
  822. hCertStore,
  823. *ppCertContext,
  824. CERT_STORE_ADD_ALWAYS,
  825. NULL
  826. ) ) {
  827. rc = GetLastError();
  828. }
  829. //
  830. // close the store
  831. //
  832. CertCloseStore(hCertStore, 0);
  833. hCertStore = NULL;
  834. } else {
  835. rc = GetLastError();
  836. }
  837. if ( ERROR_SUCCESS == rc ) {
  838. rc = RegSetValueEx(
  839. hKey,
  840. CERT_EFSBLOB_VALUE_NAME,
  841. 0,
  842. REG_BINARY,
  843. (PBYTE)(*pEfsBlob),
  844. *pEfsSize
  845. );
  846. if (rc == ERROR_SUCCESS) {
  847. hr = pGPO->Save(TRUE, TRUE, &guidExtension, &guidSnapin );
  848. hr = pGPO->Save(TRUE, TRUE, &guidRegExt, &guidSnapin );
  849. if ( FAILED(hr) ) {
  850. LogEvent(STATUS_SEVERITY_ERROR,
  851. GPOEVENT_ERROR_CREATE_LPO,
  852. IDS_ERROR_SAVE_LPO,
  853. hr
  854. );
  855. } else {
  856. /* comment out due to PM request
  857. //
  858. // popup a message to warn user
  859. //
  860. EFSRecPolicyPopup(
  861. DsRole_RoleStandaloneWorkstation, // this value doesn't matter
  862. NULL
  863. );
  864. */
  865. }
  866. } else {
  867. LogEvent(STATUS_SEVERITY_ERROR,
  868. GPOEVENT_ERROR_CREATE_LPO,
  869. IDS_ERROR_SAVE_EFSBLOB,
  870. rc
  871. );
  872. }
  873. } else {
  874. LogEvent(STATUS_SEVERITY_ERROR,
  875. GPOEVENT_ERROR_CREATE_LPO,
  876. IDS_ERROR_ADD_CERTIFICATE,
  877. rc
  878. );
  879. }
  880. } else {
  881. LogEvent(STATUS_SEVERITY_ERROR,
  882. GPOEVENT_ERROR_CREATE_LPO,
  883. IDS_ERROR_CREATE_EFSBLOB,
  884. rc
  885. );
  886. }
  887. }
  888. //
  889. // close the registry key
  890. //
  891. RegCloseKey(hKey);
  892. } else {
  893. LogEvent(STATUS_SEVERITY_ERROR,
  894. GPOEVENT_ERROR_CREATE_LPO,
  895. IDS_ERROR_OPEN_EFSKEY,
  896. rc
  897. );
  898. }
  899. if ( rc != ERROR_SUCCESS ) {
  900. hr = HRESULT_FROM_WIN32(rc);
  901. }
  902. RegCloseKey(hKeyPolicyRoot);
  903. } else {
  904. LogEvent(STATUS_SEVERITY_ERROR,
  905. GPOEVENT_ERROR_CREATE_LPO,
  906. IDS_ERROR_GET_REGISTRY_KEY,
  907. hr
  908. );
  909. }
  910. } else {
  911. LogEvent(STATUS_SEVERITY_ERROR,
  912. GPOEVENT_ERROR_CREATE_LPO,
  913. IDS_ERROR_OPEN_LPO,
  914. hr
  915. );
  916. }
  917. //
  918. // release the policy object instance
  919. //
  920. pGPO->Release();
  921. } else {
  922. LogEvent(STATUS_SEVERITY_ERROR,
  923. GPOEVENT_ERROR_CREATE_LPO,
  924. IDS_ERROR_CREATE_GPO_INSTANCE,
  925. hr
  926. );
  927. }
  928. return hr;
  929. }
  930. #endif
  931. DWORD
  932. GetDefaultRecoveryPolicy(
  933. IN HANDLE hToken,
  934. IN BOOL bIsDC,
  935. OUT PUCHAR *pRecoveryPolicyBlob,
  936. OUT ULONG *BlobSize,
  937. OUT PCCERT_CONTEXT *ppCertContext
  938. )
  939. /*++
  940. Routine Description:
  941. This routine creates the default recovery policy for the current system.
  942. It does this by auto-generating a recovery key based on the name of the
  943. machine.
  944. Arguments:
  945. hToken - the token of current user
  946. pRecoveryPolicyBlob - the output buffer to hold EFSBlob
  947. BlobSize - the size of EFSBlob
  948. Return Value:
  949. --*/
  950. {
  951. DWORD rc = ERROR_SUCCESS;
  952. PCCERT_CONTEXT pCertContext;
  953. *pRecoveryPolicyBlob = NULL;
  954. *BlobSize = 0;
  955. *ppCertContext = NULL;
  956. if (CreateSelfSignedRecoveryCertificate(
  957. bIsDC,
  958. &pCertContext
  959. )) {
  960. PEFS_PUBLIC_KEY_INFO PublicKeyInformation;
  961. PBYTE pbCert = pCertContext->pbCertEncoded;
  962. DWORD cbCert = pCertContext->cbCertEncoded;
  963. PTOKEN_USER pTokenUser = GetTokenUser( hToken );
  964. if (pTokenUser) {
  965. rc = CreatePublicKeyInformationCertificate(
  966. pTokenUser->User.Sid,
  967. pbCert,
  968. cbCert,
  969. &PublicKeyInformation
  970. );
  971. if (rc == ERROR_SUCCESS) {
  972. //
  973. // Compute the total size of the RECOVERY_POLICY_1_1 structure, which
  974. // is the size of the structure minus the size of the EFS_PUBLIC_KEY_INFO
  975. // plus the size of the thing we just created above.
  976. //
  977. ULONG RecoveryKeySize = sizeof( RECOVERY_KEY_1_1 ) - sizeof( EFS_PUBLIC_KEY_INFO ) + PublicKeyInformation->Length;
  978. ULONG PolicySize = sizeof( RECOVERY_POLICY_1_1 ) + RecoveryKeySize - sizeof( RECOVERY_KEY_1_1 );
  979. //
  980. // Allocate the policy block
  981. //
  982. PRECOVERY_POLICY_1_1 RecoveryPolicy = (PRECOVERY_POLICY_1_1)malloc( PolicySize );
  983. if (RecoveryPolicy != NULL) {
  984. RecoveryPolicy->RecoveryPolicyHeader.MajorRevision = EFS_RECOVERY_POLICY_MAJOR_REVISION_1;
  985. RecoveryPolicy->RecoveryPolicyHeader.MinorRevision = EFS_RECOVERY_POLICY_MINOR_REVISION_1;
  986. RecoveryPolicy->RecoveryPolicyHeader.RecoveryKeyCount = 1;
  987. PRECOVERY_KEY_1_1 RecoveryKey = (PRECOVERY_KEY_1_1) &(RecoveryPolicy->RecoveryKeyList[0]);
  988. memcpy( &RecoveryKey->PublicKeyInfo, PublicKeyInformation, PublicKeyInformation->Length );
  989. RecoveryKey->TotalLength = sizeof( RECOVERY_KEY_1_1 ) + PublicKeyInformation->Length - sizeof( EFS_PUBLIC_KEY_INFO );
  990. *pRecoveryPolicyBlob = (PUCHAR)RecoveryPolicy;
  991. *BlobSize = PolicySize;
  992. *ppCertContext = pCertContext;
  993. //
  994. // will free this outside this function
  995. //
  996. pCertContext = NULL;
  997. } else {
  998. rc = ERROR_NOT_ENOUGH_MEMORY;
  999. }
  1000. free( PublicKeyInformation );
  1001. }
  1002. free( pTokenUser );
  1003. } else {
  1004. rc = GetLastError();
  1005. }
  1006. //
  1007. // free the certificate context if not outputted
  1008. //
  1009. if ( pCertContext ) {
  1010. CertFreeCertificateContext( pCertContext );
  1011. }
  1012. } else {
  1013. rc = GetLastError();
  1014. }
  1015. return( rc );
  1016. }
  1017. BOOLEAN
  1018. CreateSelfSignedRecoveryCertificate(
  1019. IN BOOL bIsDC,
  1020. OUT PCCERT_CONTEXT * pCertContext
  1021. )
  1022. /*++
  1023. Routine Description:
  1024. This routine sets up and creates a self-signed certificate.
  1025. Arguments:
  1026. Return Value:
  1027. TRUE on success, FALSE on failure. Call GetLastError() for more details.
  1028. --*/
  1029. {
  1030. BOOLEAN fReturn = FALSE;
  1031. DWORD rc = ERROR_SUCCESS;
  1032. LPWSTR lpContainerName = NULL;
  1033. LPWSTR lpProviderName = NULL;
  1034. PBYTE pbHash = NULL;
  1035. LPWSTR lpDisplayInfo = NULL;
  1036. HCRYPTKEY hKey = NULL;
  1037. HCRYPTPROV hProv = NULL;
  1038. *pCertContext = NULL;
  1039. //
  1040. // Croft up a key pair
  1041. //
  1042. //
  1043. // Container name
  1044. //
  1045. GUID guidContainerName;
  1046. if ( ERROR_SUCCESS != UuidCreate(&guidContainerName) ) {
  1047. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1048. return(fReturn);
  1049. }
  1050. LPWSTR TmpContainerName;
  1051. if (ERROR_SUCCESS == UuidToStringW(&guidContainerName, (unsigned short **)&lpContainerName )) {
  1052. //
  1053. // Copy the container name into LSA heap memory
  1054. //
  1055. lpProviderName = MS_DEF_PROV;
  1056. //
  1057. // Create the key container
  1058. //
  1059. if (CryptAcquireContext(&hProv, lpContainerName, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET )) {
  1060. if (CryptGenKey(hProv, AT_KEYEXCHANGE, RSA1024BIT_KEY | CRYPT_EXPORTABLE, &hKey)) {
  1061. DWORD NameLength = 64;
  1062. LPWSTR AgentName = NULL;
  1063. //
  1064. // Construct the subject name information
  1065. //
  1066. //lpDisplayInfo = MakeDNName();
  1067. AgentName = (LPWSTR)malloc(NameLength * sizeof(WCHAR));
  1068. if (AgentName){
  1069. if (!GetUserName(AgentName, &NameLength)){
  1070. free(AgentName);
  1071. AgentName = (LPWSTR)malloc(NameLength * sizeof(WCHAR));
  1072. //
  1073. // Try again with big buffer
  1074. //
  1075. if ( AgentName ){
  1076. if (!GetUserName(AgentName, &NameLength)){
  1077. rc = GetLastError();
  1078. free(AgentName);
  1079. AgentName = NULL;
  1080. }
  1081. } else {
  1082. rc = ERROR_NOT_ENOUGH_MEMORY;
  1083. }
  1084. }
  1085. } else {
  1086. rc = ERROR_NOT_ENOUGH_MEMORY;
  1087. }
  1088. if (AgentName) {
  1089. LPCWSTR DNNameTemplate = L"CN=%ws,L=EFS,OU=EFS File Encryption Certificate";
  1090. DWORD cbDNName = 0;
  1091. cbDNName = (wcslen( DNNameTemplate ) + 1) * sizeof( WCHAR ) + (wcslen( AgentName ) + 1) * sizeof( WCHAR );
  1092. lpDisplayInfo = (LPWSTR)malloc( cbDNName );
  1093. if (lpDisplayInfo) {
  1094. swprintf( lpDisplayInfo, DNNameTemplate, AgentName );
  1095. } else {
  1096. rc = ERROR_NOT_ENOUGH_MEMORY;
  1097. }
  1098. free(AgentName);
  1099. AgentName = NULL;
  1100. }
  1101. if (lpDisplayInfo) {
  1102. //
  1103. // Use this piece of code to create the PCERT_NAME_BLOB going into CertCreateSelfSignCertificate()
  1104. //
  1105. CERT_NAME_BLOB SubjectName;
  1106. SubjectName.cbData = 0;
  1107. if(CertStrToNameW(
  1108. CRYPT_ASN_ENCODING,
  1109. lpDisplayInfo,
  1110. 0,
  1111. NULL,
  1112. NULL,
  1113. &SubjectName.cbData,
  1114. NULL)) {
  1115. SubjectName.pbData = (BYTE *) malloc(SubjectName.cbData);
  1116. if (SubjectName.pbData) {
  1117. if (CertStrToNameW(
  1118. CRYPT_ASN_ENCODING,
  1119. lpDisplayInfo,
  1120. 0,
  1121. NULL,
  1122. SubjectName.pbData,
  1123. &SubjectName.cbData,
  1124. NULL) ) {
  1125. //
  1126. // Make the enhanced key usage
  1127. //
  1128. CERT_ENHKEY_USAGE certEnhKeyUsage;
  1129. LPSTR lpstr;
  1130. CERT_EXTENSION certExt;
  1131. lpstr = szOID_EFS_RECOVERY;
  1132. certEnhKeyUsage.cUsageIdentifier = 1;
  1133. certEnhKeyUsage.rgpszUsageIdentifier = &lpstr;
  1134. // now call CryptEncodeObject to encode the enhanced key usage into the extension struct
  1135. certExt.Value.cbData = 0;
  1136. certExt.Value.pbData = NULL;
  1137. certExt.fCritical = FALSE;
  1138. certExt.pszObjId = szOID_ENHANCED_KEY_USAGE;
  1139. //
  1140. // Encode it
  1141. //
  1142. if (EncodeAndAlloc(
  1143. CRYPT_ASN_ENCODING,
  1144. X509_ENHANCED_KEY_USAGE,
  1145. &certEnhKeyUsage,
  1146. &certExt.Value.pbData,
  1147. &certExt.Value.cbData
  1148. )) {
  1149. //
  1150. // finally, set up the array of extensions in the certInfo struct
  1151. // any further extensions need to be added to this array.
  1152. //
  1153. CERT_EXTENSIONS certExts;
  1154. certExts.cExtension = 1;
  1155. certExts.rgExtension = &certExt;
  1156. CRYPT_KEY_PROV_INFO KeyProvInfo;
  1157. memset( &KeyProvInfo, 0, sizeof( CRYPT_KEY_PROV_INFO ));
  1158. KeyProvInfo.pwszContainerName = lpContainerName;
  1159. KeyProvInfo.pwszProvName = lpProviderName;
  1160. KeyProvInfo.dwProvType = PROV_RSA_FULL;
  1161. KeyProvInfo.dwKeySpec = AT_KEYEXCHANGE;
  1162. SYSTEMTIME StartTime;
  1163. FILETIME FileTime;
  1164. LARGE_INTEGER TimeData;
  1165. SYSTEMTIME EndTime;
  1166. GetSystemTime(&StartTime);
  1167. SystemTimeToFileTime(&StartTime, &FileTime);
  1168. TimeData.LowPart = FileTime.dwLowDateTime;
  1169. TimeData.HighPart = (LONG) FileTime.dwHighDateTime;
  1170. if ( bIsDC ) {
  1171. TimeData.QuadPart += YEARCOUNT * 3;
  1172. } else {
  1173. TimeData.QuadPart += YEARCOUNT * 100;
  1174. }
  1175. FileTime.dwLowDateTime = TimeData.LowPart;
  1176. FileTime.dwHighDateTime = (DWORD) TimeData.HighPart;
  1177. FileTimeToSystemTime(&FileTime, &EndTime);
  1178. *pCertContext = CertCreateSelfSignCertificate(
  1179. hProv,
  1180. &SubjectName,
  1181. 0,
  1182. &KeyProvInfo,
  1183. NULL,
  1184. &StartTime,
  1185. &EndTime,
  1186. &certExts
  1187. );
  1188. if (*pCertContext) {
  1189. HCERTSTORE hStore;
  1190. hStore = CertOpenSystemStoreW( NULL, L"MY" );
  1191. if (hStore) {
  1192. //
  1193. // save the temp cert
  1194. //
  1195. if(CertAddCertificateContextToStore(
  1196. hStore,
  1197. *pCertContext,
  1198. CERT_STORE_ADD_NEW,
  1199. NULL) ) {
  1200. fReturn = TRUE;
  1201. } else {
  1202. rc = GetLastError();
  1203. }
  1204. CertCloseStore( hStore, 0 );
  1205. } else {
  1206. rc = GetLastError();
  1207. }
  1208. } else {
  1209. rc = GetLastError();
  1210. }
  1211. free( certExt.Value.pbData );
  1212. } else {
  1213. rc = GetLastError();
  1214. }
  1215. } else {
  1216. rc = GetLastError();
  1217. }
  1218. free( SubjectName.pbData );
  1219. } else {
  1220. rc = ERROR_NOT_ENOUGH_MEMORY;
  1221. }
  1222. } else {
  1223. rc = GetLastError();
  1224. }
  1225. free( lpDisplayInfo );
  1226. } else {
  1227. rc = ERROR_NOT_ENOUGH_MEMORY;
  1228. }
  1229. CryptDestroyKey( hKey );
  1230. } else {
  1231. rc = GetLastError();
  1232. }
  1233. CryptReleaseContext( hProv, 0 );
  1234. } else {
  1235. rc = GetLastError();
  1236. }
  1237. RpcStringFree( (unsigned short **)&lpContainerName );
  1238. } else {
  1239. rc = ERROR_NOT_ENOUGH_MEMORY;
  1240. }
  1241. SetLastError( rc );
  1242. if (!fReturn) {
  1243. if (*pCertContext) {
  1244. CertFreeCertificateContext( *pCertContext );
  1245. *pCertContext = NULL;
  1246. }
  1247. }
  1248. return( fReturn );
  1249. }
  1250. BOOL
  1251. EncodeAndAlloc(
  1252. DWORD dwEncodingType,
  1253. LPCSTR lpszStructType,
  1254. const void * pvStructInfo,
  1255. PBYTE * pbEncoded,
  1256. PDWORD pcbEncoded
  1257. )
  1258. {
  1259. BOOL b = FALSE;
  1260. if (CryptEncodeObject(
  1261. dwEncodingType,
  1262. lpszStructType,
  1263. pvStructInfo,
  1264. NULL,
  1265. pcbEncoded )) {
  1266. *pbEncoded = (PBYTE)malloc( *pcbEncoded );
  1267. if (*pbEncoded) {
  1268. if (CryptEncodeObject(
  1269. dwEncodingType,
  1270. lpszStructType,
  1271. pvStructInfo,
  1272. *pbEncoded,
  1273. pcbEncoded )) {
  1274. b = TRUE;
  1275. } else {
  1276. free( *pbEncoded );
  1277. *pbEncoded = NULL;
  1278. }
  1279. } else {
  1280. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  1281. }
  1282. }
  1283. return( b );
  1284. }
  1285. LPWSTR
  1286. MakeDNName(
  1287. VOID
  1288. )
  1289. /*++
  1290. Routine Description:
  1291. Fabricates a display name for a locally built self-signed cert
  1292. Arguments:
  1293. RecoveryKey - Specifies if this is a recovery key or not.
  1294. Return Value:
  1295. Returns a string containing a display name, or NULL.
  1296. --*/
  1297. {
  1298. LPWSTR DNName = NULL;
  1299. LPCWSTR DNNameTemplate = L"CN=%ws,L=EFS,OU=EFS File Encryption Certificate";
  1300. DWORD cbDNName = 0;
  1301. DWORD nSize = MAX_COMPUTERNAME_LENGTH + 1;
  1302. WCHAR lpComputerName[(MAX_COMPUTERNAME_LENGTH + 1) * sizeof( WCHAR )];
  1303. BOOL b = GetComputerName ( lpComputerName, &nSize );
  1304. if (b) {
  1305. cbDNName = (wcslen( DNNameTemplate ) + 1) * sizeof( WCHAR ) + (wcslen( lpComputerName ) + 1) * sizeof( WCHAR );
  1306. DNName = (LPWSTR)malloc( cbDNName );
  1307. if (DNName) {
  1308. swprintf( DNName, DNNameTemplate, lpComputerName );
  1309. } else {
  1310. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  1311. }
  1312. }
  1313. return( DNName );
  1314. }
  1315. DWORD
  1316. CreatePublicKeyInformationCertificate(
  1317. IN PSID pUserSid OPTIONAL,
  1318. PBYTE pbCert,
  1319. DWORD cbCert,
  1320. OUT PEFS_PUBLIC_KEY_INFO * PublicKeyInformation
  1321. )
  1322. {
  1323. DWORD PublicKeyInformationLength = 0;
  1324. DWORD UserSidLength = 0;
  1325. PWCHAR Base;
  1326. if (pUserSid != NULL) {
  1327. UserSidLength = GetLengthSid( pUserSid );
  1328. }
  1329. //
  1330. // Total size is the size of the public key info structure, the size of the
  1331. // cert hash data structure, the length of the thumbprint, and the lengths of the
  1332. // container name and provider name if they were passed.
  1333. //
  1334. PublicKeyInformationLength = sizeof( EFS_PUBLIC_KEY_INFO ) + UserSidLength + cbCert;
  1335. //
  1336. // Allocate and fill in the PublicKeyInformation structure
  1337. //
  1338. *PublicKeyInformation = (PEFS_PUBLIC_KEY_INFO)malloc( PublicKeyInformationLength );
  1339. if (*PublicKeyInformation == NULL) {
  1340. return( ERROR_NOT_ENOUGH_MEMORY );
  1341. }
  1342. (*PublicKeyInformation)->Length = PublicKeyInformationLength;
  1343. (*PublicKeyInformation)->KeySourceTag = (ULONG)EfsCertificate;
  1344. //
  1345. // Copy the string and SID data to the end of the structure.
  1346. //
  1347. Base = (PWCHAR)(*PublicKeyInformation);
  1348. Base = (PWCHAR)((PBYTE)Base + sizeof( EFS_PUBLIC_KEY_INFO ));
  1349. if (pUserSid != NULL) {
  1350. (*PublicKeyInformation)->PossibleKeyOwner = (ULONG)POINTER_TO_OFFSET( Base, *PublicKeyInformation );
  1351. CopySid( UserSidLength, (PSID)Base, pUserSid );
  1352. } else {
  1353. (*PublicKeyInformation)->PossibleKeyOwner = (ULONG)0;
  1354. }
  1355. Base = (PWCHAR)((PBYTE)Base + UserSidLength);
  1356. (*PublicKeyInformation)->CertificateInfo.CertificateLength = cbCert;
  1357. (*PublicKeyInformation)->CertificateInfo.Certificate = (ULONG)POINTER_TO_OFFSET( Base, *PublicKeyInformation );
  1358. memcpy( (PBYTE)Base, pbCert, cbCert );
  1359. return( ERROR_SUCCESS );
  1360. }
  1361. #if 0
  1362. BOOLEAN
  1363. Admin(
  1364. IN LSA_HANDLE LsaPolicyHandle,
  1365. IN HANDLE hToken,
  1366. OUT PSID * Sid
  1367. )
  1368. /*++
  1369. Routine Description:
  1370. This routine determines if the passed token belongs to an administrator.
  1371. If we are in a domain, the user must be a domain admin for this to succeed.
  1372. If we are standalne, the user must be in the local administrator's group.
  1373. Arguments:
  1374. hToken - Supplies the token of the user to be examined.
  1375. bDomain - Returns TRUE if the caller is a domain administrator.
  1376. Sid - Returns the Sid of the user.
  1377. Return Value:
  1378. TRUE if the user is an administrator of the type we need, FALSE otherwise.
  1379. Note that this routine does not attempt to set last error, it either works
  1380. or it doesn't.
  1381. --*/
  1382. {
  1383. NET_API_STATUS NetStatus;
  1384. PSID DomainId;
  1385. NTSTATUS Status;
  1386. BOOLEAN fReturn = FALSE;
  1387. DWORD ReturnLength;
  1388. PPOLICY_PRIMARY_DOMAIN_INFO PrimaryDomainInfo;
  1389. //
  1390. // Initialize OUT parameters
  1391. //
  1392. *Sid = NULL;
  1393. Status = NtQueryInformationToken (
  1394. hToken,
  1395. TokenGroups,
  1396. NULL,
  1397. 0,
  1398. &ReturnLength
  1399. );
  1400. if (STATUS_BUFFER_TOO_SMALL == Status) {
  1401. PTOKEN_GROUPS Groups = (PTOKEN_GROUPS)malloc( ReturnLength );
  1402. if (Groups) {
  1403. Status = NtQueryInformationToken (
  1404. hToken,
  1405. TokenGroups,
  1406. Groups,
  1407. ReturnLength,
  1408. &ReturnLength
  1409. );
  1410. if (NT_SUCCESS( Status )) {
  1411. //
  1412. // We've got the groups, build the SIDs and see if
  1413. // they're in the token.
  1414. //
  1415. //
  1416. // We're standalone
  1417. //
  1418. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  1419. PSID AdminAccountSid;
  1420. Status = RtlAllocateAndInitializeSid(
  1421. &NtAuthority,
  1422. 2,
  1423. SECURITY_BUILTIN_DOMAIN_RID,
  1424. DOMAIN_ALIAS_RID_ADMINS,
  1425. 0, 0, 0, 0, 0, 0,
  1426. &AdminAccountSid
  1427. );
  1428. if (NT_SUCCESS( Status )) {
  1429. DWORD i;
  1430. for (i=0; i<Groups->GroupCount; i++) {
  1431. if (RtlEqualSid(Groups->Groups[i].Sid, AdminAccountSid)) {
  1432. *Sid = AdminAccountSid;
  1433. fReturn = TRUE;
  1434. break;
  1435. }
  1436. }
  1437. }
  1438. }
  1439. free( Groups );
  1440. }
  1441. if (!fReturn) {
  1442. //
  1443. // Something failed, clean up any allocated OUT parameters
  1444. //
  1445. if (*Sid) {
  1446. if (*bDomain == FALSE) {
  1447. FreeSid( *Sid );
  1448. } else {
  1449. free( *Sid );
  1450. }
  1451. *Sid = NULL;
  1452. }
  1453. }
  1454. }
  1455. return( fReturn );
  1456. }
  1457. #endif
  1458. PTOKEN_USER
  1459. GetTokenUser(
  1460. HANDLE TokenHandle
  1461. )
  1462. /*++
  1463. Routine Description:
  1464. This routine returns the TOKEN_USER structure for the
  1465. current user, and optionally, the AuthenticationId from his
  1466. token.
  1467. Arguments:
  1468. AuthenticationId - Supplies an optional pointer to return the
  1469. AuthenticationId.
  1470. Return Value:
  1471. On success, returns a pointer to a TOKEN_USER structure.
  1472. On failure, returns NULL. Call GetLastError() for more
  1473. detailed error information.
  1474. --*/
  1475. {
  1476. NTSTATUS Status;
  1477. ULONG ReturnLength;
  1478. TOKEN_STATISTICS TokenStats;
  1479. PTOKEN_USER pTokenUser = NULL;
  1480. BOOLEAN b = FALSE;
  1481. Status = NtQueryInformationToken (
  1482. TokenHandle,
  1483. TokenUser,
  1484. NULL,
  1485. 0,
  1486. &ReturnLength
  1487. );
  1488. if (Status == STATUS_BUFFER_TOO_SMALL) {
  1489. pTokenUser = (PTOKEN_USER)malloc( ReturnLength );
  1490. if (pTokenUser) {
  1491. Status = NtQueryInformationToken (
  1492. TokenHandle,
  1493. TokenUser,
  1494. pTokenUser,
  1495. ReturnLength,
  1496. &ReturnLength
  1497. );
  1498. if ( NT_SUCCESS( Status )) {
  1499. //
  1500. // We're done, mark that everything worked
  1501. //
  1502. b = TRUE;
  1503. } else {
  1504. SetLastError( RtlNtStatusToDosError( Status ));
  1505. }
  1506. if (!b) {
  1507. //
  1508. // Something failed, clean up what we were going to return
  1509. //
  1510. free( pTokenUser );
  1511. pTokenUser = NULL;
  1512. }
  1513. } else {
  1514. SetLastError( RtlNtStatusToDosError( STATUS_INSUFFICIENT_RESOURCES ));
  1515. }
  1516. } else {
  1517. SetLastError( RtlNtStatusToDosError( Status ));
  1518. }
  1519. return( pTokenUser );
  1520. }
  1521. VOID
  1522. InitializeOtherPolicies(LPGROUPPOLICYOBJECT pGPO, HKEY hKeyRoot)
  1523. {
  1524. TCHAR szPath[2*MAX_PATH];
  1525. GUID guidRIClient = {0x3060e8d0, 0x7020, 0x11d2, 0x84, 0x2d, 0x0, 0xc0, 0x4f, 0xa3, 0x72, 0xd4};
  1526. GUID guidRISnap = {0x3060e8ce, 0x7020, 0x11d2, 0x84, 0x2d, 0x0, 0xc0, 0x4f, 0xa3, 0x72, 0xd4};
  1527. //
  1528. // Initialize Remote Install settings
  1529. //
  1530. if (SUCCEEDED(pGPO->GetFileSysPath (GPO_SECTION_USER, szPath, 2*MAX_PATH)))
  1531. {
  1532. lstrcat (szPath, TEXT("\\Microsoft"));
  1533. if (!CreateDirectory(szPath, NULL)) {
  1534. return;
  1535. }
  1536. lstrcat (szPath, TEXT("\\RemoteInstall"));
  1537. if (!CreateDirectory(szPath, NULL)) {
  1538. return;
  1539. }
  1540. lstrcat (szPath, TEXT("\\oscfilter.ini"));
  1541. WritePrivateProfileString(TEXT("choice"), TEXT("custom"), TEXT("0"), szPath);
  1542. WritePrivateProfileString(TEXT("choice"), TEXT("tools"), TEXT("0"), szPath);
  1543. WritePrivateProfileString(TEXT("choice"), TEXT("restart"), TEXT("0"), szPath);
  1544. pGPO->Save(FALSE, TRUE, &guidRIClient, &guidRISnap);
  1545. }
  1546. }
  1547. HRESULT
  1548. CreateEFSDefaultPolicy(
  1549. IN HANDLE hToken,
  1550. IN PUCHAR *pEfsBlob,
  1551. IN DWORD *pEfsSize,
  1552. IN PCCERT_CONTEXT *ppCertContext,
  1553. IN LPTSTR DomainName
  1554. )
  1555. /*++
  1556. Routine Description:
  1557. Creates the default domain-wide EFS recovery policy object.
  1558. Arguments:
  1559. hToken - the current logged on user's token
  1560. EfsBlob - EFS recovery policy blob
  1561. EfsSize - the size of the blob ( in bytes)
  1562. Return:
  1563. HRESULT
  1564. --*/
  1565. {
  1566. //
  1567. // bind to DS to find the domain DNS name
  1568. //
  1569. DWORD rc;
  1570. PLDAP phLdap=NULL;
  1571. PWSTR DsRootName=NULL;
  1572. rc = MyLdapOpen(&phLdap);
  1573. if ( ERROR_SUCCESS == rc ) {
  1574. rc = MyGetDsObjectRoot(
  1575. phLdap,
  1576. &DsRootName
  1577. );
  1578. if ( ERROR_SUCCESS != rc ) {
  1579. LogEvent(STATUS_SEVERITY_ERROR,
  1580. GPOEVENT_ERROR_CREATE_GPO,
  1581. IDS_ERROR_GET_DSROOT,
  1582. rc
  1583. );
  1584. }
  1585. } else {
  1586. LogEvent(STATUS_SEVERITY_ERROR,
  1587. GPOEVENT_ERROR_CREATE_GPO,
  1588. IDS_ERROR_BIND_DS,
  1589. rc
  1590. );
  1591. }
  1592. HRESULT hr = HRESULT_FROM_WIN32(rc);
  1593. // if ( SUCCEEDED(hr) && DsRootName ) {
  1594. /* Get the default recovery policy only when there is no existing one
  1595. if ( *pEfsBlob == NULL ) {
  1596. rc = GetDefaultRecoveryPolicy(hToken,
  1597. TRUE,
  1598. pEfsBlob,
  1599. pEfsSize,
  1600. ppCertContext);
  1601. if ( ERROR_SUCCESS != rc ) {
  1602. LogEvent(STATUS_SEVERITY_ERROR,
  1603. GPOEVENT_ERROR_CREATE_GPO,
  1604. IDS_ERROR_CREATE_EFSBLOB,
  1605. rc
  1606. );
  1607. }
  1608. hr = HRESULT_FROM_WIN32(rc);
  1609. }
  1610. */
  1611. // }
  1612. if ( SUCCEEDED(hr) && DsRootName) {
  1613. LPGROUPPOLICYOBJECT pEfsGPO = NULL;
  1614. //
  1615. // OLE is already initialized before this call
  1616. // create Policy Object instances
  1617. //
  1618. TCHAR szPolicyName[MAX_PATH];
  1619. pLoadResourceString(IDS_DEFAULT_EFS_POLICY,
  1620. szPolicyName,
  1621. MAX_PATH,
  1622. L"Domain EFS Recovery Policy"
  1623. );
  1624. hr = CreateGroupPolicyObjectInDomain(hToken,
  1625. DsRootName,
  1626. szPolicyName,
  1627. *pEfsBlob,
  1628. *pEfsSize,
  1629. *ppCertContext,
  1630. &pEfsGPO);
  1631. if ( FAILED(hr) ) {
  1632. //
  1633. // if any of the creation failed, delet both objects
  1634. //
  1635. if ( pEfsGPO ) {
  1636. pEfsGPO->Delete();
  1637. }
  1638. }
  1639. //
  1640. // release the instances
  1641. //
  1642. if ( pEfsGPO ) {
  1643. pEfsGPO->Release();
  1644. }
  1645. }
  1646. //
  1647. // close LDAP port
  1648. //
  1649. if ( phLdap ) {
  1650. MyLdapClose(&phLdap);
  1651. }
  1652. if ( DsRootName ) {
  1653. LocalFree(DsRootName);
  1654. }
  1655. return hr;
  1656. }
  1657. HRESULT
  1658. CreateGroupPolicyObjectInDomain(
  1659. IN HANDLE hToken,
  1660. IN PWSTR DomainNCName,
  1661. IN PWSTR GPObjectName,
  1662. IN PUCHAR EfsBlob,
  1663. IN ULONG EfsSize,
  1664. IN PCCERT_CONTEXT pCertContext,
  1665. OUT LPGROUPPOLICYOBJECT *ppObject
  1666. )
  1667. /*++
  1668. Routine Description:
  1669. Creates a group policy object in DS (and sysvol).
  1670. Arguments:
  1671. DomainNCName - The DS domain's ADSI name
  1672. GPObjectName - the display name for the group policy object to create
  1673. EfsBlob - The EFS recovery policy blob (ignored if to create default
  1674. domain policy)
  1675. EfsSize - the size of EfsBlob (in bytes)
  1676. ppObject - the created group policy object instance. This will be
  1677. released by the caller.
  1678. Return:
  1679. HRESULT
  1680. --*/
  1681. {
  1682. LPGROUPPOLICYOBJECT pGPO;
  1683. HRESULT hr = CoCreateInstance( CLSID_GroupPolicyObject,
  1684. NULL,
  1685. CLSCTX_SERVER,
  1686. IID_IGroupPolicyObject,
  1687. (PVOID *)&pGPO
  1688. );
  1689. if (SUCCEEDED(hr) && pGPO) {
  1690. LPWSTR lpPath;
  1691. //
  1692. // Build the path to the default GPO
  1693. //
  1694. lpPath = (LPWSTR) LocalAlloc (LPTR, (lstrlen(DomainNCName) + 100) * sizeof(WCHAR));
  1695. if (lpPath) {
  1696. lstrcpy (lpPath, TEXT("LDAP://CN={31B2F340-016D-11D2-945F-00C04FB984F9},CN=Policies,CN=System,"));
  1697. lstrcat (lpPath, (DomainNCName+7));
  1698. //
  1699. // Open the default GPO
  1700. //
  1701. hr = pGPO->OpenDSGPO(lpPath, GPO_OPEN_LOAD_REGISTRY);
  1702. LocalFree (lpPath);
  1703. if ( SUCCEEDED(hr) ) {
  1704. //
  1705. // save EFS blob into the object
  1706. //
  1707. HKEY hKeyPolicyRoot;
  1708. hr = pGPO->GetRegistryKey( GPO_SECTION_MACHINE,
  1709. &hKeyPolicyRoot
  1710. );
  1711. if (SUCCEEDED(hr)) {
  1712. //
  1713. // create EFS recovery policy in the registry
  1714. // open reg key CERT_EFSBLOB_REGPATH defined in wincrypt.h
  1715. //
  1716. DWORD dwDisposition;
  1717. HKEY hKey;
  1718. DWORD Win32rc;
  1719. if ( (Win32rc = RegCreateKeyEx(
  1720. hKeyPolicyRoot,
  1721. CERT_EFSBLOB_REGPATH,
  1722. 0,
  1723. TEXT("REG_SZ"),
  1724. REG_OPTION_NON_VOLATILE,
  1725. KEY_ALL_ACCESS,
  1726. NULL,
  1727. &hKey,
  1728. &dwDisposition
  1729. ) ) == ERROR_SUCCESS ) {
  1730. //
  1731. // check to see if there is EFS blob
  1732. // if not, create it.
  1733. //
  1734. DWORD RegType;
  1735. DWORD BlobSize;
  1736. PUCHAR pNewBlob=NULL;
  1737. PCCERT_CONTEXT pNewCert=NULL;
  1738. Win32rc = RegQueryValueEx(
  1739. hKey,
  1740. CERT_EFSBLOB_VALUE_NAME,
  1741. 0,
  1742. &RegType,
  1743. NULL,
  1744. &BlobSize
  1745. );
  1746. if ( Win32rc != ERROR_SUCCESS || BlobSize == 0 ) {
  1747. if ( EfsBlob == NULL ) {
  1748. Win32rc = GetDefaultRecoveryPolicy(hToken,
  1749. TRUE,
  1750. &pNewBlob,
  1751. &BlobSize,
  1752. &pNewCert);
  1753. if ( ERROR_SUCCESS != Win32rc ) {
  1754. LogEvent(STATUS_SEVERITY_ERROR,
  1755. GPOEVENT_ERROR_CREATE_GPO,
  1756. IDS_ERROR_CREATE_EFSBLOB,
  1757. Win32rc
  1758. );
  1759. }
  1760. } else {
  1761. //
  1762. // EFS blob is already created, just use it
  1763. //
  1764. pNewBlob = EfsBlob;
  1765. BlobSize = EfsSize;
  1766. pNewCert = pCertContext;
  1767. Win32rc = ERROR_SUCCESS;
  1768. }
  1769. if ( ERROR_SUCCESS == Win32rc ) {
  1770. //
  1771. // add to the cert store of this GPO first
  1772. //
  1773. CERT_SYSTEM_STORE_RELOCATE_PARA paraRelocate;
  1774. paraRelocate.hKeyBase = hKeyPolicyRoot;
  1775. paraRelocate.pwszSystemStore = L"EFS";
  1776. HCERTSTORE hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
  1777. 0,
  1778. NULL,
  1779. CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY |
  1780. CERT_SYSTEM_STORE_RELOCATE_FLAG,
  1781. (void *)&paraRelocate
  1782. );
  1783. if ( hCertStore ) {
  1784. if ( !CertAddCertificateContextToStore(
  1785. hCertStore,
  1786. pNewCert, // pCertContext,
  1787. CERT_STORE_ADD_ALWAYS,
  1788. NULL
  1789. ) ) {
  1790. Win32rc = GetLastError();
  1791. }
  1792. //
  1793. // close the store
  1794. //
  1795. CertCloseStore(hCertStore, 0);
  1796. hCertStore = NULL;
  1797. } else {
  1798. Win32rc = GetLastError();
  1799. }
  1800. if ( ERROR_SUCCESS == Win32rc ) {
  1801. //
  1802. // set EFS recovery policy binary data to registry
  1803. // open reg key CERT_EFSBLOB_REGPATH defined in wincrypt.h
  1804. //
  1805. Win32rc = RegSetValueEx(
  1806. hKey,
  1807. CERT_EFSBLOB_VALUE_NAME,
  1808. 0,
  1809. REG_BINARY,
  1810. (PBYTE)pNewBlob, // EfsBlob
  1811. BlobSize // EfsSize
  1812. );
  1813. if (Win32rc == ERROR_SUCCESS) {
  1814. hr = pGPO->Save(TRUE, TRUE, &guidExtension, &guidSnapin);
  1815. hr = pGPO->Save(TRUE, TRUE, &guidRegExt, &guidSnapin );
  1816. if ( FAILED(hr) ) {
  1817. LogEvent(STATUS_SEVERITY_ERROR,
  1818. GPOEVENT_ERROR_CREATE_GPO,
  1819. IDS_ERROR_SAVE_GPO,
  1820. hr,
  1821. GPObjectName
  1822. );
  1823. }
  1824. } else {
  1825. LogEvent(STATUS_SEVERITY_ERROR,
  1826. GPOEVENT_ERROR_CREATE_GPO,
  1827. IDS_ERROR_SAVE_EFSBLOB,
  1828. Win32rc
  1829. );
  1830. }
  1831. } else {
  1832. LogEvent(STATUS_SEVERITY_ERROR,
  1833. GPOEVENT_ERROR_CREATE_GPO,
  1834. IDS_ERROR_ADD_CERTIFICATE,
  1835. Win32rc
  1836. );
  1837. }
  1838. //
  1839. // free allocated blob and certificate
  1840. //
  1841. if ( pNewBlob != EfsBlob ) {
  1842. if ( pNewBlob ) {
  1843. free(pNewBlob);
  1844. }
  1845. if ( pNewCert ) {
  1846. CertFreeCertificateContext( pNewCert );
  1847. }
  1848. }
  1849. } else {
  1850. LogEvent(STATUS_SEVERITY_ERROR,
  1851. GPOEVENT_ERROR_CREATE_GPO,
  1852. IDS_ERROR_CREATE_EFSBLOB,
  1853. Win32rc
  1854. );
  1855. }
  1856. }
  1857. //
  1858. // close the registry key
  1859. //
  1860. RegCloseKey(hKey);
  1861. } else {
  1862. LogEvent(STATUS_SEVERITY_ERROR,
  1863. GPOEVENT_ERROR_CREATE_GPO,
  1864. IDS_ERROR_OPEN_EFSKEY,
  1865. Win32rc
  1866. );
  1867. }
  1868. if ( Win32rc != ERROR_SUCCESS ) {
  1869. hr = HRESULT_FROM_WIN32(Win32rc);
  1870. }
  1871. InitializeOtherPolicies(pGPO, hKeyPolicyRoot);
  1872. RegCloseKey(hKeyPolicyRoot);
  1873. } else {
  1874. LogEvent(STATUS_SEVERITY_ERROR,
  1875. GPOEVENT_ERROR_CREATE_GPO,
  1876. IDS_ERROR_GETGPO_REGKEY,
  1877. hr,
  1878. GPObjectName
  1879. );
  1880. }
  1881. } else {
  1882. LogEvent(STATUS_SEVERITY_ERROR,
  1883. GPOEVENT_ERROR_CREATE_GPO,
  1884. IDS_ERROR_NEW_GPO,
  1885. hr,
  1886. GPObjectName,
  1887. DomainNCName
  1888. );
  1889. }
  1890. }
  1891. } else {
  1892. LogEvent(STATUS_SEVERITY_ERROR,
  1893. GPOEVENT_ERROR_CREATE_GPO,
  1894. IDS_ERROR_CREATE_GPO_INSTANCE,
  1895. hr
  1896. );
  1897. }
  1898. if ( SUCCEEDED(hr) ) {
  1899. *ppObject = pGPO;
  1900. } else if ( pGPO ) {
  1901. //
  1902. // failed, release the instance
  1903. //
  1904. pGPO->Release();
  1905. }
  1906. return hr;
  1907. }
  1908. DWORD
  1909. MyGetDsObjectRoot(
  1910. IN PLDAP pLdap,
  1911. OUT PWSTR *pDsRootName
  1912. )
  1913. /*++
  1914. Routine Description:
  1915. Get the root domain name of the current domain. The returned domain's
  1916. name is in ADSI format, for example,
  1917. LDAP://DC=test_dom,DC=ntdev,DC=microsoft,DC=com
  1918. Arguments:
  1919. pLdap - the ldap handle
  1920. pDsRootName - the domain's ADSI name to output
  1921. Return:
  1922. Win32 error
  1923. --*/
  1924. {
  1925. DWORD retErr;
  1926. LDAPMessage *Message = NULL; // for LDAP calls.
  1927. PWSTR Attribs[2]; // for LDAP calls.
  1928. if ( pLdap == NULL || pDsRootName == NULL ) {
  1929. return(ERROR_INVALID_PARAMETER);
  1930. }
  1931. Attribs[0] = L"defaultNamingContext";
  1932. Attribs[1] = NULL;
  1933. retErr = ldap_search_s(pLdap,
  1934. L"",
  1935. LDAP_SCOPE_BASE,
  1936. L"(objectClass=*)",
  1937. Attribs,
  1938. 0,
  1939. &Message);
  1940. if( Message ) { // should not check for error code
  1941. retErr = ERROR_SUCCESS;
  1942. LDAPMessage *Entry = NULL;
  1943. //
  1944. // read the first entry.
  1945. // we did base level search, we have only one entry.
  1946. // Entry does not need to be freed (it is freed with the message)
  1947. //
  1948. Entry = ldap_first_entry(pLdap, Message);
  1949. if(Entry != NULL) {
  1950. PWSTR *Values = ldap_get_values(pLdap, Entry, Attribs[0]);
  1951. if(Values != NULL) {
  1952. //
  1953. // should only get one value for the default naming context
  1954. // Values[0] here is the DN.
  1955. //
  1956. *pDsRootName = (PWSTR)LocalAlloc(0, (wcslen(Values[0])+1+7)*sizeof(WCHAR));
  1957. if ( *pDsRootName ) {
  1958. swprintf(*pDsRootName, L"LDAP://%s\0", Values[0]);
  1959. } else {
  1960. retErr = ERROR_NOT_ENOUGH_MEMORY;
  1961. }
  1962. ldap_value_free(Values);
  1963. } else
  1964. retErr = LdapMapErrorToWin32(pLdap->ld_errno);
  1965. } else
  1966. retErr = LdapMapErrorToWin32(pLdap->ld_errno);
  1967. ldap_msgfree(Message);
  1968. Message = NULL;
  1969. }
  1970. return(retErr);
  1971. }
  1972. DWORD
  1973. MyLdapOpen(
  1974. OUT PLDAP *pLdap
  1975. )
  1976. /*++
  1977. Routine Description:
  1978. Open a LDAP port and bind to it.
  1979. Arguments:
  1980. pLdap - the ldap handle to output
  1981. Return:
  1982. Win32 error
  1983. --*/
  1984. {
  1985. DWORD Win32rc;
  1986. WCHAR sysName[256];
  1987. DWORD dSize = (sizeof(sysName) / sizeof(sysName[0]));
  1988. if ( pLdap == NULL ) {
  1989. return(ERROR_INVALID_PARAMETER);
  1990. }
  1991. //
  1992. // get current computer and IP address
  1993. //
  1994. if ( !GetComputerName(sysName, &dSize) ) {
  1995. Win32rc = GetLastError();
  1996. } else {
  1997. PDOMAIN_CONTROLLER_INFOW DCInfo; // for DsGetDcName
  1998. HINSTANCE hDsGetDcDll = LoadLibrary(TEXT("netapi32.dll"));
  1999. PFNDSGETDCNAME pfnDsGetDcName=NULL;
  2000. if ( hDsGetDcDll) {
  2001. #if defined(UNICODE)
  2002. pfnDsGetDcName = (PFNDSGETDCNAME)GetProcAddress(hDsGetDcDll,
  2003. "DsGetDcNameW");
  2004. #else
  2005. pfnDsGetDcName = (PFNDSGETDCNAME)GetProcAddress(hDsGetDcDll,
  2006. "DsGetDcNameA");
  2007. #endif
  2008. }
  2009. if ( pfnDsGetDcName ) {
  2010. Win32rc = (*pfnDsGetDcName)(sysName,
  2011. NULL,
  2012. NULL,
  2013. NULL,
  2014. DS_IP_REQUIRED,
  2015. &DCInfo
  2016. );
  2017. } else {
  2018. Win32rc = ERROR_PROC_NOT_FOUND;
  2019. }
  2020. if ( hDsGetDcDll ) {
  2021. FreeLibrary(hDsGetDcDll);
  2022. }
  2023. if(Win32rc == ERROR_SUCCESS) {
  2024. PWSTR pwszAddress = DCInfo[0].DomainControllerAddress;
  2025. if(*pwszAddress == L'\\') {
  2026. pwszAddress += 2;
  2027. }
  2028. //
  2029. // bind to ldap
  2030. //
  2031. *pLdap = ldap_open(pwszAddress, LDAP_PORT);
  2032. if ( *pLdap == NULL ) {
  2033. Win32rc = ERROR_FILE_NOT_FOUND;
  2034. } else {
  2035. Win32rc = ldap_bind_s(*pLdap,
  2036. NULL,
  2037. NULL,
  2038. LDAP_AUTH_SSPI);
  2039. }
  2040. //
  2041. // free DCInfo
  2042. //
  2043. LocalFree(DCInfo);
  2044. }
  2045. }
  2046. return(Win32rc);
  2047. }
  2048. DWORD
  2049. MyLdapClose(
  2050. IN PLDAP *pLdap
  2051. )
  2052. /*++
  2053. Routine Description:
  2054. Close the LDAP bind.
  2055. Arguments:
  2056. pLdap - the ldap handle
  2057. Return:
  2058. Win32 error
  2059. --*/
  2060. {
  2061. if ( pLdap != NULL ) {
  2062. //
  2063. // unbind pLDAP
  2064. //
  2065. if ( *pLdap != NULL )
  2066. ldap_unbind(*pLdap);
  2067. *pLdap = NULL;
  2068. }
  2069. return(ERROR_SUCCESS);
  2070. }
  2071. //*************************************************************
  2072. // Routines to handle events
  2073. //*************************************************************
  2074. BOOL InitializeEvents (void)
  2075. /*++
  2076. Routine Description:
  2077. Opens the event log
  2078. Arguments:
  2079. None
  2080. Return:
  2081. TRUE if successful
  2082. FALSE if an error occurs
  2083. --*/
  2084. {
  2085. //
  2086. // Open the event source
  2087. //
  2088. hEventLog = RegisterEventSource(NULL, EventSourceName);
  2089. if (hEventLog) {
  2090. return TRUE;
  2091. }
  2092. return FALSE;
  2093. }
  2094. int
  2095. LogEvent(
  2096. IN DWORD LogLevel,
  2097. IN DWORD dwEventID,
  2098. IN UINT idMsg,
  2099. ...)
  2100. /*++
  2101. Routine Description:
  2102. Logs a verbose event to the event log
  2103. Arguments:
  2104. bLogLevel - the severity level of the log
  2105. STATUS_SEVERITY_SUCCESS
  2106. STATUS_SEVERITY_INFORMATIONAL
  2107. STATUS_SEVERITY_WARNING
  2108. STATUS_SEVERITY_ERROR
  2109. dwEventID - the event ID (defined in uevents.mc)
  2110. idMsg - Message id
  2111. Return:
  2112. TRUE if successful
  2113. FALSE if an error occurs
  2114. --*/
  2115. {
  2116. TCHAR szMsg[MAX_PATH];
  2117. TCHAR szErrorMsg[2*MAX_PATH+40];
  2118. LPTSTR aStrings[2];
  2119. WORD wType;
  2120. va_list marker;
  2121. //
  2122. // Load the message
  2123. //
  2124. if (idMsg != 0) {
  2125. pLoadResourceString(idMsg, szMsg, MAX_PATH,
  2126. TEXT("Error loading resource string. Params : %x"));
  2127. } else {
  2128. lstrcpy (szMsg, TEXT("%s"));
  2129. }
  2130. //
  2131. // Plug in the arguments
  2132. //
  2133. szErrorMsg[0] = L'\0';
  2134. va_start(marker, idMsg);
  2135. __try {
  2136. wvsprintf(szErrorMsg, szMsg, marker);
  2137. } __except(EXCEPTION_EXECUTE_HANDLER) {
  2138. }
  2139. va_end(marker);
  2140. //
  2141. // Check for the event log being open.
  2142. //
  2143. if (!hEventLog) {
  2144. if (!InitializeEvents()) {
  2145. return -1;
  2146. }
  2147. }
  2148. //
  2149. // Report the event to the eventlog
  2150. //
  2151. aStrings[0] = szErrorMsg;
  2152. switch (LogLevel) {
  2153. case STATUS_SEVERITY_WARNING:
  2154. wType = EVENTLOG_WARNING_TYPE;
  2155. break;
  2156. case STATUS_SEVERITY_SUCCESS:
  2157. wType = EVENTLOG_SUCCESS;
  2158. break;
  2159. case STATUS_SEVERITY_ERROR:
  2160. wType = EVENTLOG_ERROR_TYPE;
  2161. break;
  2162. default:
  2163. wType = EVENTLOG_INFORMATION_TYPE;
  2164. break;
  2165. }
  2166. if (!ReportEvent(hEventLog,
  2167. wType,
  2168. 0,
  2169. dwEventID,
  2170. NULL,
  2171. 1,
  2172. 0,
  2173. (LPCTSTR *)aStrings,
  2174. NULL) ) {
  2175. return 1;
  2176. }
  2177. return 0;
  2178. }
  2179. BOOL
  2180. ShutdownEvents (void)
  2181. /*++
  2182. Routine Description:
  2183. Stops the event log
  2184. Arguments:
  2185. None
  2186. Return:
  2187. TRUE if successful
  2188. FALSE if an error occurs
  2189. --*/
  2190. {
  2191. BOOL bRetVal = TRUE;
  2192. if (hEventLog) {
  2193. bRetVal = DeregisterEventSource(hEventLog);
  2194. hEventLog = NULL;
  2195. }
  2196. return bRetVal;
  2197. }
  2198. LPWSTR
  2199. GetCertDisplayInformation(
  2200. IN PCCERT_CONTEXT pCertContext
  2201. )
  2202. /*++
  2203. Routine Description:
  2204. Returns the display string from the passed certificate context.
  2205. Arguments:
  2206. pCertContext - Supplies a pointer to an open certificate context.
  2207. Return Value:
  2208. On success, pointer to display string. Caller must call
  2209. free() to free.
  2210. NULL on failure.
  2211. --*/
  2212. {
  2213. DWORD Format = CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG;
  2214. //
  2215. // First, try to get the email name
  2216. //
  2217. DWORD cchNameString;
  2218. LPWSTR wszNameString = NULL;
  2219. cchNameString = CertGetNameString(
  2220. pCertContext,
  2221. CERT_NAME_RDN_TYPE,
  2222. 0,
  2223. &Format,
  2224. NULL,
  2225. 0
  2226. );
  2227. if (cchNameString != 1) {
  2228. //
  2229. // String was found
  2230. //
  2231. wszNameString = (LPWSTR)malloc( cchNameString * sizeof( WCHAR ));
  2232. if (wszNameString) {
  2233. cchNameString = CertGetNameString(
  2234. pCertContext,
  2235. CERT_NAME_RDN_TYPE,
  2236. 0,
  2237. &Format,
  2238. wszNameString,
  2239. cchNameString
  2240. );
  2241. } else {
  2242. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  2243. }
  2244. } else {
  2245. //
  2246. // This shouldn't happen. If it does, we'll return NULL.
  2247. // Try to complain about it.
  2248. //
  2249. ASSERT( FALSE );
  2250. }
  2251. return( wszNameString );
  2252. }
  2253. BOOLEAN
  2254. IsSelfSignedPolicyExpired(
  2255. IN PRECOVERY_POLICY_1_1 RecoveryPolicy OPTIONAL
  2256. )
  2257. /*++
  2258. Routine Description:
  2259. This routine checks if the existing recovery cert expiring within one year
  2260. Arguments:
  2261. PolicyEfsInfo - Supplies a pointer to the current EFS recovery policy.
  2262. Return Value:
  2263. return-value - TRUE if it is within one year
  2264. --*/
  2265. {
  2266. BOOLEAN GetNewCert = TRUE;
  2267. if (RecoveryPolicy == NULL) {
  2268. //
  2269. // We need to create a new one if none exists.
  2270. //
  2271. return TRUE;
  2272. }
  2273. if (RecoveryPolicy->RecoveryPolicyHeader.RecoveryKeyCount > 1){
  2274. //
  2275. // Default recovery policy changed.
  2276. //
  2277. return FALSE;
  2278. }
  2279. __try {
  2280. //
  2281. // Scan the recovery data looking for recovery keys in a format we understand
  2282. //
  2283. PEFS_PUBLIC_KEY_INFO PublicKeyInfo = &((PRECOVERY_KEY_1_1) &(RecoveryPolicy->RecoveryKeyList[0]))->PublicKeyInfo;
  2284. if (PublicKeyInfo->KeySourceTag != EfsCertificate) {
  2285. //
  2286. // Out dated recovery cert. Get a new one
  2287. //
  2288. return TRUE;
  2289. }
  2290. PBYTE pbCert = (PBYTE)OFFSET_TO_POINTER(CertificateInfo.Certificate, PublicKeyInfo);
  2291. DWORD cbCert = PublicKeyInfo->CertificateInfo.CertificateLength;
  2292. PCCERT_CONTEXT pCertContext = CertCreateCertificateContext(
  2293. CRYPT_ASN_ENCODING,
  2294. (const PBYTE)pbCert,
  2295. cbCert);
  2296. if (pCertContext) {
  2297. SYSTEMTIME CertTime;
  2298. SYSTEMTIME CrntTime;
  2299. if (FileTimeToSystemTime(&(pCertContext->pCertInfo->NotAfter), &CertTime)){
  2300. GetSystemTime( &CrntTime);
  2301. if ( CertTime.wYear <= CrntTime.wYear + 1) {
  2302. //
  2303. // Get the display information
  2304. //
  2305. LPWSTR lpDisplayInfo = GetCertDisplayInformation( pCertContext );
  2306. if (lpDisplayInfo ) {
  2307. if (!wcstok( lpDisplayInfo, L"OU=EFS File Encryption Certificate" )){
  2308. GetNewCert = FALSE;
  2309. }
  2310. free(lpDisplayInfo);
  2311. }
  2312. } else {
  2313. GetNewCert = FALSE;
  2314. }
  2315. }
  2316. CertFreeCertificateContext( pCertContext );
  2317. }
  2318. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2319. //
  2320. // There was something wrong with the recovery policy.
  2321. // Get a new recovery cert.
  2322. //
  2323. }
  2324. return GetNewCert;
  2325. }