Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1116 lines
25 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: backup.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. #include <pch.cpp>
  11. #pragma hdrstop
  12. #include "certbcli.h"
  13. #define __dwFILE__ __dwFILE_CERTUTIL_BACKUP_CPP__
  14. HRESULT
  15. verbDynamicFileList(
  16. IN WCHAR const *pwszOption,
  17. IN WCHAR const *pwszArg1,
  18. IN WCHAR const *pwszArg2,
  19. IN WCHAR const *pwszArg3,
  20. IN WCHAR const *pwszArg4)
  21. {
  22. HRESULT hr;
  23. HRESULT hr2;
  24. BOOL fServerOnline;
  25. HCSBC hcsbc;
  26. BOOL fBegin = FALSE;
  27. WCHAR *pwszzFileList = NULL;
  28. DWORD cbList;
  29. WCHAR const *pwsz;
  30. BOOL fImpersonating = FALSE;
  31. if (!ImpersonateSelf(SecurityImpersonation))
  32. {
  33. hr = myHLastError();
  34. _JumpError(hr, error, "ImpersonateSelf");
  35. }
  36. fImpersonating = TRUE;
  37. hr = myEnablePrivilege(SE_BACKUP_NAME, TRUE);
  38. _JumpIfError(hr, error, "myEnablePrivilege");
  39. hr = CertSrvIsServerOnline(g_pwszConfig, &fServerOnline);
  40. _JumpIfError(hr, error, "CertSrvIsServerOnline");
  41. //wprintf(L"Cert Server Online -> %d\n", fServerOnline);
  42. if (!fServerOnline)
  43. {
  44. hr = HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE);
  45. _JumpError(hr, error, "CertSrvIsServerOnline");
  46. }
  47. hr = CertSrvRestorePrepare(g_pwszConfig, 0, &hcsbc);
  48. _JumpIfError(hr, error, "CertSrvRestorePrepare");
  49. fBegin = TRUE;
  50. hr = CertSrvBackupGetDynamicFileList(hcsbc, &pwszzFileList, &cbList);
  51. _JumpIfError(hr, error, "CertSrvBackupGetDynamicFileList");
  52. for (pwsz = pwszzFileList; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  53. {
  54. wprintf(
  55. L"%x: %ws\n",
  56. SAFE_SUBTRACT_POINTERS((BYTE *) pwsz, (BYTE *) pwszzFileList),
  57. pwsz);
  58. }
  59. wprintf(L"%x\n", cbList);
  60. error:
  61. if (fBegin)
  62. {
  63. hr2 = CertSrvRestoreEnd(hcsbc);
  64. _PrintIfError(hr, "CertSrvRestoreEnd");
  65. }
  66. if (NULL != pwszzFileList)
  67. {
  68. CertSrvBackupFree(pwszzFileList);
  69. }
  70. if (fImpersonating)
  71. {
  72. myEnablePrivilege(SE_BACKUP_NAME, FALSE);
  73. RevertToSelf();
  74. }
  75. return(hr);
  76. }
  77. HRESULT
  78. verbDatabaseLocations(
  79. IN WCHAR const *pwszOption,
  80. IN WCHAR const *pwszArg1,
  81. IN WCHAR const *pwszArg2,
  82. IN WCHAR const *pwszArg3,
  83. IN WCHAR const *pwszArg4)
  84. {
  85. HRESULT hr;
  86. HRESULT hr2;
  87. BOOL fServerOnline;
  88. HCSBC hcsbc;
  89. BOOL fBegin = FALSE;
  90. WCHAR *pwszzFileList = NULL;
  91. DWORD cbList;
  92. WCHAR const *pwsz;
  93. BOOL fImpersonating = FALSE;
  94. if (!ImpersonateSelf(SecurityImpersonation))
  95. {
  96. hr = myHLastError();
  97. _JumpError(hr, error, "ImpersonateSelf");
  98. }
  99. fImpersonating = TRUE;
  100. hr = myEnablePrivilege(SE_BACKUP_NAME, TRUE);
  101. _JumpIfError(hr, error, "myEnablePrivilege");
  102. hr = CertSrvIsServerOnline(g_pwszConfig, &fServerOnline);
  103. _JumpIfError(hr, error, "CertSrvIsServerOnline");
  104. //wprintf(L"Cert Server Online -> %d\n", fServerOnline);
  105. if (!fServerOnline)
  106. {
  107. hr = HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE);
  108. _JumpError(hr, error, "CertSrvIsServerOnline");
  109. }
  110. hr = CertSrvBackupPrepare(g_pwszConfig, 0, CSBACKUP_TYPE_FULL, &hcsbc);
  111. _JumpIfError(hr, error, "CertSrvBackupPrepare");
  112. fBegin = TRUE;
  113. hr = CertSrvRestoreGetDatabaseLocations(hcsbc, &pwszzFileList, &cbList);
  114. _JumpIfError(hr, error, "CertSrvRestoreGetDatabaseLocations");
  115. for (pwsz = pwszzFileList; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  116. {
  117. wprintf(
  118. L"%x: %02x %ws\n",
  119. SAFE_SUBTRACT_POINTERS((BYTE *) pwsz, (BYTE *) pwszzFileList),
  120. *pwsz,
  121. &pwsz[1]);
  122. }
  123. wprintf(L"%x\n", cbList);
  124. error:
  125. if (fBegin)
  126. {
  127. hr2 = CertSrvBackupEnd(hcsbc);
  128. _PrintIfError(hr, "CertSrvBackupEnd");
  129. }
  130. if (NULL != pwszzFileList)
  131. {
  132. CertSrvBackupFree(pwszzFileList);
  133. }
  134. if (fImpersonating)
  135. {
  136. myEnablePrivilege(SE_BACKUP_NAME, FALSE);
  137. RevertToSelf();
  138. }
  139. return(hr);
  140. }
  141. DWORD
  142. DBSetFlags(
  143. IN WCHAR const *pwszType,
  144. IN OUT DWORD *pFlags)
  145. {
  146. HRESULT hr;
  147. if (NULL != pwszType)
  148. {
  149. if (0 == LSTRCMPIS(pwszType, L"Incremental"))
  150. {
  151. *pFlags |= CDBBACKUP_INCREMENTAL;
  152. }
  153. else
  154. if (0 == LSTRCMPIS(pwszType, L"KeepLog"))
  155. {
  156. *pFlags |= CDBBACKUP_KEEPOLDLOGS;
  157. }
  158. else
  159. {
  160. hr = E_INVALIDARG;
  161. _JumpError2(hr, error, "bad type", hr);
  162. }
  163. }
  164. hr = S_OK;
  165. error:
  166. return(hr);
  167. }
  168. HRESULT
  169. verbBackup(
  170. IN WCHAR const *pwszOption,
  171. IN WCHAR const *pwszBackupDir,
  172. IN WCHAR const *pwszType1,
  173. IN WCHAR const *pwszType2,
  174. IN WCHAR const *pwszArg4)
  175. {
  176. HRESULT hr;
  177. DWORD Flags = 0;
  178. hr = verbBackupPFX(pwszOption, pwszBackupDir, NULL, NULL, NULL);
  179. _JumpIfError(hr, error, "verbBackupPFX");
  180. hr = verbBackupDB(pwszOption, pwszBackupDir, pwszType1, pwszType2, NULL);
  181. _JumpIfError(hr, error, "verbBackupDB");
  182. error:
  183. return(hr);
  184. }
  185. typedef struct _CUBACKUP
  186. {
  187. IN DWORD Flags;
  188. IN WCHAR const *pwszBackupDir;
  189. OUT DBBACKUPPROGRESS *pdbp;
  190. } CUBACKUP;
  191. DWORD
  192. cuBackupThread(
  193. OPTIONAL IN OUT VOID *pvparms)
  194. {
  195. HRESULT hr;
  196. CUBACKUP *pparms = (CUBACKUP *) pvparms;
  197. CSASSERT(NULL != pparms);
  198. hr = myBackupDB(
  199. g_pwszConfig,
  200. pparms->Flags,
  201. pparms->pwszBackupDir,
  202. pparms->pdbp);
  203. _JumpIfError(hr, error, "myBackupDB");
  204. error:
  205. return(hr);
  206. }
  207. DWORD
  208. cuRestoreThread(
  209. OPTIONAL IN OUT VOID *pvparms)
  210. {
  211. HRESULT hr;
  212. CUBACKUP *pparms = (CUBACKUP *) pvparms;
  213. CSASSERT(NULL != pparms);
  214. hr = myRestoreDB(
  215. g_pwszConfig,
  216. pparms->Flags,
  217. pparms->pwszBackupDir,
  218. NULL,
  219. NULL,
  220. NULL,
  221. pparms->pdbp);
  222. _JumpIfError(hr, error, "myRestoreDB");
  223. error:
  224. return(hr);
  225. }
  226. VOID
  227. cuBackupRestoreProgress(
  228. IN BOOL fRestore,
  229. IN BOOL fIncremental,
  230. IN BOOL fKeepLogs,
  231. OPTIONAL IN DBBACKUPPROGRESS const *pdbp)
  232. {
  233. DWORD id;
  234. DWORD dw;
  235. static DWORD s_LastValue;
  236. static DWORD s_LastState;
  237. static DWORD s_State;
  238. static DWORD s_EndState;
  239. static BOOL s_fDone;
  240. if (NULL == pdbp)
  241. {
  242. s_State = fIncremental? 1 : 0; // Incremental starts with log files
  243. s_LastState = s_State - 1;
  244. s_LastValue = MAXDWORD;
  245. // Restore or KeepLogs ends with log files
  246. s_EndState = (fRestore || fKeepLogs)? 1 : 2;
  247. s_fDone = FALSE;
  248. }
  249. else
  250. {
  251. BOOL fPrint;
  252. switch (s_State)
  253. {
  254. case 0:
  255. dw = pdbp->dwDBPercentComplete;
  256. id = fRestore?
  257. IDS_RESTOREPROGRESSDB : // "Restoring Database files"
  258. IDS_BACKUPPROGRESSDB; // "Backing up Database files"
  259. break;
  260. case 1:
  261. dw = pdbp->dwLogPercentComplete;
  262. id = fRestore?
  263. IDS_RESTOREPROGRESSLOG : // "Restoring Log files"
  264. IDS_BACKUPPROGRESSLOG; // "Backing up Log files"
  265. break;
  266. default:
  267. dw = pdbp->dwTruncateLogPercentComplete;
  268. CSASSERT(!fRestore);
  269. id = IDS_BACKUPPROGRESSTRUNCATELOG; // "Truncating Logs"
  270. break;
  271. }
  272. fPrint = s_LastState != s_State || s_LastValue != dw;
  273. #if 0
  274. if (g_fVerbose)
  275. {
  276. wprintf(
  277. L"\n%ws %d %3u%% -- %d %3u%% -- %3u %3u %3u%ws",
  278. fPrint? L"+" : L"-",
  279. s_LastState,
  280. s_LastValue,
  281. s_State,
  282. dw,
  283. pdbp->dwDBPercentComplete,
  284. pdbp->dwLogPercentComplete,
  285. pdbp->dwTruncateLogPercentComplete,
  286. fPrint? L"\n" : L"");
  287. }
  288. #endif
  289. if (fPrint)
  290. {
  291. wprintf(L"\r%ws: %u%%", myLoadResourceString(id), dw);
  292. }
  293. s_LastState = s_State;
  294. s_LastValue = dw;
  295. if (!s_fDone && 100 <= dw)
  296. {
  297. wprintf(wszNewLine);
  298. if (s_EndState == s_State)
  299. {
  300. s_fDone = TRUE;
  301. }
  302. else if (s_EndState > s_State)
  303. {
  304. s_State++;
  305. cuBackupRestoreProgress(
  306. fRestore,
  307. fIncremental,
  308. fKeepLogs,
  309. pdbp);
  310. }
  311. }
  312. }
  313. }
  314. DWORD
  315. cuBackupRestoreDB(
  316. IN BOOL fRestore,
  317. IN DWORD Flags,
  318. IN WCHAR const *pwszBackupDir)
  319. {
  320. HRESULT hr = S_OK;
  321. DBBACKUPPROGRESS dbp;
  322. CUBACKUP parms;
  323. HANDLE hThread = NULL;
  324. DWORD ThreadId;
  325. BOOL fIncremental = 0 != (CDBBACKUP_INCREMENTAL & Flags);
  326. BOOL fKeepLogs = 0 != (CDBBACKUP_KEEPOLDLOGS & Flags);
  327. parms.Flags = Flags;
  328. parms.pwszBackupDir = pwszBackupDir;
  329. parms.pdbp = &dbp;
  330. ZeroMemory(&dbp, sizeof(dbp));
  331. hThread = CreateThread(
  332. NULL, // lpThreadAttributes (Security Attr)
  333. 0, // dwStackSize
  334. fRestore? cuRestoreThread : cuBackupThread,
  335. &parms, // lpParameter
  336. 0, // dwCreationFlags
  337. &ThreadId);
  338. if (NULL == hThread)
  339. {
  340. hr = myHLastError();
  341. _JumpError(hr, error, "CreateThread");
  342. }
  343. DBGPRINT((DBG_SS_CERTUTILI, "Backup Thread = %x\n", ThreadId));
  344. // Wait for the backup thread to return.
  345. cuBackupRestoreProgress(fRestore, fIncremental, fKeepLogs, NULL);
  346. while (TRUE)
  347. {
  348. hr = WaitForSingleObject(hThread, 500);
  349. DBGPRINT((DBG_SS_CERTUTILI, "Wait for backup returns %x\n", hr));
  350. cuBackupRestoreProgress(fRestore, fIncremental, fKeepLogs, &dbp);
  351. if ((HRESULT) WAIT_OBJECT_0 == hr)
  352. {
  353. // Backup thread returned.
  354. if (!GetExitCodeThread(hThread, (DWORD *) &hr))
  355. {
  356. hr = myHLastError();
  357. _JumpError(hr, error, "GetExitCodeThread");
  358. }
  359. DBGPRINT((DBG_SS_CERTUTILI, "Backup thread exit: %x\n", hr));
  360. _JumpIfError(hr, error, "cuBackupThread");
  361. break; // Backup Thread terminated successfully
  362. }
  363. // Wait failed. Why?
  364. if ((HRESULT) WAIT_TIMEOUT != hr)
  365. {
  366. _JumpError(hr, error, "WaitForSingleObject");
  367. }
  368. // Worker thread still busy. Wait again...
  369. }
  370. error:
  371. DBGPRINT((DBG_SS_CERTUTILI, "cuBackupThread returns %x\n", hr));
  372. if (NULL != hThread)
  373. {
  374. CloseHandle(hThread);
  375. }
  376. return(hr);
  377. }
  378. HRESULT
  379. verbBackupDB(
  380. IN WCHAR const *pwszOption,
  381. IN WCHAR const *pwszBackupDir,
  382. IN WCHAR const *pwszType1,
  383. IN WCHAR const *pwszType2,
  384. IN WCHAR const *pwszArg4)
  385. {
  386. HRESULT hr;
  387. DWORD Flags = 0;
  388. hr = DBSetFlags(pwszType1, &Flags);
  389. _JumpIfError(hr, error, "DBSetFlags");
  390. hr = DBSetFlags(pwszType2, &Flags);
  391. _JumpIfError(hr, error, "DBSetFlags");
  392. if (g_fForce)
  393. {
  394. Flags |= CDBBACKUP_OVERWRITE;
  395. }
  396. wprintf(
  397. myLoadResourceString(
  398. (CDBBACKUP_INCREMENTAL & Flags)?
  399. IDS_FORMAT_BACKEDUPDBNOFULL : // "Incremental database backup for %ws."
  400. IDS_FORMAT_BACKEDUPDBFULL), // "Full database backup for %ws."
  401. g_pwszConfig);
  402. wprintf(wszNewLine);
  403. hr = myBackupDB(g_pwszConfig, (Flags|CDBBACKUP_VERIFYONLY), pwszBackupDir, NULL);
  404. if (S_OK != hr)
  405. {
  406. wprintf(
  407. myLoadResourceString(IDS_FORMAT_INVALIDBACKUPDIR), // "Not a valid backup target directory: %ws."
  408. pwszBackupDir);
  409. wprintf(wszNewLine);
  410. _JumpError(hr, error, "myBackupDB");
  411. }
  412. // Perfom the actual backup:
  413. hr = cuBackupRestoreDB(FALSE, Flags, pwszBackupDir);
  414. _JumpIfError(hr, error, "cuBackupRestoreDB");
  415. Flags &= ~CDBBACKUP_OVERWRITE;
  416. Flags |= CDBBACKUP_VERIFYONLY;
  417. hr = myRestoreDB(
  418. g_pwszConfig,
  419. Flags,
  420. pwszBackupDir,
  421. NULL,
  422. NULL,
  423. NULL,
  424. NULL);
  425. if (S_OK != hr)
  426. {
  427. wprintf(
  428. myLoadResourceString(IDS_FORMAT_BADBACKUPRESULTS), // "Backup content verification failed: %ws."
  429. pwszBackupDir);
  430. wprintf(wszNewLine);
  431. _JumpError(hr, error, "myRestoreDB");
  432. }
  433. wprintf(
  434. myLoadResourceString(IDS_FORMAT_BACKEDUPDB), // "Backed up database to %ws."
  435. pwszBackupDir);
  436. wprintf(wszNewLine);
  437. wprintf(
  438. myLoadResourceString(
  439. (CDBBACKUP_KEEPOLDLOGS & Flags)?
  440. IDS_FORMAT_BACKEDUPDBKEEP : // "Database logs were preserved."
  441. IDS_FORMAT_BACKEDUPDBNOKEEP)); // "Database logs successfully truncated."
  442. wprintf(wszNewLine);
  443. error:
  444. return(hr);
  445. }
  446. // Leave out quotes, commas, backslash
  447. #define wszPASSWORDCHARSETPUNCT \
  448. L"!#$%&()*+-./:;<=>?@[]^_{|}~"
  449. WCHAR const s_awcPasswordCharSet[] =
  450. L"0123456789"
  451. L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  452. L"abcdefghijklmnopqrstuvwxyz"
  453. wszPASSWORDCHARSETPUNCT;
  454. #define cwcPASSWORDCHARSET WSZARRAYSIZE(s_awcPasswordCharSet)
  455. #define cwcPASSWORDCHARSETALPHANUM (cwcPASSWORDCHARSET - WSZARRAYSIZE(wszPASSWORDCHARSETPUNCT))
  456. HRESULT
  457. cuGeneratePassword(
  458. IN DWORD cwcMax,
  459. OUT WCHAR *pwszPassword,
  460. IN DWORD cwcPassword)
  461. {
  462. HRESULT hr;
  463. HCRYPTPROV hProv = NULL;
  464. BYTE abPassword[cwcAUTOPASSWORDMAX];
  465. BYTE abIndex[sizeof(abPassword)];
  466. DWORD i;
  467. DWORD cwcPunctuation;
  468. DWORD cwcCharSet;
  469. if (!CryptAcquireContext(
  470. &hProv,
  471. NULL, // pwszContainer
  472. NULL, // pwszProvName
  473. PROV_RSA_FULL,
  474. CRYPT_VERIFYCONTEXT))
  475. {
  476. hr = myHLastError();
  477. _JumpError(hr, error, "CryptAcquireContext");
  478. }
  479. if (1 == cwcMax || sizeof(abPassword) < cwcMax)
  480. {
  481. cwcMax = sizeof(abPassword);
  482. }
  483. CSASSERT(sizeof(abPassword) < cwcPassword);
  484. if (cwcMax > cwcPassword)
  485. {
  486. cwcMax = cwcPassword;
  487. }
  488. if (!CryptGenRandom(hProv, cwcMax, abPassword))
  489. {
  490. hr = myHLastError();
  491. _JumpError(hr, error, "CryptGenRandom");
  492. }
  493. if (!CryptGenRandom(hProv, cwcMax, abIndex))
  494. {
  495. hr = myHLastError();
  496. _JumpError(hr, error, "CryptGenRandom");
  497. }
  498. // Generate at most min(1, cwcMax / 8) punctuation characters.
  499. cwcCharSet = cwcPASSWORDCHARSET;
  500. cwcPunctuation = cwcMax / 8;
  501. ZeroMemory(pwszPassword, sizeof(WCHAR) * (1 + cwcMax)); // initialization, not clearing it out
  502. for (i = 0; i < cwcMax; i++)
  503. {
  504. DWORD iwc = abPassword[i] % cwcCharSet;
  505. DWORD itgt = abIndex[i] % cwcMax;
  506. CSASSERT(wcslen(pwszPassword) < cwcMax);
  507. while (L'\0' != pwszPassword[itgt])
  508. {
  509. if (++itgt == cwcMax)
  510. {
  511. itgt = 0;
  512. }
  513. }
  514. pwszPassword[itgt] = s_awcPasswordCharSet[iwc];
  515. if (cwcPASSWORDCHARSETALPHANUM <= iwc)
  516. {
  517. if (0 < cwcPunctuation)
  518. {
  519. cwcPunctuation--;
  520. }
  521. if (0 == cwcPunctuation)
  522. {
  523. cwcCharSet = cwcPASSWORDCHARSETALPHANUM;
  524. }
  525. }
  526. }
  527. hr = S_OK;
  528. error:
  529. SecureZeroMemory(abPassword, sizeof(abPassword)); // password data
  530. if (NULL != hProv)
  531. {
  532. CryptReleaseContext(hProv, 0);
  533. }
  534. return(hr);
  535. }
  536. HRESULT
  537. cuGetPasswordString(
  538. IN LONG idMsg,
  539. OUT WCHAR *pwszPassword,
  540. IN DWORD cwcPassword)
  541. {
  542. HRESULT hr;
  543. WCHAR *pwsz;
  544. WCHAR *pwszLast;
  545. LONG wc;
  546. HANDLE hConsole;
  547. DWORD InputMode = FILE_TYPE_UNKNOWN;
  548. DWORD ConsoleMode;
  549. // Prompt for password, making sure password isn't echoed.
  550. // If the stdin is redirected, don't bother querying/changing console mode.
  551. wprintf(L"%ws ", myLoadResourceString(idMsg));
  552. fflush(stdout);
  553. hConsole = GetStdHandle(STD_INPUT_HANDLE);
  554. if (INVALID_HANDLE_VALUE != hConsole)
  555. {
  556. InputMode = GetFileType(hConsole);
  557. if (FILE_TYPE_CHAR == InputMode)
  558. {
  559. GetConsoleMode(hConsole, &ConsoleMode);
  560. SetConsoleMode(
  561. hConsole,
  562. ~ENABLE_ECHO_INPUT & ConsoleMode);
  563. //~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT) & ConsoleMode);
  564. }
  565. }
  566. pwsz = pwszPassword;
  567. pwszLast = &pwsz[cwcPassword - 1];
  568. while (TRUE)
  569. {
  570. wc = _fgetwchar();
  571. if (WEOF == wc || L'\r' == wc || L'\n' == wc)
  572. {
  573. break;
  574. }
  575. if (L'\b' == wc)
  576. {
  577. if (pwsz == pwszPassword)
  578. {
  579. continue; // don't backup buffer or console display
  580. }
  581. pwsz--;
  582. }
  583. else
  584. {
  585. if (pwsz >= pwszLast)
  586. {
  587. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  588. goto error;
  589. }
  590. *pwsz++ = (WCHAR) wc;
  591. wc = L'*';
  592. }
  593. //_fputwchar((WCHAR) wc);
  594. //fflush(stdout);
  595. }
  596. CSASSERT(&pwszPassword[cwcPassword] > pwsz);
  597. *pwsz = L'\0';
  598. hr = S_OK;
  599. error:
  600. if (FILE_TYPE_CHAR == InputMode)
  601. {
  602. SetConsoleMode(hConsole, ConsoleMode);
  603. }
  604. wprintf(wszNewLine);
  605. return(hr);
  606. }
  607. HRESULT
  608. cuGetPassword(
  609. OPTIONAL IN UINT idsPrompt,
  610. OPTIONAL IN WCHAR const *pwszfn,
  611. OPTIONAL IN WCHAR const *pwszPasswordIn,
  612. IN BOOL fVerify,
  613. OUT WCHAR *pwszPasswordBuf,
  614. IN DWORD cwcPasswordBuf,
  615. OUT WCHAR const **ppwszPasswordOut)
  616. {
  617. HRESULT hr;
  618. WCHAR wszPassword2[MAX_PATH];
  619. CSASSERT(ARRAYSIZE(wszPassword2) == cwcPasswordBuf);
  620. if (NULL != pwszPasswordIn && 0 != wcscmp(L"*", pwszPasswordIn))
  621. {
  622. if (fVerify &&
  623. L'?' == *pwszPasswordIn &&
  624. L'\0' == pwszPasswordIn[wcsspn(pwszPasswordIn, L"?")])
  625. {
  626. hr = cuGeneratePassword(
  627. wcslen(pwszPasswordIn),
  628. pwszPasswordBuf,
  629. cwcPasswordBuf);
  630. _JumpIfError(hr, error, "cuGeneratePassword");
  631. wprintf(L"PASSWORD: \"%ws\"\n", pwszPasswordBuf);
  632. *ppwszPasswordOut = pwszPasswordBuf;
  633. }
  634. else
  635. {
  636. *ppwszPasswordOut = pwszPasswordIn;
  637. }
  638. }
  639. else
  640. {
  641. if (0 != idsPrompt)
  642. {
  643. wprintf(myLoadResourceString(idsPrompt), pwszfn);
  644. wprintf(wszNewLine);
  645. }
  646. while (TRUE)
  647. {
  648. hr = cuGetPasswordString(
  649. fVerify? IDS_NEWPASSWORDPROMPT : IDS_PASSWORDPROMPT,
  650. pwszPasswordBuf,
  651. cwcPasswordBuf);
  652. _JumpIfError(hr, error, "cuGetPasswordString");
  653. if (!fVerify)
  654. {
  655. break;
  656. }
  657. hr = cuGetPasswordString(
  658. IDS_CONFIRMPASSWORDPROMPT,
  659. wszPassword2,
  660. ARRAYSIZE(wszPassword2));
  661. _JumpIfError(hr, error, "cuGetPasswordString");
  662. if (0 == wcscmp(pwszPasswordBuf, wszPassword2))
  663. {
  664. break;
  665. }
  666. wprintf(myLoadResourceString(IDS_NOCONFIRMPASSWORD));
  667. wprintf(wszNewLine);
  668. }
  669. *ppwszPasswordOut = pwszPasswordBuf;
  670. }
  671. hr = S_OK;
  672. error:
  673. SecureZeroMemory(wszPassword2, sizeof(wszPassword2)); // password data
  674. return(hr);
  675. }
  676. HRESULT
  677. cuGetLocalCANameFromConfig(
  678. OPTIONAL OUT WCHAR **ppwszMachine,
  679. OPTIONAL OUT WCHAR **ppwszCA)
  680. {
  681. HRESULT hr;
  682. DWORD cwc;
  683. WCHAR *pwsz;
  684. WCHAR *pwszMachine = NULL;
  685. WCHAR *pwszCA = NULL;
  686. if (NULL != ppwszCA)
  687. {
  688. *ppwszCA = NULL;
  689. }
  690. pwsz = wcschr(g_pwszConfig, L'\\');
  691. if (NULL == pwsz)
  692. {
  693. hr = E_INVALIDARG;
  694. _JumpError(hr, error, "bad config string");
  695. }
  696. cwc = SAFE_SUBTRACT_POINTERS(pwsz, g_pwszConfig);
  697. pwszMachine = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  698. if (NULL == pwszMachine)
  699. {
  700. hr = E_OUTOFMEMORY;
  701. _JumpError(hr, error, "LocalAlloc");
  702. }
  703. CopyMemory(pwszMachine, g_pwszConfig, cwc * sizeof(WCHAR));
  704. pwszMachine[cwc] = L'\0';
  705. if (0 != mylstrcmpiL(pwszMachine, g_pwszDnsName) &&
  706. 0 != mylstrcmpiL(pwszMachine, g_pwszOldName))
  707. {
  708. hr = E_INVALIDARG;
  709. _JumpError(hr, error, "config string not local");
  710. }
  711. pwsz++;
  712. cwc = wcslen(pwsz);
  713. if (NULL != ppwszCA)
  714. {
  715. pwszCA = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  716. if (NULL == pwszCA)
  717. {
  718. hr = E_OUTOFMEMORY;
  719. _JumpError(hr, error, "LocalAlloc");
  720. }
  721. wcscpy(pwszCA, pwsz);
  722. }
  723. if (NULL != ppwszMachine)
  724. {
  725. *ppwszMachine = pwszMachine;
  726. pwszMachine = NULL;
  727. }
  728. if (NULL != ppwszCA)
  729. {
  730. *ppwszCA = pwszCA;
  731. pwszCA = NULL;
  732. }
  733. hr = S_OK;
  734. error:
  735. if (NULL != pwszMachine)
  736. {
  737. LocalFree(pwszMachine);
  738. }
  739. if (NULL != pwszCA)
  740. {
  741. LocalFree(pwszCA);
  742. }
  743. return(hr);
  744. }
  745. HRESULT
  746. verbBackupPFX(
  747. IN WCHAR const *pwszOption,
  748. IN WCHAR const *pwszBackupDir,
  749. IN WCHAR const *pwszArg2,
  750. IN WCHAR const *pwszArg3,
  751. IN WCHAR const *pwszArg4)
  752. {
  753. HRESULT hr;
  754. WCHAR const *pwszPassword;
  755. WCHAR wszPassword[MAX_PATH];
  756. WCHAR *pwszMachine = NULL;
  757. WCHAR *pwszCA = NULL;
  758. WCHAR *pwszPFXFileOut = NULL;
  759. hr = cuGetLocalCANameFromConfig(&pwszMachine, &pwszCA);
  760. _JumpIfError(hr, error, "cuGetLocalCANameFromConfig");
  761. hr = cuGetPassword(
  762. 0, // idsPrompt
  763. NULL, // pwszfn
  764. g_pwszPassword,
  765. TRUE, // fVerify
  766. wszPassword,
  767. ARRAYSIZE(wszPassword),
  768. &pwszPassword);
  769. _JumpIfError(hr, error, "cuGetPassword");
  770. hr = myCertServerExportPFX(
  771. pwszCA,
  772. pwszBackupDir,
  773. pwszPassword,
  774. !g_fWeakPFX, // fEnhancedStrength
  775. g_fForce, // fForceOverWrite
  776. TRUE, // fMustExportPrivateKeys
  777. g_dwmsTimeout,
  778. &pwszPFXFileOut);
  779. _JumpIfError(hr, error, "myCertServerExportPFX");
  780. wprintf(
  781. myLoadResourceString(IDS_FORMAT_BACKEDUP), // "Backed up keys and certificates for %ws\\%ws to %ws."
  782. pwszMachine,
  783. pwszCA,
  784. pwszPFXFileOut);
  785. wprintf(wszNewLine);
  786. error:
  787. SecureZeroMemory(wszPassword, sizeof(wszPassword)); // password data
  788. if (NULL != pwszPFXFileOut)
  789. {
  790. LocalFree(pwszPFXFileOut);
  791. }
  792. if (NULL != pwszMachine)
  793. {
  794. LocalFree(pwszMachine);
  795. }
  796. if (NULL != pwszCA)
  797. {
  798. LocalFree(pwszCA);
  799. }
  800. return(hr);
  801. }
  802. HRESULT
  803. verbRestore(
  804. IN WCHAR const *pwszOption,
  805. IN WCHAR const *pwszBackupDir,
  806. IN WCHAR const *pwszArg2,
  807. IN WCHAR const *pwszArg3,
  808. IN WCHAR const *pwszArg4)
  809. {
  810. HRESULT hr;
  811. hr = verbRestorePFX(pwszOption, pwszBackupDir, NULL, NULL, NULL);
  812. _JumpIfError(hr, error, "verbRestorePFX");
  813. hr = verbRestoreDB(pwszOption, pwszBackupDir, NULL, NULL, NULL);
  814. _JumpIfError(hr, error, "verbRestoreDB");
  815. error:
  816. return(hr);
  817. }
  818. HRESULT
  819. verbRestoreDB(
  820. IN WCHAR const *pwszOption,
  821. IN WCHAR const *pwszBackupDir,
  822. IN WCHAR const *pwszArg2,
  823. IN WCHAR const *pwszArg3,
  824. IN WCHAR const *pwszArg4)
  825. {
  826. HRESULT hr;
  827. DWORD Flags;
  828. hr = cuGetLocalCANameFromConfig(NULL, NULL);
  829. _JumpIfError(hr, error, "cuGetLocalCANameFromConfig");
  830. wprintf(
  831. myLoadResourceString(IDS_FORMAT_RESTOREDB), // "Restoring database for %ws."
  832. g_pwszConfig);
  833. wprintf(wszNewLine);
  834. Flags = CDBBACKUP_VERIFYONLY;
  835. if (g_fForce)
  836. {
  837. Flags |= CDBBACKUP_OVERWRITE;
  838. }
  839. while (TRUE)
  840. {
  841. hr = myRestoreDB(
  842. g_pwszConfig,
  843. Flags,
  844. pwszBackupDir,
  845. NULL,
  846. NULL,
  847. NULL,
  848. NULL);
  849. if (S_OK == hr)
  850. {
  851. break;
  852. }
  853. if (!(CDBBACKUP_INCREMENTAL & Flags))
  854. {
  855. Flags |= CDBBACKUP_INCREMENTAL;
  856. continue;
  857. }
  858. wprintf(
  859. myLoadResourceString(IDS_FORMAT_INVALIDRESTOREDIR), // "Not a valid backup directory: %ws."
  860. pwszBackupDir);
  861. wprintf(wszNewLine);
  862. _JumpError(hr, error, "myRestoreDB");
  863. }
  864. Flags &= ~CDBBACKUP_VERIFYONLY;
  865. // Perfom the actual restore:
  866. hr = cuBackupRestoreDB(TRUE, Flags, pwszBackupDir);
  867. _JumpIfError(hr, error, "cuBackupRestoreDB");
  868. wprintf(
  869. myLoadResourceString(
  870. (CDBBACKUP_INCREMENTAL & Flags)?
  871. IDS_FORMAT_RESTOREDDBNOFULL : // "Incremental database restore for %ws."
  872. IDS_FORMAT_RESTOREDDBFULL), // "Full database restore for %ws."
  873. g_pwszConfig);
  874. wprintf(wszNewLine);
  875. wprintf(
  876. myLoadResourceString(IDS_FORMAT_RESTORE_NEEDS_RESTART), // "Stop and Start the Certificate Server to complete database restore from %ws."
  877. pwszBackupDir);
  878. wprintf(wszNewLine);
  879. error:
  880. return(hr);
  881. }
  882. HRESULT
  883. verbRestorePFX(
  884. IN WCHAR const *pwszOption,
  885. IN WCHAR const *pwszBackupDirOrPFXFile,
  886. IN WCHAR const *pwszArg2,
  887. IN WCHAR const *pwszArg3,
  888. IN WCHAR const *pwszArg4)
  889. {
  890. HRESULT hr;
  891. WCHAR const *pwszPassword;
  892. WCHAR wszPassword[MAX_PATH];
  893. WCHAR *pwszCommonName = NULL;
  894. WCHAR *pwszPFXFile = NULL;
  895. hr = cuGetPassword(
  896. 0, // idsPrompt
  897. NULL, // pwszfn
  898. g_pwszPassword,
  899. FALSE, // fVerify
  900. wszPassword,
  901. ARRAYSIZE(wszPassword),
  902. &pwszPassword);
  903. _JumpIfError(hr, error, "cuGetPassword");
  904. hr = myCertServerImportPFX(
  905. pwszBackupDirOrPFXFile,
  906. pwszPassword,
  907. g_fForce,
  908. &pwszCommonName,
  909. &pwszPFXFile,
  910. NULL);
  911. if (!g_fForce && HRESULT_FROM_WIN32(ERROR_FILE_EXISTS) == hr)
  912. {
  913. wprintf(
  914. myLoadResourceString(IDS_FORMAT_USE_FORCE), // "Certificate or key exists. Use the %ws option to overwrite."
  915. L"-f");
  916. wprintf(wszNewLine);
  917. }
  918. _JumpIfError(hr, error, "myCertServerImportPFX");
  919. wprintf(
  920. myLoadResourceString(IDS_FORMAT_RESTORED), // "Restored keys and certificates for %ws\\%ws from %ws."
  921. g_pwszDnsName,
  922. pwszCommonName,
  923. pwszPFXFile);
  924. wprintf(wszNewLine);
  925. error:
  926. SecureZeroMemory(wszPassword, sizeof(wszPassword)); // password data
  927. if (NULL != pwszPFXFile)
  928. {
  929. LocalFree(pwszPFXFile);
  930. }
  931. if (NULL != pwszCommonName)
  932. {
  933. LocalFree(pwszCommonName);
  934. }
  935. return(hr);
  936. }
  937. // #define DO_VECTOR_TEST
  938. HRESULT
  939. verbMACFile(
  940. IN WCHAR const *pwszOption,
  941. IN WCHAR const *pwszBackupFile,
  942. IN WCHAR const *pwszArg2,
  943. IN WCHAR const *pwszArg3,
  944. IN WCHAR const *pwszArg4)
  945. {
  946. HRESULT hr;
  947. CAutoLPWSTR pwszMAC;
  948. hr = myComputeMAC(pwszBackupFile, &pwszMAC);
  949. _JumpIfError(hr, error, "myComputeMAC");
  950. wprintf(
  951. myLoadResourceString(IDS_FORMAT_HASHFILEOUTPUT), // "SHA-1 hash of file %ws:"
  952. pwszBackupFile);
  953. wprintf(wszNewLine);
  954. wprintf(L"%ws\n", pwszMAC);
  955. error:
  956. return hr;
  957. }