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.

1977 lines
54 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1999 - 1999
  3. Module Name:
  4. pwdui.c
  5. Abstract:
  6. This module contains routines for displaying Data Protection API
  7. related UI, originating from client process address space.
  8. For the future, there is support planned for causing UI to originate
  9. from the secure desktop, via Secure Authentication Sequence (SAS).
  10. Author:
  11. Scott Field (sfield) 12-May-99
  12. --*/
  13. #define UNICODE
  14. #define _UNICODE
  15. #include <nt.h>
  16. #include <ntrtl.h>
  17. #include <nturtl.h>
  18. #include <windows.h>
  19. #include <wincrypt.h>
  20. #include <sha.h>
  21. #include <unicode5.h>
  22. #include "resource.h"
  23. #include "pwdui.h"
  24. typedef struct {
  25. DATA_BLOB *pDataIn; // input DATA_BLOB* to CryptProtect or CryptUnprotect
  26. CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct; // PromptStruct describing UI operations to perform
  27. LPWSTR szDataDescription; // Application supplied data descr
  28. PBYTE rgbPasswordHash; // resultant passwordhash for strong security
  29. BOOL fCachedPassword; // did we find password in cache?
  30. BOOL fProtect; // protect or unprotect?
  31. BOOL fValidPassword; // does rgbPasswordHash contain a valid value?
  32. } DIALOGARGS, *PDIALOGARGS, *LPDIALOGARGS;
  33. typedef struct {
  34. LIST_ENTRY Next;
  35. LUID LogonId;
  36. FILETIME ftLastAccess;
  37. BYTE rgbDataInHash[A_SHA_DIGEST_LEN];
  38. BYTE rgbPasswordHash[A_SHA_DIGEST_LEN];
  39. } PASSWORD_CACHE_ENTRY, *PPASSWORD_CACHE_ENTRY, *LPPASSWORD_CACHE_ENTRY;
  40. DWORD
  41. ProtectUIConfirm(
  42. IN DIALOGARGS *pDialogArgs
  43. );
  44. DWORD
  45. UnprotectUIConfirm(
  46. IN DIALOGARGS *pDialogArgs
  47. );
  48. BOOL
  49. ChooseSecurityLevel(
  50. IN HWND hWndParent,
  51. IN DIALOGARGS *pDialogArgs
  52. );
  53. VOID
  54. AdvancedSecurityDetails(
  55. IN HWND hWndParent,
  56. IN DIALOGARGS *pDialogArgs
  57. );
  58. //
  59. // dialog box handling routines.
  60. //
  61. INT_PTR
  62. CALLBACK
  63. DialogConfirmProtect(
  64. HWND hDlg, // handle to dialog box
  65. UINT message, // message
  66. WPARAM wParam, // first message parameter
  67. LPARAM lParam // second message parameter
  68. );
  69. INT_PTR
  70. CALLBACK
  71. DialogConfirmAccess(
  72. HWND hDlg, // handle to dialog box
  73. UINT message, // message
  74. WPARAM wParam, // first message parameter
  75. LPARAM lParam // second message parameter
  76. );
  77. INT_PTR
  78. CALLBACK
  79. DialogChooseSecurityLevel(
  80. HWND hDlg, // handle to dialog box
  81. UINT message, // message
  82. WPARAM wParam, // first message parameter
  83. LPARAM lParam // second message parameter
  84. );
  85. INT_PTR
  86. CALLBACK
  87. DialogChooseSecurityLevelMedium(
  88. HWND hDlg, // handle to dialog box
  89. UINT message, // message
  90. WPARAM wParam, // first message parameter
  91. LPARAM lParam // second message parameter
  92. );
  93. INT_PTR
  94. CALLBACK
  95. DialogChooseSecurityLevelHigh(
  96. HWND hDlg, // handle to dialog box
  97. UINT message, // message
  98. WPARAM wParam, // first message parameter
  99. LPARAM lParam // second message parameter
  100. );
  101. INT_PTR
  102. CALLBACK
  103. DialogAdvancedSecurityDetails(
  104. HWND hDlg, // handle to dialog box
  105. UINT message, // message
  106. WPARAM wParam, // first message parameter
  107. LPARAM lParam // second message parameter
  108. );
  109. //
  110. // helper routines.
  111. //
  112. #ifndef SSAlloc
  113. #define SSAlloc(x) LocalAlloc(LMEM_FIXED, x)
  114. #endif
  115. #ifndef SSFree
  116. #define SSFree(x) LocalFree(x)
  117. #endif
  118. VOID
  119. ComputePasswordHash(
  120. IN PVOID pvPassword,
  121. IN DWORD cbPassword,
  122. IN OUT BYTE rgbPasswordHash[A_SHA_DIGEST_LEN]
  123. );
  124. BOOL
  125. GetEffectiveLogonId(
  126. IN OUT LUID *pLogonId
  127. );
  128. BOOL
  129. InitializeDetailGlobals(
  130. VOID
  131. );
  132. //
  133. // password cache related routines.
  134. //
  135. BOOL
  136. InitializeProtectPasswordCache(
  137. VOID
  138. );
  139. VOID
  140. DeleteProtectPasswordCache(
  141. VOID
  142. );
  143. BOOL
  144. AddProtectPasswordCache(
  145. IN DATA_BLOB* pDataIn,
  146. IN BYTE rgbPassword[A_SHA_DIGEST_LEN]
  147. );
  148. BOOL
  149. SearchProtectPasswordCache(
  150. IN DATA_BLOB* pDataIn,
  151. IN OUT BYTE rgbPassword[A_SHA_DIGEST_LEN],
  152. IN BOOL fDeleteFoundEntry
  153. );
  154. VOID
  155. PurgeProtectPasswordCache(
  156. VOID
  157. );
  158. BOOL
  159. IsCachePWAllowed(
  160. VOID
  161. );
  162. //
  163. // global variables.
  164. //
  165. HINSTANCE g_hInstProtectUI;
  166. CRITICAL_SECTION g_csProtectPasswordCache;
  167. LIST_ENTRY g_ProtectPasswordCache;
  168. #define ALLOW_CACHE_UNKNOWN 0
  169. #define ALLOW_CACHE_NO 1
  170. #define ALLOW_CACHE_YES 2
  171. DWORD g_dwAllowCachePW = 0;
  172. WCHAR g_szGooPassword[] = L"(*&#$(^(#%^))(*&(^(*{}_SAF^^%";
  173. BOOL g_fDetailGlobalsInitialized = FALSE;
  174. LPWSTR g_szDetailApplicationName = NULL;
  175. LPWSTR g_szDetailApplicationPath = NULL;
  176. BOOL
  177. WINAPI
  178. ProtectUI_DllMain(
  179. HINSTANCE hinstDLL, // handle to DLL module
  180. DWORD fdwReason, // reason for calling function
  181. LPVOID lpvReserved // reserved
  182. )
  183. {
  184. BOOL fRet = TRUE;
  185. if( fdwReason == DLL_PROCESS_ATTACH ) {
  186. g_hInstProtectUI = hinstDLL;
  187. fRet = InitializeProtectPasswordCache();
  188. } else if ( fdwReason == DLL_PROCESS_DETACH ) {
  189. DeleteProtectPasswordCache();
  190. }
  191. return fRet;
  192. }
  193. DWORD
  194. WINAPI
  195. I_CryptUIProtect(
  196. IN PVOID pvReserved1,
  197. IN PVOID pvReserved2,
  198. IN DWORD dwReserved3,
  199. IN PVOID *pvReserved4,
  200. IN BOOL fReserved5,
  201. IN PVOID pvReserved6
  202. )
  203. {
  204. DIALOGARGS DialogArgs;
  205. DWORD dwLastError = ERROR_SUCCESS;
  206. DATA_BLOB* pDataIn = (DATA_BLOB*)pvReserved1;
  207. CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct = (CRYPTPROTECT_PROMPTSTRUCT*)pvReserved2;
  208. DWORD dwFlags = (DWORD)dwReserved3;
  209. LPCWSTR szDescription = (LPCWSTR)*pvReserved4;
  210. BOOL fProtectOperation = (BOOL)fReserved5;
  211. PBYTE rgbPasswordHash = (PBYTE)pvReserved6;
  212. BOOL fEmptyDescription;
  213. //
  214. // for protect:
  215. // szDescription, if NULL or empty, get from user
  216. // if PROMPT_STRONG is set, grey out medium security.
  217. //
  218. // for unprotect:
  219. // szDescription, get from datablob.
  220. // pPromptStruct->dwPromptFlags from datablob.
  221. // if PROMPT_STRONG is set, enable password field and
  222. //
  223. if( pPromptStruct == NULL )
  224. return ERROR_INVALID_PARAMETER;
  225. if( pPromptStruct->cbSize != sizeof( CRYPTPROTECT_PROMPTSTRUCT) )
  226. return ERROR_INVALID_PARAMETER;
  227. if( fProtectOperation ) {
  228. //
  229. // if unprotect was specified, protect is implicitly specified.
  230. // vice-versa is true, too.
  231. //
  232. if ( ((pPromptStruct->dwPromptFlags & CRYPTPROTECT_PROMPT_ON_PROTECT) == 0) &&
  233. ((pPromptStruct->dwPromptFlags & CRYPTPROTECT_PROMPT_ON_UNPROTECT) == 0)
  234. )
  235. {
  236. //
  237. // nothing to do, bail out.
  238. //
  239. return ERROR_SUCCESS;
  240. }
  241. pPromptStruct->dwPromptFlags |= CRYPTPROTECT_PROMPT_ON_PROTECT;
  242. pPromptStruct->dwPromptFlags |= CRYPTPROTECT_PROMPT_ON_UNPROTECT;
  243. }
  244. if ( dwFlags & CRYPTPROTECT_UI_FORBIDDEN ) {
  245. return ERROR_PASSWORD_RESTRICTION;
  246. }
  247. //
  248. // build dialog box arguments block.
  249. //
  250. DialogArgs.pDataIn = pDataIn;
  251. DialogArgs.pPromptStruct = pPromptStruct;
  252. if( szDescription != NULL && szDescription[0] != L'\0' ) {
  253. DialogArgs.szDataDescription = (LPWSTR)szDescription;
  254. fEmptyDescription = FALSE;
  255. } else {
  256. DialogArgs.szDataDescription = NULL;
  257. fEmptyDescription = TRUE;
  258. }
  259. DialogArgs.rgbPasswordHash = rgbPasswordHash;
  260. DialogArgs.fCachedPassword = FALSE;
  261. DialogArgs.fProtect = fProtectOperation;
  262. DialogArgs.fValidPassword = FALSE;
  263. if( fProtectOperation ) {
  264. //
  265. // now, throw the UI for the protect operation.
  266. //
  267. dwLastError = ProtectUIConfirm( &DialogArgs );
  268. if( dwLastError == ERROR_SUCCESS && fEmptyDescription &&
  269. DialogArgs.szDataDescription ) {
  270. //
  271. // output modified data description to caller.
  272. //
  273. *pvReserved4 = DialogArgs.szDataDescription;
  274. }
  275. } else {
  276. //
  277. // now, throw the UI for the unprotect operation.
  278. //
  279. dwLastError = UnprotectUIConfirm( &DialogArgs );
  280. }
  281. if( fEmptyDescription && dwLastError != ERROR_SUCCESS &&
  282. DialogArgs.szDataDescription ) {
  283. SSFree( DialogArgs.szDataDescription );
  284. }
  285. return dwLastError;
  286. }
  287. DWORD
  288. WINAPI
  289. I_CryptUIProtectFailure(
  290. IN PVOID pvReserved1,
  291. IN DWORD dwReserved2,
  292. IN PVOID *pvReserved3)
  293. {
  294. CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct = (CRYPTPROTECT_PROMPTSTRUCT*)pvReserved1;
  295. DWORD dwFlags = (DWORD)dwReserved2;
  296. LPCWSTR szDescription = (LPCWSTR)*pvReserved3;
  297. WCHAR szTitle[512];
  298. WCHAR szText[512];
  299. if((pPromptStruct->dwPromptFlags & CRYPTPROTECT_PROMPT_ON_UNPROTECT) == 0)
  300. {
  301. return ERROR_SUCCESS;
  302. }
  303. if(dwFlags & CRYPTPROTECT_UI_FORBIDDEN)
  304. {
  305. return ERROR_PASSWORD_RESTRICTION;
  306. }
  307. LoadStringU(g_hInstProtectUI, IDS_PROTECT_DECRYPTION_ERROR, szTitle, sizeof(szTitle)/sizeof(WCHAR));
  308. LoadStringU(g_hInstProtectUI, IDS_PROTECT_CANNOT_DECRYPT, szText, sizeof(szText)/sizeof(WCHAR));
  309. MessageBoxU(pPromptStruct->hwndApp, szText, szTitle, MB_OK | MB_ICONWARNING);
  310. return ERROR_SUCCESS;
  311. }
  312. DWORD
  313. ProtectUIConfirm(
  314. IN DIALOGARGS *pDialogArgs
  315. )
  316. {
  317. INT_PTR iRet;
  318. iRet = DialogBoxParamU(
  319. g_hInstProtectUI,
  320. MAKEINTRESOURCE(IDD_PROTECT_CONFIRM_PROTECT),
  321. pDialogArgs->pPromptStruct->hwndApp,
  322. DialogConfirmProtect,
  323. (LPARAM)pDialogArgs
  324. );
  325. return (DWORD)iRet;
  326. }
  327. DWORD
  328. UnprotectUIConfirm(
  329. IN DIALOGARGS *pDialogArgs
  330. )
  331. {
  332. INT_PTR iRet;
  333. iRet = DialogBoxParamU(
  334. g_hInstProtectUI,
  335. MAKEINTRESOURCE(IDD_PROTECT_CONFIRM_SECURITY),
  336. pDialogArgs->pPromptStruct->hwndApp,
  337. DialogConfirmAccess,
  338. (LPARAM)pDialogArgs
  339. );
  340. return (DWORD)iRet;
  341. }
  342. INT_PTR
  343. CALLBACK
  344. DialogConfirmProtect(
  345. HWND hDlg, // handle to dialog box
  346. UINT message, // message
  347. WPARAM wParam, // first message parameter
  348. LPARAM lParam // second message parameter
  349. )
  350. {
  351. DIALOGARGS *pDialogArgs;
  352. CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct;
  353. switch (message)
  354. {
  355. case WM_INITDIALOG:
  356. {
  357. SetLastError( 0 ); // as per win32 documentation
  358. if(SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)lParam) == 0) {
  359. if(GetLastError() != ERROR_SUCCESS) {
  360. EndDialog(hDlg, GetLastError());
  361. return FALSE;
  362. }
  363. }
  364. // lParam is DIALOGARGS *
  365. pDialogArgs = (DIALOGARGS*)lParam;
  366. pPromptStruct = pDialogArgs->pPromptStruct;
  367. //
  368. // set the dialog title
  369. //
  370. SetWindowTextU(hDlg, pPromptStruct->szPrompt);
  371. //
  372. // display dynamic stuff.
  373. //
  374. SendMessage( hDlg, WM_COMMAND, IDC_PROTECT_UPDATE_DYNAMIC, 0 );
  375. return FALSE; // don't default the Focus..
  376. } // WM_INITDIALOG
  377. case WM_COMMAND:
  378. {
  379. switch(LOWORD(wParam))
  380. {
  381. case IDOK:
  382. {
  383. EndDialog(hDlg, ERROR_SUCCESS);
  384. return TRUE;
  385. }
  386. case IDCANCEL:
  387. {
  388. EndDialog(hDlg, ERROR_CANCELLED);
  389. return TRUE;
  390. }
  391. case IDC_PROTECT_ADVANCED:
  392. {
  393. pDialogArgs = (DIALOGARGS*)GetWindowLongPtr(
  394. hDlg,
  395. GWLP_USERDATA
  396. );
  397. if(pDialogArgs == NULL)
  398. break; // TODO: bail out
  399. //
  400. // show details dialog.
  401. //
  402. AdvancedSecurityDetails(
  403. hDlg,
  404. pDialogArgs
  405. );
  406. return FALSE;
  407. }
  408. case IDC_PROTECT_UPDATE_DYNAMIC:
  409. {
  410. WCHAR szResource[ 256 ];
  411. int cchResource = sizeof(szResource) / sizeof(WCHAR);
  412. UINT ResourceId;
  413. pDialogArgs = (DIALOGARGS*)GetWindowLongPtr(
  414. hDlg,
  415. GWLP_USERDATA
  416. );
  417. if(pDialogArgs == NULL)
  418. break; // TODO: bail out
  419. pPromptStruct = pDialogArgs->pPromptStruct;
  420. //
  421. // description.
  422. //
  423. SetWindowTextU(GetDlgItem(hDlg, IDC_PROTECT_LABEL_EDIT1), pDialogArgs->szDataDescription);
  424. // Disable the OK button if we're defaulting to strong protection,
  425. // unless a password has already been set.
  426. if((pPromptStruct->dwPromptFlags & (CRYPTPROTECT_PROMPT_STRONG |
  427. CRYPTPROTECT_PROMPT_REQUIRE_STRONG)) &&
  428. (pDialogArgs->fValidPassword == FALSE))
  429. {
  430. EnableWindow( GetDlgItem(hDlg, IDOK), FALSE );
  431. SendMessage(hDlg, DM_SETDEFID, IDC_PROTECT_CHANGE_SECURITY, 0);
  432. SetFocus(GetDlgItem(hDlg, IDC_PROTECT_CHANGE_SECURITY));
  433. }
  434. else
  435. {
  436. EnableWindow( GetDlgItem(hDlg, IDOK), TRUE );
  437. SendMessage(hDlg, DM_SETDEFID, IDOK,0);
  438. SetFocus(GetDlgItem(hDlg, IDOK));
  439. }
  440. //
  441. // security level.
  442. //
  443. if( pPromptStruct->dwPromptFlags & (CRYPTPROTECT_PROMPT_STRONG |
  444. CRYPTPROTECT_PROMPT_REQUIRE_STRONG))
  445. {
  446. ResourceId = IDS_PROTECT_SECURITY_LEVEL_SET_HIGH;
  447. } else {
  448. ResourceId = IDS_PROTECT_SECURITY_LEVEL_SET_MEDIUM;
  449. }
  450. cchResource = LoadStringU(g_hInstProtectUI,
  451. ResourceId,
  452. szResource,
  453. cchResource
  454. );
  455. SetWindowTextU( GetDlgItem(hDlg,IDC_PROTECT_SECURITY_LEVEL),
  456. szResource
  457. );
  458. return FALSE;
  459. }
  460. case IDC_PROTECT_CHANGE_SECURITY:
  461. {
  462. pDialogArgs = (DIALOGARGS*)GetWindowLongPtr(
  463. hDlg,
  464. GWLP_USERDATA
  465. );
  466. if(pDialogArgs == NULL)
  467. break; // TODO: bail out
  468. //
  469. // spawn child dialog to handle prompting for security level.
  470. //
  471. if(!ChooseSecurityLevel( hDlg, pDialogArgs )) {
  472. EndDialog(hDlg, ERROR_CANCELLED);
  473. return TRUE;
  474. }
  475. //
  476. // display dynamic stuff that may have changed.
  477. //
  478. SendMessage( hDlg, WM_COMMAND, IDC_PROTECT_UPDATE_DYNAMIC, 0 );
  479. break;
  480. }
  481. default:
  482. {
  483. return FALSE;
  484. }
  485. }
  486. } // WM_COMMAND
  487. default:
  488. {
  489. return FALSE;
  490. }
  491. } // message
  492. }
  493. INT_PTR
  494. CALLBACK
  495. DialogConfirmAccess(
  496. HWND hDlg, // handle to dialog box
  497. UINT message, // message
  498. WPARAM wParam, // first message parameter
  499. LPARAM lParam // second message parameter
  500. )
  501. {
  502. DIALOGARGS *pDialogArgs;
  503. CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct;
  504. switch (message)
  505. {
  506. case WM_INITDIALOG:
  507. {
  508. SetLastError( 0 ); // as per win32 documentation
  509. if(SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)lParam) == 0) {
  510. if(GetLastError() != ERROR_SUCCESS) {
  511. EndDialog(hDlg, GetLastError());
  512. return FALSE;
  513. }
  514. }
  515. // lParam is DIALOGARGS *
  516. pDialogArgs = (DIALOGARGS*)lParam;
  517. pPromptStruct = pDialogArgs->pPromptStruct;
  518. //
  519. // set the dialog title
  520. //
  521. SetWindowTextU(hDlg, pPromptStruct->szPrompt);
  522. //
  523. // description.
  524. //
  525. SetWindowTextU(GetDlgItem(hDlg, IDC_PROTECT_LABEL_EDIT1), pDialogArgs->szDataDescription);
  526. if( pPromptStruct->dwPromptFlags & CRYPTPROTECT_PROMPT_STRONG ) {
  527. //
  528. // If policy doesn't allow, disable caching of password.
  529. //
  530. // Otherwise, search password cache to see if user cached password
  531. // for this item.
  532. //
  533. if( g_dwAllowCachePW == ALLOW_CACHE_UNKNOWN )
  534. {
  535. if(!IsCachePWAllowed()) {
  536. g_dwAllowCachePW = ALLOW_CACHE_NO;
  537. } else {
  538. g_dwAllowCachePW = ALLOW_CACHE_YES;
  539. }
  540. }
  541. if((g_dwAllowCachePW == ALLOW_CACHE_NO) ||
  542. (pPromptStruct->dwPromptFlags & CRYPTPROTECT_PROMPT_REQUIRE_STRONG))
  543. {
  544. ShowWindow( GetDlgItem(hDlg, IDC_PROTECT_CACHEPW), SW_HIDE );
  545. EnableWindow( GetDlgItem(hDlg, IDC_PROTECT_CACHEPW), FALSE );
  546. } else if(SearchProtectPasswordCache( pDialogArgs->pDataIn, pDialogArgs->rgbPasswordHash, FALSE ))
  547. {
  548. //
  549. // enable checkbox for cached password, fill edit control
  550. // with password.
  551. //
  552. SetWindowTextU(GetDlgItem(hDlg,IDC_PROTECT_PASSWORD1),
  553. g_szGooPassword
  554. );
  555. SendMessage(GetDlgItem(hDlg, IDC_PROTECT_CACHEPW), BM_SETCHECK, BST_CHECKED, 0);
  556. pDialogArgs->fCachedPassword = TRUE;
  557. pDialogArgs->fValidPassword = TRUE;
  558. }
  559. } else {
  560. //
  561. // disable irrelevant fields in dialog.
  562. //
  563. ShowWindow( GetDlgItem(hDlg, IDC_PROTECT_CACHEPW), SW_HIDE );
  564. EnableWindow( GetDlgItem(hDlg, IDC_PROTECT_CACHEPW), FALSE );
  565. ShowWindow( GetDlgItem(hDlg, IDC_PROTECT_PASSWORD1), SW_HIDE );
  566. EnableWindow( GetDlgItem(hDlg, IDC_PROTECT_PASSWORD1), FALSE );
  567. }
  568. return TRUE;
  569. } // WM_INITDIALOG
  570. case WM_COMMAND:
  571. {
  572. switch(LOWORD(wParam))
  573. {
  574. case IDOK:
  575. {
  576. pDialogArgs = (DIALOGARGS*)GetWindowLongPtr(
  577. hDlg,
  578. GWLP_USERDATA
  579. );
  580. if(pDialogArgs == NULL)
  581. break; // TODO: bail out
  582. pPromptStruct = pDialogArgs->pPromptStruct;
  583. if( pPromptStruct->dwPromptFlags & CRYPTPROTECT_PROMPT_STRONG )
  584. {
  585. WCHAR szPassword[ 256 ];
  586. int cchPassword = sizeof(szPassword) / sizeof(WCHAR);
  587. BOOL fCachePassword;
  588. //
  589. // check if remember password is checked.
  590. // if so, check if password is untypable goo.
  591. //
  592. if( g_dwAllowCachePW != ALLOW_CACHE_NO &&
  593. (BST_CHECKED == SendMessage(GetDlgItem(hDlg, IDC_PROTECT_CACHEPW), BM_GETCHECK, 0, 0))
  594. )
  595. {
  596. fCachePassword = TRUE;
  597. } else {
  598. fCachePassword = FALSE;
  599. }
  600. cchPassword = GetWindowTextU(
  601. GetDlgItem(hDlg,IDC_PROTECT_PASSWORD1),
  602. szPassword,
  603. cchPassword
  604. );
  605. if( !fCachePassword && pDialogArgs->fCachedPassword ) {
  606. //
  607. // user un-checked cachePW button, and item was cached.
  608. // remove it from cache.
  609. //
  610. SearchProtectPasswordCache(
  611. pDialogArgs->pDataIn,
  612. pDialogArgs->rgbPasswordHash,
  613. TRUE
  614. );
  615. }
  616. if(
  617. pDialogArgs->fCachedPassword &&
  618. (cchPassword*sizeof(WCHAR) == sizeof(g_szGooPassword)-sizeof(WCHAR)) &&
  619. (memcmp(szPassword, g_szGooPassword, cchPassword*sizeof(WCHAR)) == 0)
  620. )
  621. {
  622. //
  623. // nothing to do, rgbPasswordHash was updated by
  624. // cache search...
  625. //
  626. } else {
  627. ComputePasswordHash(
  628. szPassword,
  629. (DWORD)(cchPassword * sizeof(WCHAR)),
  630. pDialogArgs->rgbPasswordHash
  631. );
  632. pDialogArgs->fValidPassword = TRUE;
  633. //
  634. // if user chose to cache password, add it.
  635. //
  636. if( fCachePassword )
  637. {
  638. AddProtectPasswordCache(
  639. pDialogArgs->pDataIn,
  640. pDialogArgs->rgbPasswordHash
  641. );
  642. }
  643. }
  644. }
  645. EndDialog(hDlg, ERROR_SUCCESS);
  646. return TRUE;
  647. }
  648. case IDCANCEL:
  649. {
  650. EndDialog(hDlg, ERROR_CANCELLED);
  651. return TRUE;
  652. }
  653. case IDC_PROTECT_ADVANCED:
  654. {
  655. pDialogArgs = (DIALOGARGS*)GetWindowLongPtr(
  656. hDlg,
  657. GWLP_USERDATA
  658. );
  659. if(pDialogArgs == NULL)
  660. break; // TODO: bail out
  661. //
  662. // show details dialog.
  663. //
  664. AdvancedSecurityDetails(
  665. hDlg,
  666. pDialogArgs
  667. );
  668. return FALSE;
  669. }
  670. default:
  671. {
  672. return FALSE;
  673. }
  674. }
  675. } // WM_COMMAND
  676. default:
  677. {
  678. return FALSE;
  679. }
  680. } // message
  681. }
  682. //
  683. // security level chooser routines.
  684. //
  685. BOOL
  686. ChooseSecurityLevel(
  687. IN HWND hWndParent,
  688. IN DIALOGARGS *pDialogArgs
  689. )
  690. {
  691. CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct;
  692. DWORD dwOriginalPromptFlags;
  693. BOOL fEmptyDescription;
  694. INT_PTR iRet;
  695. pPromptStruct = pDialogArgs->pPromptStruct;
  696. dwOriginalPromptFlags = pPromptStruct->dwPromptFlags;
  697. fEmptyDescription = (pDialogArgs->szDataDescription == NULL);
  698. Step1:
  699. if(pPromptStruct->dwPromptFlags & CRYPTPROTECT_PROMPT_REQUIRE_STRONG)
  700. {
  701. //
  702. // Force strong protection.
  703. //
  704. pPromptStruct->dwPromptFlags |= CRYPTPROTECT_PROMPT_STRONG;
  705. }
  706. else
  707. {
  708. //
  709. // The "require strong" flag is not set, so allow the user to select
  710. // between medium and strong protection.
  711. //
  712. iRet = DialogBoxParamU(
  713. g_hInstProtectUI,
  714. MAKEINTRESOURCE(IDD_PROTECT_CHOOSE_SECURITY),
  715. hWndParent,
  716. DialogChooseSecurityLevel,
  717. (LPARAM)pDialogArgs
  718. );
  719. // if user decides not to choose, bail
  720. if( iRet == IDCANCEL )
  721. return TRUE;
  722. if( iRet != IDOK )
  723. return FALSE;
  724. }
  725. if( pPromptStruct->dwPromptFlags & CRYPTPROTECT_PROMPT_STRONG ) {
  726. //
  727. // display dialog 'page' confirming high security.
  728. //
  729. iRet = DialogBoxParamU(
  730. g_hInstProtectUI,
  731. MAKEINTRESOURCE(IDD_PROTECT_CHOOSE_SECURITY_H),
  732. hWndParent,
  733. DialogChooseSecurityLevelHigh,
  734. (LPARAM)pDialogArgs
  735. );
  736. } else {
  737. //
  738. // display dialog 'page' confirming medium security.
  739. //
  740. iRet = DialogBoxParamU(
  741. g_hInstProtectUI,
  742. MAKEINTRESOURCE(IDD_PROTECT_CHOOSE_SECURITY_M),
  743. hWndParent,
  744. DialogChooseSecurityLevelMedium,
  745. (LPARAM)pDialogArgs
  746. );
  747. }
  748. if( iRet == IDC_PROTECT_BACK ) {
  749. //
  750. // put original prompt flags back so we don't end up with undefined
  751. // pwd at high-security level.
  752. // free allocated description if that happened, too.
  753. //
  754. pPromptStruct->dwPromptFlags = dwOriginalPromptFlags;
  755. if( fEmptyDescription && pDialogArgs->szDataDescription ) {
  756. SSFree( pDialogArgs->szDataDescription );
  757. pDialogArgs->szDataDescription = NULL;
  758. }
  759. goto Step1;
  760. }
  761. if( iRet != IDOK )
  762. return FALSE;
  763. return TRUE;
  764. }
  765. INT_PTR
  766. CALLBACK
  767. DialogChooseSecurityLevel(
  768. HWND hDlg, // handle to dialog box
  769. UINT message, // message
  770. WPARAM wParam, // first message parameter
  771. LPARAM lParam // second message parameter
  772. )
  773. {
  774. switch (message)
  775. {
  776. CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct;
  777. DIALOGARGS *pDialogArgs;
  778. case WM_INITDIALOG:
  779. {
  780. SetLastError( 0 ); // as per win32 documentation
  781. if(SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)lParam) == 0) {
  782. if(GetLastError() != ERROR_SUCCESS) {
  783. EndDialog(hDlg, IDCANCEL);
  784. return FALSE;
  785. }
  786. }
  787. // lParam is DIALOGARGS*
  788. pDialogArgs = (DIALOGARGS*)lParam;
  789. pPromptStruct = pDialogArgs->pPromptStruct;
  790. // set the dialog title
  791. SetWindowTextU(hDlg, pPromptStruct->szPrompt);
  792. if( pPromptStruct->dwPromptFlags & CRYPTPROTECT_PROMPT_STRONG ) {
  793. SendDlgItemMessage(hDlg, IDC_PROTECT_RADIO_HIGH, BM_SETCHECK, BST_CHECKED, 0);
  794. SendMessage(hDlg, WM_COMMAND, (WORD)IDC_PROTECT_RADIO_HIGH, 0);
  795. } else {
  796. SendDlgItemMessage(hDlg, IDC_PROTECT_RADIO_MEDIUM, BM_SETCHECK, BST_CHECKED, 0);
  797. SendMessage(hDlg, WM_COMMAND, (WORD)IDC_PROTECT_RADIO_MEDIUM, 0);
  798. }
  799. return TRUE;
  800. } // WM_INITDIALOG
  801. case WM_COMMAND:
  802. {
  803. switch (LOWORD(wParam))
  804. {
  805. case IDC_PROTECT_NEXT:
  806. case IDOK:
  807. {
  808. pDialogArgs = (DIALOGARGS*)GetWindowLongPtr(
  809. hDlg,
  810. GWLP_USERDATA
  811. );
  812. if(pDialogArgs == NULL)
  813. break; // TODO: bail out
  814. pPromptStruct = pDialogArgs->pPromptStruct;
  815. if (BST_CHECKED == SendDlgItemMessageW(
  816. hDlg,
  817. IDC_PROTECT_RADIO_HIGH,
  818. BM_GETCHECK,
  819. 0,
  820. 0
  821. ))
  822. {
  823. pPromptStruct->dwPromptFlags |= CRYPTPROTECT_PROMPT_STRONG;
  824. } else {
  825. pPromptStruct->dwPromptFlags &= ~(CRYPTPROTECT_PROMPT_STRONG);
  826. }
  827. break;
  828. }
  829. default:
  830. {
  831. break;
  832. }
  833. }
  834. if (
  835. (LOWORD(wParam) == IDOK) ||
  836. (LOWORD(wParam) == IDCANCEL) ||
  837. (LOWORD(wParam) == IDC_PROTECT_NEXT)
  838. )
  839. {
  840. EndDialog(hDlg, LOWORD(wParam));
  841. return TRUE;
  842. }
  843. } // WM_COMMAND
  844. default:
  845. {
  846. return FALSE;
  847. }
  848. } // message
  849. }
  850. INT_PTR
  851. CALLBACK
  852. DialogChooseSecurityLevelMedium(
  853. HWND hDlg, // handle to dialog box
  854. UINT message, // message
  855. WPARAM wParam, // first message parameter
  856. LPARAM lParam // second message parameter
  857. )
  858. {
  859. switch (message)
  860. {
  861. case WM_INITDIALOG:
  862. {
  863. DIALOGARGS *pDialogArgs;
  864. CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct;
  865. // lParam is DIALOGARGS*
  866. pDialogArgs = (DIALOGARGS*)lParam;
  867. pPromptStruct = pDialogArgs->pPromptStruct;
  868. // set the dialog title
  869. SetWindowTextU(hDlg, pPromptStruct->szPrompt);
  870. return TRUE;
  871. } // WM_INITDIALOG
  872. case WM_COMMAND:
  873. {
  874. if (
  875. (LOWORD(wParam) == IDOK) ||
  876. (LOWORD(wParam) == IDCANCEL) ||
  877. (LOWORD(wParam) == IDC_PROTECT_BACK)
  878. )
  879. {
  880. EndDialog(hDlg, LOWORD(wParam));
  881. return TRUE;
  882. }
  883. } // WM_COMMAND
  884. default:
  885. {
  886. return FALSE;
  887. }
  888. } // message
  889. }
  890. INT_PTR
  891. CALLBACK
  892. DialogChooseSecurityLevelHigh(
  893. HWND hDlg, // handle to dialog box
  894. UINT message, // message
  895. WPARAM wParam, // first message parameter
  896. LPARAM lParam // second message parameter
  897. )
  898. {
  899. switch (message)
  900. {
  901. DIALOGARGS *pDialogArgs;
  902. CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct;
  903. case WM_INITDIALOG:
  904. {
  905. SetLastError( 0 ); // as per win32 documentation
  906. if(SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)lParam) == 0) {
  907. if(GetLastError() != ERROR_SUCCESS) {
  908. EndDialog(hDlg, IDCANCEL);
  909. return FALSE;
  910. }
  911. }
  912. // lParam is DIALOGARGS*
  913. pDialogArgs = (DIALOGARGS*)lParam;
  914. pPromptStruct = pDialogArgs->pPromptStruct;
  915. // set the dialog title
  916. SetWindowTextU(hDlg, pPromptStruct->szPrompt);
  917. // Disable <Back and Finished buttons
  918. if(pPromptStruct->dwPromptFlags & CRYPTPROTECT_PROMPT_REQUIRE_STRONG)
  919. {
  920. EnableWindow( GetDlgItem(hDlg, IDC_PROTECT_BACK), FALSE );
  921. EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
  922. }
  923. //
  924. // description.
  925. //
  926. if( pDialogArgs->szDataDescription ) {
  927. HWND hwndProtectEdit1 = GetDlgItem( hDlg, IDC_PROTECT_PASSWORD1 );
  928. SetWindowTextU(GetDlgItem(hDlg, IDC_PROTECT_PW_NEWNAME), pDialogArgs->szDataDescription);
  929. //
  930. // set focus to Password entry box.
  931. //
  932. EnableWindow(hwndProtectEdit1, TRUE);
  933. SetFocus(hwndProtectEdit1);
  934. //
  935. // default dialog template disabled input.
  936. //
  937. } else {
  938. HWND hwndProtectPWNew = GetDlgItem( hDlg, IDC_PROTECT_PW_NEWNAME );
  939. //
  940. // enable edit box entry.
  941. //
  942. EnableWindow(hwndProtectPWNew, TRUE);
  943. //
  944. // set focus to description box
  945. //
  946. SetFocus(hwndProtectPWNew);
  947. }
  948. return FALSE;
  949. } // WM_INITDIALOG
  950. case WM_COMMAND:
  951. {
  952. switch(LOWORD(wParam))
  953. {
  954. case IDOK:
  955. {
  956. WCHAR szPassword[ 256 ];
  957. int cchPassword;
  958. BYTE rgbPasswordHashConfirm[A_SHA_DIGEST_LEN];
  959. BOOL fPasswordsMatch = TRUE; // assume passwords match.
  960. pDialogArgs = (DIALOGARGS*)GetWindowLongPtr(
  961. hDlg,
  962. GWLP_USERDATA
  963. );
  964. if(pDialogArgs == NULL)
  965. break; // TODO: bail out
  966. pPromptStruct = pDialogArgs->pPromptStruct;
  967. //
  968. // nothing more to do if not STRONG
  969. //
  970. if( (pPromptStruct->dwPromptFlags & CRYPTPROTECT_PROMPT_STRONG) == 0 ) {
  971. EndDialog( hDlg, IDOK );
  972. }
  973. cchPassword = sizeof(szPassword) / sizeof(WCHAR);
  974. cchPassword = GetWindowTextU(
  975. GetDlgItem(hDlg,IDC_PROTECT_PASSWORD1),
  976. szPassword,
  977. cchPassword
  978. );
  979. ComputePasswordHash(
  980. szPassword,
  981. cchPassword * sizeof(WCHAR),
  982. pDialogArgs->rgbPasswordHash
  983. );
  984. ZeroMemory( szPassword, cchPassword*sizeof(WCHAR) );
  985. cchPassword = sizeof(szPassword) / sizeof(WCHAR);
  986. cchPassword = GetWindowTextU(
  987. GetDlgItem(hDlg,IDC_PROTECT_EDIT2),
  988. szPassword,
  989. cchPassword
  990. );
  991. ComputePasswordHash(
  992. szPassword,
  993. cchPassword * sizeof(WCHAR),
  994. rgbPasswordHashConfirm
  995. );
  996. ZeroMemory( szPassword, cchPassword*sizeof(WCHAR) );
  997. //
  998. // check if both passwords entered by user match.
  999. //
  1000. if( memcmp(rgbPasswordHashConfirm, pDialogArgs->rgbPasswordHash, sizeof(rgbPasswordHashConfirm)) != 0 )
  1001. {
  1002. fPasswordsMatch = FALSE;
  1003. }
  1004. ZeroMemory( rgbPasswordHashConfirm, sizeof(rgbPasswordHashConfirm) );
  1005. if( !fPasswordsMatch )
  1006. {
  1007. WCHAR szText[256];
  1008. WCHAR szCaption[256];
  1009. //
  1010. // passwords must match: tell user.
  1011. //
  1012. LoadStringU(g_hInstProtectUI,
  1013. IDS_PROTECT_PASSWORD_NOMATCH,
  1014. szText,
  1015. sizeof(szText) / sizeof(WCHAR)
  1016. );
  1017. LoadStringU(g_hInstProtectUI,
  1018. IDS_PROTECT_PASSWORD_ERROR_DLGTITLE,
  1019. szCaption,
  1020. sizeof(szCaption) / sizeof(WCHAR)
  1021. );
  1022. MessageBoxW(hDlg,
  1023. szText,
  1024. szCaption,
  1025. MB_OK | MB_ICONEXCLAMATION
  1026. );
  1027. return FALSE;
  1028. }
  1029. //
  1030. // if no description provided, make sure user entered one,
  1031. // and grab it..
  1032. //
  1033. if( pDialogArgs->szDataDescription == NULL ) {
  1034. cchPassword = sizeof(szPassword) / sizeof(WCHAR);
  1035. cchPassword = GetWindowTextU(
  1036. GetDlgItem(hDlg,IDC_PROTECT_PW_NEWNAME),
  1037. szPassword,
  1038. cchPassword
  1039. );
  1040. if( cchPassword == 0 ) {
  1041. WCHAR szText[256];
  1042. WCHAR szCaption[256];
  1043. //
  1044. // password must be named: tell user.
  1045. //
  1046. LoadStringU(g_hInstProtectUI,
  1047. IDS_PROTECT_PASSWORD_MUSTNAME,
  1048. szText,
  1049. sizeof(szText) / sizeof(WCHAR)
  1050. );
  1051. LoadStringU(g_hInstProtectUI,
  1052. IDS_PROTECT_PASSWORD_ERROR_DLGTITLE,
  1053. szCaption,
  1054. sizeof(szCaption) / sizeof(WCHAR)
  1055. );
  1056. MessageBoxW(hDlg,
  1057. szText,
  1058. szCaption,
  1059. MB_OK | MB_ICONEXCLAMATION
  1060. );
  1061. return FALSE;
  1062. }
  1063. pDialogArgs->szDataDescription = (LPWSTR)SSAlloc( (cchPassword+1) * sizeof(WCHAR) );
  1064. if( pDialogArgs->szDataDescription == NULL )
  1065. return FALSE;
  1066. CopyMemory( pDialogArgs->szDataDescription, szPassword, cchPassword*sizeof(WCHAR) );
  1067. (pDialogArgs->szDataDescription)[cchPassword] = L'\0';
  1068. }
  1069. pDialogArgs->fValidPassword = TRUE;
  1070. EndDialog(hDlg, IDOK);
  1071. return TRUE;
  1072. }
  1073. case IDC_PROTECT_PASSWORD1:
  1074. {
  1075. pDialogArgs = (DIALOGARGS*)GetWindowLongPtr(
  1076. hDlg,
  1077. GWLP_USERDATA
  1078. );
  1079. if(pDialogArgs == NULL)
  1080. break; // TODO: bail out
  1081. pPromptStruct = pDialogArgs->pPromptStruct;
  1082. if(pPromptStruct->dwPromptFlags & CRYPTPROTECT_PROMPT_REQUIRE_STRONG)
  1083. {
  1084. WCHAR szPassword[ 256 ];
  1085. int cchPassword;
  1086. //
  1087. // Disable the Finish button until a password has been entered.
  1088. //
  1089. cchPassword = sizeof(szPassword) / sizeof(WCHAR);
  1090. cchPassword = GetWindowTextU(
  1091. GetDlgItem(hDlg,IDC_PROTECT_PASSWORD1),
  1092. szPassword,
  1093. cchPassword
  1094. );
  1095. if(cchPassword)
  1096. {
  1097. ZeroMemory(szPassword, cchPassword * sizeof(WCHAR));
  1098. EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
  1099. }
  1100. else
  1101. {
  1102. EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
  1103. }
  1104. }
  1105. break;
  1106. }
  1107. case IDC_PROTECT_BACK:
  1108. case IDCANCEL:
  1109. {
  1110. EndDialog(hDlg, LOWORD(wParam));
  1111. return TRUE;
  1112. }
  1113. default:
  1114. {
  1115. break;
  1116. }
  1117. }
  1118. } // WM_COMMAND
  1119. default:
  1120. {
  1121. return FALSE;
  1122. }
  1123. } // message
  1124. }
  1125. VOID
  1126. AdvancedSecurityDetails(
  1127. IN HWND hWndParent,
  1128. IN DIALOGARGS *pDialogArgs
  1129. )
  1130. {
  1131. DialogBoxParamU(
  1132. g_hInstProtectUI,
  1133. MAKEINTRESOURCE(IDD_PROTECT_SECURITY_DETAILS),
  1134. hWndParent,
  1135. DialogAdvancedSecurityDetails,
  1136. (LPARAM)pDialogArgs
  1137. );
  1138. }
  1139. INT_PTR
  1140. CALLBACK
  1141. DialogAdvancedSecurityDetails(
  1142. HWND hDlg, // handle to dialog box
  1143. UINT message, // message
  1144. WPARAM wParam, // first message parameter
  1145. LPARAM lParam // second message parameter
  1146. )
  1147. {
  1148. switch (message) {
  1149. DIALOGARGS *pDialogArgs;
  1150. CRYPTPROTECT_PROMPTSTRUCT *pPromptStruct;
  1151. case WM_INITDIALOG:
  1152. {
  1153. WCHAR szResource[ 256 ];
  1154. UINT ResourceId;
  1155. SetLastError( 0 ); // as per win32 documentation
  1156. if(SetWindowLongPtr(hDlg, GWLP_USERDATA, (LONG_PTR)lParam) == 0) {
  1157. if(GetLastError() != ERROR_SUCCESS) {
  1158. EndDialog(hDlg, IDCANCEL);
  1159. return FALSE;
  1160. }
  1161. }
  1162. // lParam is DIALOGARGS*
  1163. pDialogArgs = (DIALOGARGS*)lParam;
  1164. pPromptStruct = pDialogArgs->pPromptStruct;
  1165. // set the dialog title
  1166. SetWindowTextU(hDlg, pPromptStruct->szPrompt);
  1167. InitializeDetailGlobals();
  1168. if(g_szDetailApplicationPath)
  1169. {
  1170. SetWindowTextU(GetDlgItem(hDlg, IDC_PROTECT_APP_PATH), g_szDetailApplicationPath);
  1171. }
  1172. if( pDialogArgs->fProtect ) {
  1173. ResourceId = IDS_PROTECT_OPERATION_PROTECT;
  1174. } else {
  1175. ResourceId = IDS_PROTECT_OPERATION_UNPROTECT;
  1176. }
  1177. LoadStringU(g_hInstProtectUI,
  1178. ResourceId,
  1179. szResource,
  1180. sizeof(szResource) / sizeof(WCHAR)
  1181. );
  1182. SetWindowTextU(GetDlgItem(hDlg, IDC_PROTECT_OPERATION_TYPE), szResource);
  1183. if( pDialogArgs->szDataDescription ) {
  1184. SetWindowTextU(GetDlgItem(hDlg, IDC_PROTECT_APP_DESCRIPTION), pDialogArgs->szDataDescription);
  1185. }
  1186. return FALSE;
  1187. } // WM_INITDIALOG
  1188. case WM_COMMAND:
  1189. {
  1190. switch(LOWORD(wParam))
  1191. {
  1192. case IDOK:
  1193. case IDCANCEL:
  1194. {
  1195. EndDialog(hDlg, LOWORD(wParam));
  1196. return TRUE;
  1197. }
  1198. default:
  1199. {
  1200. break;
  1201. }
  1202. }
  1203. } // WM_COMMAND
  1204. default:
  1205. {
  1206. return FALSE;
  1207. }
  1208. } // switch
  1209. return FALSE;
  1210. }
  1211. VOID
  1212. ComputePasswordHash(
  1213. IN PVOID pvPassword,
  1214. IN DWORD cbPassword,
  1215. IN OUT BYTE rgbPasswordHash[A_SHA_DIGEST_LEN]
  1216. )
  1217. /*++
  1218. Compute SHA-1 hash of supplied pvPassword of size cbPassword, returning
  1219. resultant hash in rgbPasswordHash buffer.
  1220. --*/
  1221. {
  1222. A_SHA_CTX shaCtx;
  1223. if( pvPassword == NULL )
  1224. return;
  1225. A_SHAInit( &shaCtx );
  1226. A_SHAUpdate( &shaCtx, (unsigned char*)pvPassword, (unsigned int)cbPassword );
  1227. A_SHAFinal( &shaCtx, rgbPasswordHash );
  1228. ZeroMemory( &shaCtx, sizeof(shaCtx) );
  1229. return;
  1230. }
  1231. BOOL
  1232. GetEffectiveLogonId(
  1233. IN OUT LUID *pLogonId
  1234. )
  1235. {
  1236. HANDLE hToken;
  1237. TOKEN_STATISTICS TokenInformation;
  1238. DWORD cbTokenInformation;
  1239. BOOL fSuccess;
  1240. if(!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken)) {
  1241. if(GetLastError() != ERROR_NO_TOKEN)
  1242. return FALSE;
  1243. if(!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
  1244. return FALSE;
  1245. }
  1246. fSuccess = GetTokenInformation(
  1247. hToken,
  1248. TokenStatistics,
  1249. &TokenInformation,
  1250. sizeof(TokenInformation),
  1251. &cbTokenInformation
  1252. );
  1253. CloseHandle( hToken );
  1254. if( fSuccess ) {
  1255. CopyMemory( pLogonId, &TokenInformation.AuthenticationId, sizeof(*pLogonId) );
  1256. }
  1257. return fSuccess;
  1258. }
  1259. BOOL
  1260. InitializeDetailGlobals(
  1261. VOID
  1262. )
  1263. {
  1264. WCHAR szStackBuffer[ 256 ];
  1265. DWORD cchStackBuffer;
  1266. LPWSTR szDetailApplicationName = NULL;
  1267. LPWSTR szDetailApplicationPath = NULL;
  1268. if( g_fDetailGlobalsInitialized )
  1269. return TRUE;
  1270. cchStackBuffer = sizeof(szStackBuffer) / sizeof(WCHAR);
  1271. cchStackBuffer = GetModuleFileNameU( NULL, szStackBuffer, cchStackBuffer );
  1272. if( cchStackBuffer ) {
  1273. cchStackBuffer++; // include terminal NULL.
  1274. szDetailApplicationPath = (LPWSTR)SSAlloc( cchStackBuffer * sizeof(WCHAR) );
  1275. if( szDetailApplicationPath ) {
  1276. CopyMemory( szDetailApplicationPath, szStackBuffer, cchStackBuffer*sizeof(WCHAR) );
  1277. }
  1278. }
  1279. EnterCriticalSection( &g_csProtectPasswordCache );
  1280. if( !g_fDetailGlobalsInitialized ) {
  1281. g_szDetailApplicationName = szDetailApplicationName;
  1282. g_szDetailApplicationPath = szDetailApplicationPath;
  1283. g_fDetailGlobalsInitialized = TRUE;
  1284. szDetailApplicationName = NULL;
  1285. szDetailApplicationPath = NULL;
  1286. }
  1287. LeaveCriticalSection( &g_csProtectPasswordCache );
  1288. if( szDetailApplicationName )
  1289. SSFree( szDetailApplicationName );
  1290. if( szDetailApplicationPath )
  1291. SSFree( szDetailApplicationPath );
  1292. return TRUE;
  1293. }
  1294. BOOL
  1295. InitializeProtectPasswordCache(
  1296. VOID
  1297. )
  1298. {
  1299. __try
  1300. {
  1301. InitializeCriticalSection( &g_csProtectPasswordCache );
  1302. }
  1303. __except(EXCEPTION_EXECUTE_HANDLER)
  1304. {
  1305. memset(&g_csProtectPasswordCache, 0, sizeof(g_csProtectPasswordCache));
  1306. SetLastError(GetExceptionCode());
  1307. return FALSE;
  1308. }
  1309. InitializeListHead( &g_ProtectPasswordCache );
  1310. g_fDetailGlobalsInitialized = FALSE;
  1311. g_szDetailApplicationName = NULL;
  1312. g_szDetailApplicationPath = NULL;
  1313. return TRUE;
  1314. }
  1315. VOID
  1316. DeleteProtectPasswordCache(
  1317. VOID
  1318. )
  1319. {
  1320. if( g_szDetailApplicationName )
  1321. {
  1322. SSFree(g_szDetailApplicationName);
  1323. g_szDetailApplicationName = NULL;
  1324. }
  1325. if( g_szDetailApplicationPath )
  1326. {
  1327. SSFree(g_szDetailApplicationPath);
  1328. g_szDetailApplicationPath = NULL;
  1329. }
  1330. g_fDetailGlobalsInitialized = FALSE;
  1331. EnterCriticalSection( &g_csProtectPasswordCache );
  1332. while ( !IsListEmpty( &g_ProtectPasswordCache ) ) {
  1333. PPASSWORD_CACHE_ENTRY pCacheEntry;
  1334. pCacheEntry = CONTAINING_RECORD(
  1335. g_ProtectPasswordCache.Flink,
  1336. PASSWORD_CACHE_ENTRY,
  1337. Next
  1338. );
  1339. RemoveEntryList( &pCacheEntry->Next );
  1340. ZeroMemory( pCacheEntry, sizeof(*pCacheEntry) );
  1341. SSFree( pCacheEntry );
  1342. }
  1343. LeaveCriticalSection( &g_csProtectPasswordCache );
  1344. DeleteCriticalSection( &g_csProtectPasswordCache );
  1345. }
  1346. BOOL
  1347. AddProtectPasswordCache(
  1348. IN DATA_BLOB* pDataIn,
  1349. IN BYTE rgbPassword[A_SHA_DIGEST_LEN]
  1350. )
  1351. {
  1352. PPASSWORD_CACHE_ENTRY pCacheEntry = NULL;
  1353. A_SHA_CTX shaCtx;
  1354. pCacheEntry = (PPASSWORD_CACHE_ENTRY)SSAlloc( sizeof(PASSWORD_CACHE_ENTRY) );
  1355. if( pCacheEntry == NULL )
  1356. return FALSE;
  1357. GetEffectiveLogonId( &pCacheEntry->LogonId );
  1358. GetSystemTimeAsFileTime( &pCacheEntry->ftLastAccess );
  1359. A_SHAInit( &shaCtx );
  1360. A_SHAUpdate( &shaCtx, (unsigned char*)pDataIn->pbData, pDataIn->cbData );
  1361. A_SHAFinal( &shaCtx, pCacheEntry->rgbDataInHash );
  1362. ZeroMemory( &shaCtx, sizeof(shaCtx) );
  1363. CopyMemory( pCacheEntry->rgbPasswordHash, rgbPassword, A_SHA_DIGEST_LEN );
  1364. EnterCriticalSection( &g_csProtectPasswordCache );
  1365. InsertHeadList( &g_ProtectPasswordCache, &pCacheEntry->Next );
  1366. LeaveCriticalSection( &g_csProtectPasswordCache );
  1367. return TRUE;
  1368. }
  1369. BOOL
  1370. SearchProtectPasswordCache(
  1371. IN DATA_BLOB* pDataIn,
  1372. IN OUT BYTE rgbPassword[A_SHA_DIGEST_LEN],
  1373. IN BOOL fDeleteFoundEntry
  1374. )
  1375. {
  1376. A_SHA_CTX shaCtx;
  1377. BYTE rgbDataInHashCandidate[A_SHA_DIGEST_LEN];
  1378. LUID LogonIdCandidate;
  1379. PLIST_ENTRY ListEntry;
  1380. PLIST_ENTRY ListHead;
  1381. BOOL fFoundMatch = FALSE;
  1382. if(!GetEffectiveLogonId( &LogonIdCandidate ))
  1383. return FALSE;
  1384. A_SHAInit( &shaCtx );
  1385. A_SHAUpdate( &shaCtx, (unsigned char*)pDataIn->pbData, pDataIn->cbData );
  1386. A_SHAFinal( &shaCtx, rgbDataInHashCandidate );
  1387. EnterCriticalSection( &g_csProtectPasswordCache );
  1388. ListHead = &g_ProtectPasswordCache;
  1389. for( ListEntry = ListHead->Flink;
  1390. ListEntry != ListHead;
  1391. ListEntry = ListEntry->Flink ) {
  1392. PPASSWORD_CACHE_ENTRY pCacheEntry;
  1393. signed int comparator;
  1394. pCacheEntry = CONTAINING_RECORD( ListEntry, PASSWORD_CACHE_ENTRY, Next );
  1395. //
  1396. // search by hash, then LogonId
  1397. // note that most usage scenarios, all cache entries will correspond
  1398. // to same LogonId.
  1399. //
  1400. comparator = memcmp( rgbDataInHashCandidate, pCacheEntry->rgbDataInHash, sizeof(rgbDataInHashCandidate) );
  1401. if( comparator != 0 )
  1402. continue;
  1403. comparator = memcmp(&LogonIdCandidate, &pCacheEntry->LogonId, sizeof(LUID));
  1404. if( comparator != 0 )
  1405. continue;
  1406. //
  1407. // match found.
  1408. //
  1409. fFoundMatch = TRUE;
  1410. if( fDeleteFoundEntry ) {
  1411. RemoveEntryList( &pCacheEntry->Next );
  1412. ZeroMemory( pCacheEntry, sizeof(*pCacheEntry) );
  1413. SSFree( pCacheEntry );
  1414. } else {
  1415. CopyMemory( rgbPassword, pCacheEntry->rgbPasswordHash, A_SHA_DIGEST_LEN );
  1416. //
  1417. // update last access time.
  1418. //
  1419. GetSystemTimeAsFileTime( &pCacheEntry->ftLastAccess );
  1420. }
  1421. break;
  1422. }
  1423. LeaveCriticalSection( &g_csProtectPasswordCache );
  1424. PurgeProtectPasswordCache();
  1425. return fFoundMatch;
  1426. }
  1427. VOID
  1428. PurgeProtectPasswordCache(
  1429. VOID
  1430. )
  1431. /*++
  1432. This routine purges entries in the password cache that are greater than
  1433. 1 hour in age, via the ftLastAccess time.
  1434. --*/
  1435. {
  1436. // static FILETIME ftLastPurge = {0xffffffff,0xffffffff};
  1437. static FILETIME ftLastPurge;
  1438. FILETIME ftStaleEntry;
  1439. PLIST_ENTRY ListEntry;
  1440. PLIST_ENTRY ListHead;
  1441. unsigned __int64 ui64;
  1442. //
  1443. // get current time, and subtract an hour off it.
  1444. //
  1445. GetSystemTimeAsFileTime( &ftStaleEntry );
  1446. ui64 = ftStaleEntry.dwHighDateTime;
  1447. ui64 <<= 32;
  1448. ui64 |= ftStaleEntry.dwLowDateTime;
  1449. // ui64 -= (600000000*60);
  1450. ui64 -= 0x861c46800;
  1451. ftStaleEntry.dwLowDateTime = (DWORD)(ui64 & 0xffffffff);
  1452. ftStaleEntry.dwHighDateTime = (DWORD)(ui64 >> 32);
  1453. //
  1454. // only purge list once per hour.
  1455. //
  1456. if( CompareFileTime( &ftStaleEntry, &ftLastPurge ) < 0 ) {
  1457. return;
  1458. }
  1459. //
  1460. // update last purge time.
  1461. //
  1462. GetSystemTimeAsFileTime( &ftLastPurge );
  1463. EnterCriticalSection( &g_csProtectPasswordCache );
  1464. ListHead = &g_ProtectPasswordCache;
  1465. for( ListEntry = ListHead->Flink;
  1466. ListEntry != ListHead;
  1467. ListEntry = ListEntry->Flink ) {
  1468. PPASSWORD_CACHE_ENTRY pCacheEntry;
  1469. signed int comparator;
  1470. pCacheEntry = CONTAINING_RECORD( ListEntry, PASSWORD_CACHE_ENTRY, Next );
  1471. if( CompareFileTime( &ftStaleEntry, &pCacheEntry->ftLastAccess ) > 0 )
  1472. {
  1473. ListEntry = ListEntry->Blink;
  1474. RemoveEntryList( &pCacheEntry->Next );
  1475. ZeroMemory( pCacheEntry, sizeof(*pCacheEntry) );
  1476. SSFree( pCacheEntry );
  1477. }
  1478. }
  1479. LeaveCriticalSection( &g_csProtectPasswordCache );
  1480. return;
  1481. }
  1482. BOOL
  1483. IsCachePWAllowed(
  1484. VOID
  1485. )
  1486. {
  1487. HKEY hKeyProtect;
  1488. DWORD dwType;
  1489. DWORD dwValue;
  1490. DWORD cbValue;
  1491. LONG lRet;
  1492. lRet = RegOpenKeyExU(
  1493. HKEY_LOCAL_MACHINE,
  1494. L"SOFTWARE\\Policies\\Microsoft\\Cryptography\\Protect",
  1495. 0,
  1496. KEY_QUERY_VALUE,
  1497. &hKeyProtect
  1498. );
  1499. if( lRet != ERROR_SUCCESS )
  1500. return TRUE;
  1501. cbValue = sizeof(dwValue);
  1502. lRet = RegQueryValueExU(
  1503. hKeyProtect,
  1504. L"AllowCachePW",
  1505. NULL,
  1506. &dwType,
  1507. (PBYTE)&dwValue,
  1508. &cbValue
  1509. );
  1510. RegCloseKey( hKeyProtect );
  1511. if( lRet == ERROR_SUCCESS && dwType == REG_DWORD && dwValue == 0 ) {
  1512. return FALSE;
  1513. }
  1514. return TRUE;
  1515. }