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.

2783 lines
78 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: userinfo.cpp
  4. //
  5. // Module: CMDIAL32.DLL
  6. //
  7. // Synopsis: This module contains the code that handles getting/saving user info.
  8. //
  9. // Copyright (c) 1996-1999 Microsoft Corporation
  10. //
  11. // Author: henryt created 02/??/98
  12. // quintinb created Header 08/16/99
  13. //
  14. //+----------------------------------------------------------------------------
  15. #include "cmmaster.h"
  16. #include "cmuufns.h"
  17. #include "pwd_str.h"
  18. #include "userinfo_str.h"
  19. #include "conact_str.h"
  20. ///////////////////////////////////////////////////////////////////////////////////
  21. // define's
  22. ///////////////////////////////////////////////////////////////////////////////////
  23. //
  24. // CM_MAX_PWD - Maximum possible size of password dataencrypted or otherwise.
  25. // Includes inbound buffer size + room for encryption expansion.
  26. //
  27. const DWORD CM_MAX_PWD = PWLEN * 3; // 2.73 would be enough
  28. //
  29. // Define this if you want to test userinfo upgrade! You should also delete the key
  30. // HKEY_CURRENT_USER\Software\Microsoft\Connection Manager\UserInfo\<Service Name>
  31. //
  32. //#define TEST_USERINFO_UPGRADE 1
  33. #define CACHE_KEY_LEN 80 // Don't change unless you've read every comment regarding it
  34. //
  35. // Suffix for CacheEntry name used on Legacy and W9x. Note: the space is not a typo
  36. const TCHAR* const c_pszCacheEntryNameSuffix = TEXT(" (Connection Manager)");
  37. ///////////////////////////////////////////////////////////////////////////////////
  38. // typedef's
  39. ///////////////////////////////////////////////////////////////////////////////////
  40. ///////////////////////////////////////////////////////////////////////////////////
  41. // func prototypes
  42. ///////////////////////////////////////////////////////////////////////////////////
  43. ////////////////
  44. BOOL WriteDataToReg(
  45. LPCTSTR pszKey,
  46. UINT uiDataID,
  47. DWORD dwType,
  48. CONST BYTE *lpData,
  49. DWORD cbData,
  50. BOOL fAllUser);
  51. BOOL ReadDataFromReg(
  52. LPCTSTR pszKey,
  53. UINT uiDataID,
  54. LPDWORD lpdwType,
  55. BYTE *lpData,
  56. LPDWORD lpcbData,
  57. BOOL fAllUser);
  58. LPBYTE GetDataFromReg(
  59. LPCTSTR pszKey,
  60. UINT uiDataID,
  61. DWORD dwType,
  62. DWORD dwSize,
  63. BOOL fAllUser);
  64. BOOL DeleteDataFromReg(
  65. LPCTSTR pszKey,
  66. UINT uiDataID,
  67. BOOL fAllUser);
  68. BOOL DeleteUserInfoFromReg(
  69. ArgsStruct *pArgs,
  70. UINT uiEntry);
  71. BOOL ReadPasswordFromCmp(
  72. ArgsStruct *pArgs,
  73. UINT uiEntry,
  74. LPTSTR *ppszPassword);
  75. LPCTSTR TranslateUserDataID(
  76. UINT uiDataID);
  77. BOOL ReadUserInfoFromCmp(
  78. ArgsStruct *pArgs,
  79. UINT uiEntry,
  80. PVOID *ppvData);
  81. BOOL DeleteUserInfoFromCmp(
  82. ArgsStruct *pArgs,
  83. UINT uiEntry);
  84. DWORD RasSetCredsWrapper(
  85. ArgsStruct *pArgs,
  86. LPCTSTR pszPhoneBook,
  87. DWORD dwMask,
  88. LPCTSTR pszData);
  89. int WriteUserInfoToRas(
  90. ArgsStruct *pArgs,
  91. UINT uiDataID,
  92. PVOID pvData);
  93. int DeleteUserInfoFromRas(
  94. ArgsStruct *pArgs,
  95. UINT uiEntry);
  96. DWORD RasGetCredsWrapper(
  97. ArgsStruct *pArgs,
  98. LPCTSTR pszPhoneBook,
  99. DWORD dwMask,
  100. PVOID *ppvData);
  101. BOOL ReadUserInfoFromRas(
  102. ArgsStruct *pArgs,
  103. UINT uiEntry,
  104. PVOID *ppvData);
  105. ///////////////
  106. BOOL ReadStringFromCache(
  107. ArgsStruct *pArgs,
  108. LPTSTR pszEntryName,
  109. LPTSTR *ppszStr
  110. );
  111. BOOL DeleteStringFromCache(
  112. ArgsStruct *pArgs,
  113. LPTSTR pszEntryName
  114. );
  115. LPTSTR GetLegacyKeyName(ArgsStruct *pArgs);
  116. LPTSTR EncryptPassword(
  117. ArgsStruct *pArgs,
  118. LPCTSTR pszPassword,
  119. LPDWORD lpdwBufSize,
  120. LPDWORD lpdwCryptType,
  121. BOOL fReg,
  122. LPSTR pszSubKey);
  123. LPBYTE DecryptPassword(
  124. ArgsStruct *pArgs,
  125. LPBYTE pszEncryptedData,
  126. DWORD dwEncryptionType,
  127. DWORD dwEncryptedBytes,
  128. BOOL /*fReg*/,
  129. LPSTR pszSubKey);
  130. LPTSTR BuildUserInfoSubKey(
  131. LPCTSTR pszServiceKey,
  132. BOOL fAllUser);
  133. ///////////////////////////////////////////////////////////////////////////////////
  134. // Implementation
  135. ///////////////////////////////////////////////////////////////////////////////////
  136. #ifdef TEST_USERINFO_UPGRADE
  137. //+---------------------------------------------------------------------------
  138. //
  139. // Function: WriteStringToCache
  140. //
  141. // Synopsis: Write a null terminated password string to cache.
  142. //
  143. // Arguments: pArgs ptr to ArgsStruct
  144. // pszEntryName name to identify the cache entry
  145. // pszStr the string
  146. //
  147. // Returns: BOOL TRUE = success, FALSE = failure
  148. //
  149. //----------------------------------------------------------------------------
  150. BOOL WriteStringToCache(
  151. ArgsStruct *pArgs,
  152. LPTSTR pszEntryName,
  153. LPTSTR pszStr)
  154. {
  155. MYDBGASSERT(pArgs);
  156. MYDBGASSERT(pszEntryName && *pszEntryName);
  157. MYDBGASSERT(pszStr && *pszStr);
  158. DWORD dwRes = ERROR_SUCCESS;
  159. //
  160. // In the legacy case, we use mpr.dll for caching user data on W9x.
  161. // On NT we use the Local Security Authority (LSA)
  162. //
  163. if (OS_NT)
  164. {
  165. if (InitLsa(pArgs))
  166. {
  167. if (!(*ppszStr = (LPTSTR)CmMalloc(dwBufSize)))
  168. {
  169. return FALSE;
  170. }
  171. dwRes = LSA_WriteString(pArgs, pszEntryName, pszStr);
  172. DeInitLsa(pArgs);
  173. }
  174. else
  175. {
  176. dwRes = GetLastError();
  177. }
  178. }
  179. else
  180. {
  181. //
  182. // for Windows95
  183. //
  184. HINSTANCE hInst = NULL;
  185. WORD (WINAPI *pfnFunc)(LPSTR,WORD,LPSTR,WORD,BYTE,UINT) = NULL;
  186. //
  187. // Load MPR for system password cache support
  188. //
  189. MYVERIFY(hInst = LoadLibraryExA("mpr.dll", NULL, 0));
  190. if (hInst)
  191. {
  192. //
  193. // Get function ptr for WNetCachePassword API and cache the password
  194. //
  195. MYVERIFY(pfnFunc = (WORD (WINAPI *)(LPSTR,WORD,LPSTR,WORD,BYTE,UINT))
  196. GetProcAddress(hInst, "WNetCachePassword"));
  197. if (pfnFunc)
  198. {
  199. //
  200. // Convert the EntryName and Password Strings to Ansi
  201. //
  202. LPSTR pszAnsiEntryName = WzToSzWithAlloc(pszEntryName);
  203. LPSTR pszAnsiStr = WzToSzWithAlloc(pszStr);
  204. if (pszAnsiStr && pszAnsiEntryName)
  205. {
  206. //
  207. // Store the password
  208. //
  209. dwRes = pfnFunc(pszAnsiEntryName,
  210. (WORD)lstrlenA(pszAnsiEntryName),
  211. pszAnsiStr,
  212. (WORD)lstrlenA(pszAnsiStr),
  213. CACHE_KEY_LEN,
  214. 0);
  215. }
  216. else
  217. {
  218. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  219. }
  220. CmFree(pszAnsiStr);
  221. CmFree(pszAnsiEntryName);
  222. }
  223. else
  224. {
  225. dwRes = GetLastError();
  226. }
  227. FreeLibrary(hInst);
  228. }
  229. else
  230. {
  231. dwRes = GetLastError();
  232. }
  233. }
  234. #ifdef DEBUG
  235. if (dwRes)
  236. {
  237. CMTRACE1(TEXT("WriteStringToCache() failed, err=%u."), dwRes);
  238. }
  239. #endif
  240. return (ERROR_SUCCESS == dwRes);
  241. }
  242. #endif //TEST_USERINFO_UPGRADE
  243. //+----------------------------------------------------------------------------
  244. //
  245. // Function: BuildUserInfoSubKey
  246. //
  247. // Synopsis: Constructs the appropriate subkey for UserInfo based on the service
  248. // name key and the user mode of the profile.
  249. //
  250. // Arguments: LPCTSTR pszServiceKey - The service name key
  251. // BOOL fAllUser - Flag indicating that profile is All-User
  252. //
  253. // Returns: LPTSTR - Ptr to allocated buffer containing subkey or NULL on failure.
  254. //
  255. // History: nickball Created 8/14/98
  256. //
  257. //+----------------------------------------------------------------------------
  258. LPTSTR BuildUserInfoSubKey(LPCTSTR pszServiceKey, BOOL fAllUser)
  259. {
  260. MYDBGASSERT(pszServiceKey);
  261. if (NULL == pszServiceKey)
  262. {
  263. return NULL;
  264. }
  265. //
  266. // Use the appropriate base key
  267. //
  268. LPTSTR pszSubKey = NULL;
  269. if (fAllUser)
  270. {
  271. pszSubKey = CmStrCpyAlloc(c_pszRegCmUserInfo);
  272. }
  273. else
  274. {
  275. pszSubKey = CmStrCpyAlloc(c_pszRegCmSingleUserInfo);
  276. }
  277. MYDBGASSERT(pszSubKey);
  278. //
  279. // Append profile service name
  280. //
  281. if (pszSubKey && *pszSubKey)
  282. {
  283. pszSubKey = CmStrCatAlloc(&pszSubKey, pszServiceKey);
  284. MYDBGASSERT(pszSubKey);
  285. return pszSubKey;
  286. }
  287. CmFree(pszSubKey);
  288. return NULL;
  289. }
  290. //+----------------------------------------------------------------------------
  291. //
  292. // Function: BuildICSDataInfoSubKey
  293. //
  294. // Synopsis: Constructs the appropriate subkey for ICS UserInfo based on the service
  295. // name key.
  296. //
  297. // Arguments: LPCTSTR pszServiceKey - The service name key
  298. //
  299. // Returns: LPTSTR - Ptr to allocated buffer containing subkey or NULL on failure.
  300. //
  301. // History: 03/30/2001 tomkel Created
  302. //
  303. //+----------------------------------------------------------------------------
  304. LPTSTR BuildICSDataInfoSubKey(LPCTSTR pszServiceKey)
  305. {
  306. MYDBGASSERT(pszServiceKey);
  307. if (NULL == pszServiceKey)
  308. {
  309. return NULL;
  310. }
  311. //
  312. // Use the appropriate base key
  313. //
  314. LPTSTR pszSubKey = NULL;
  315. pszSubKey = CmStrCpyAlloc(c_pszRegCmRoot);
  316. MYDBGASSERT(pszSubKey);
  317. //
  318. // Append profile service name
  319. //
  320. if (pszSubKey && *pszSubKey)
  321. {
  322. pszSubKey = CmStrCatAlloc(&pszSubKey, pszServiceKey);
  323. MYDBGASSERT(pszSubKey);
  324. if (pszSubKey)
  325. {
  326. CmStrCatAlloc(&pszSubKey, TEXT("\\"));
  327. if (pszSubKey)
  328. {
  329. CmStrCatAlloc(&pszSubKey, c_pszCmRegKeyICSDataKey);
  330. }
  331. }
  332. return pszSubKey;
  333. }
  334. CmFree(pszSubKey);
  335. return NULL;
  336. }
  337. //+----------------------------------------------------------------------------
  338. //
  339. // Function: dwGetWNetCachedPassword
  340. //
  341. // Synopsis: Wrapper to encapsulate linking to MPR.DLL and calling GetWNetCac
  342. // hedPassword.
  343. //
  344. // Arguments: LPSTR pszEntryName - The names of the key used to identify the password.
  345. // LPSTR* ppszStr - The buffer to receive the retrieved password.
  346. // WORD* pwSizeOfStr - The size of the input buffer. Also receives
  347. // of the # of chars retrieved.
  348. //
  349. // Returns: DWORD - Windows error code.
  350. //
  351. // History: nickball Created Header 6/17/99
  352. //
  353. //+----------------------------------------------------------------------------
  354. DWORD dwGetWNetCachedPassword(LPSTR pszEntryName, LPSTR* ppszStr, WORD* pwSizeOfStr)
  355. {
  356. MYDBGASSERT(OS_W9X);
  357. DWORD dwRes = ERROR_SUCCESS;
  358. WORD (WINAPI *pfnFunc)(LPSTR,WORD,LPSTR,LPWORD,BYTE) = NULL;
  359. HINSTANCE hInst = NULL;
  360. //
  361. // Load MPR for system password cache support
  362. //
  363. MYVERIFY(hInst = LoadLibraryExA("mpr.dll", NULL, 0));
  364. if (hInst)
  365. {
  366. //
  367. // Get function ptr for WNetGetCachedPassword API and retrieve the string
  368. //
  369. MYVERIFY(pfnFunc = (WORD (WINAPI *)(LPSTR,WORD,LPSTR,LPWORD,BYTE))
  370. GetProcAddress(hInst, "WNetGetCachedPassword"));
  371. //
  372. // Read the cache data
  373. //
  374. if (pfnFunc)
  375. {
  376. //
  377. // NOTE: Final param must be CACHE_KEY_LEN (80), no docs to indicate
  378. // exact usage of API but retrieval is tied to the value used when
  379. // storing the pwd. Thus we hard code to CACHE_KEY_LEN because this
  380. // is the value that was used by the original version that stored
  381. // the password in the 9X cache. The receiving buffer size is
  382. // retained at 256 to minimize delta from latest shipping version.
  383. //
  384. // NT# 355459 - nickball - 6/17/99
  385. //
  386. dwRes = pfnFunc(pszEntryName, (WORD)lstrlenA(pszEntryName),
  387. *ppszStr, pwSizeOfStr, CACHE_KEY_LEN);
  388. }
  389. else
  390. {
  391. dwRes = GetLastError();
  392. }
  393. }
  394. else
  395. {
  396. dwRes = GetLastError();
  397. }
  398. if (NULL != hInst)
  399. {
  400. FreeLibrary(hInst);
  401. }
  402. return (dwRes);
  403. }
  404. //+---------------------------------------------------------------------------
  405. //
  406. // Function: ReadStringFromCache
  407. //
  408. // Synopsis: Read a null terminated string from cache.
  409. //
  410. // Arguments: pArgs ptr to ArgsStruct
  411. // pszEntryName name to identify the cache entry
  412. // ppszStr ptr to the ptr of the buffer.
  413. //
  414. // Returns: BOOL TRUE = success, FALSE = failure
  415. //
  416. //----------------------------------------------------------------------------
  417. BOOL ReadStringFromCache(
  418. ArgsStruct *pArgs,
  419. LPTSTR pszEntryName,
  420. LPTSTR *ppszStr
  421. )
  422. {
  423. DWORD dwRes = ERROR_SUCCESS;
  424. //
  425. // Alloc buffer - the buffer is uuencoded. See UserInfoToString().
  426. //
  427. WORD wBufSize = 256; // arbitrary, we used to use 80 on W95
  428. //
  429. // On NT, we use the Local Security Authority (LSA) services for reading
  430. // the string in the legacy case. On Win9x, we uses mpr.dll.
  431. // Note: wBufSize is used as an in\out param, can be modified below.
  432. //
  433. if (OS_NT)
  434. {
  435. if (InitLsa(pArgs))
  436. {
  437. if (!(*ppszStr = (LPTSTR)CmMalloc(wBufSize)))
  438. {
  439. return FALSE;
  440. }
  441. dwRes = LSA_ReadString(pArgs, pszEntryName, *ppszStr, wBufSize);
  442. DeInitLsa(pArgs);
  443. }
  444. else
  445. {
  446. dwRes = GetLastError();
  447. }
  448. }
  449. else
  450. {
  451. //
  452. // for Windows95
  453. //
  454. LPSTR pszAnsiStr = (LPSTR)CmMalloc(wBufSize);
  455. LPSTR pszAnsiEntryName = WzToSzWithAlloc(pszEntryName);
  456. if (pszAnsiStr && pszAnsiEntryName)
  457. {
  458. dwRes = dwGetWNetCachedPassword(pszAnsiEntryName, &pszAnsiStr, &wBufSize);
  459. if (ERROR_SUCCESS == dwRes)
  460. {
  461. *ppszStr = SzToWzWithAlloc(pszAnsiStr);
  462. if (NULL == *ppszStr)
  463. {
  464. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  465. }
  466. }
  467. }
  468. CmFree (pszAnsiStr);
  469. CmFree (pszAnsiEntryName);
  470. }
  471. if (dwRes)
  472. {
  473. CmFree(*ppszStr);
  474. *ppszStr = NULL;
  475. CMTRACE1(TEXT("ReadStringFromCache() failed, err=%u."), dwRes);
  476. }
  477. return (ERROR_SUCCESS == dwRes);
  478. }
  479. //+---------------------------------------------------------------------------
  480. //
  481. // Function: DeleteStringFromCache
  482. //
  483. // Synopsis: Delete the string from cache.
  484. //
  485. // Arguments: pArgs ptr to ArgsStruct
  486. // pszEntryName name to identify the cache entry
  487. //
  488. // Returns: BOOL TRUE = success, FALSE = failure
  489. //
  490. //----------------------------------------------------------------------------
  491. BOOL DeleteStringFromCache(
  492. ArgsStruct *pArgs,
  493. LPTSTR pszEntryName
  494. )
  495. {
  496. DWORD dwRes;
  497. //
  498. // on NT, we use the Local Security Authority (LSA) services for storing
  499. // the string. On Win95, we use mpr.dll.
  500. //
  501. if (OS_NT)
  502. {
  503. if (InitLsa(pArgs))
  504. {
  505. dwRes = LSA_WriteString(pArgs, pszEntryName, NULL);
  506. DeInitLsa(pArgs);
  507. }
  508. else
  509. {
  510. dwRes = GetLastError();
  511. }
  512. }
  513. else
  514. {
  515. //
  516. // for Windows95
  517. //
  518. HINSTANCE hInst = NULL;
  519. WORD (WINAPI *pfnFunc)(LPSTR,WORD,BYTE) = NULL;
  520. // Load MPR for system password cache support
  521. MYVERIFY(hInst = LoadLibraryExA("mpr.dll", NULL, 0));
  522. // Get function ptr for WNetRemoveCachedPassword API and remove the string
  523. if (!hInst)
  524. {
  525. return FALSE;
  526. }
  527. MYVERIFY(pfnFunc = (WORD (WINAPI *)(LPSTR,WORD,BYTE))
  528. GetProcAddress(hInst, "WNetRemoveCachedPassword"));
  529. if (!pfnFunc)
  530. {
  531. FreeLibrary(hInst);
  532. return FALSE;
  533. }
  534. LPSTR pszAnsiEntryName = WzToSzWithAlloc(pszEntryName);
  535. if (pszAnsiEntryName)
  536. {
  537. dwRes = pfnFunc(pszAnsiEntryName, (WORD)lstrlenA(pszAnsiEntryName), CACHE_KEY_LEN);
  538. }
  539. else
  540. {
  541. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  542. }
  543. CmFree (pszAnsiEntryName);
  544. FreeLibrary(hInst);
  545. }
  546. #ifdef DEBUG
  547. if (dwRes)
  548. {
  549. CMTRACE1(TEXT("DeleteStringFromCache() LSA_WriteString/WNetRemoveCachedPassword() failed, err=%u."), dwRes);
  550. }
  551. #endif
  552. return (ERROR_SUCCESS == dwRes);
  553. }
  554. //+---------------------------------------------------------------------------
  555. //
  556. // Function: RasSetCredsWrapper
  557. //
  558. // Synopsis: Wrapper to call RasSetCredential. This function stores the
  559. // given string in the appropriate field of a RASCREDENTIALS struct
  560. // (based on the value in dwMask) and calls RasSetCredentials.
  561. //
  562. //
  563. // Arguments: pArgs ptr to ArgsStruct
  564. // pszPhoneBook Full path to the phonebook file, or NULL for
  565. // the default all user pbk
  566. // dwMask dwMask value to set in the RASCREDENTIALS
  567. // struct. Currently must be one of RASCM_UserName,
  568. // RASCM_Domain, or RASCM_Password.
  569. // pszData string data to set
  570. //
  571. // Returns: DWORD ERROR_SUCCESS if successful, a windows error code otherwise
  572. //
  573. //----------------------------------------------------------------------------
  574. DWORD RasSetCredsWrapper(
  575. ArgsStruct *pArgs,
  576. LPCTSTR pszPhoneBook,
  577. DWORD dwMask,
  578. LPCTSTR pszData
  579. )
  580. {
  581. DWORD dwRet = ERROR_INVALID_PARAMETER;
  582. BOOL fSavePassword = TRUE;
  583. MYDBGASSERT(pArgs && pArgs->rlsRasLink.pfnSetCredentials);
  584. MYDBGASSERT(pszData);
  585. MYDBGASSERT((RASCM_UserName == dwMask) || (RASCM_Domain == dwMask) || (RASCM_Password == dwMask));
  586. if (pArgs && pszData && pArgs->rlsRasLink.pfnSetCredentials)
  587. {
  588. LPTSTR pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
  589. if (pszConnectoid)
  590. {
  591. RASCREDENTIALS RasCredentials = {0};
  592. RasCredentials.dwSize = sizeof(RasCredentials);
  593. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  594. {
  595. RasCredentials.dwMask = dwMask | RASCM_DefaultCreds;
  596. }
  597. else
  598. {
  599. RasCredentials.dwMask = dwMask;
  600. }
  601. BOOL bClearPassword = FALSE;
  602. if (RASCM_UserName == dwMask)
  603. {
  604. lstrcpyU(RasCredentials.szUserName, pszData);
  605. }
  606. else if (RASCM_Domain == dwMask)
  607. {
  608. lstrcpyU(RasCredentials.szDomain, pszData);
  609. }
  610. else if (RASCM_Password == dwMask)
  611. {
  612. if (0 == lstrcmpU(c_pszSavedPasswordToken, pszData))
  613. {
  614. //
  615. // We have 16 *'s. This password is from the RAS cred store,
  616. // so we don't want to save the 16 *'s
  617. //
  618. fSavePassword = FALSE;
  619. }
  620. else
  621. {
  622. lstrcpyU(RasCredentials.szPassword, pszData);
  623. bClearPassword = (TEXT('\0') == pszData[0]);
  624. }
  625. }
  626. else
  627. {
  628. CmFree(pszConnectoid);
  629. return ERROR_INVALID_PARAMETER;
  630. }
  631. if (fSavePassword)
  632. {
  633. dwRet = pArgs->rlsRasLink.pfnSetCredentials(pszPhoneBook, pszConnectoid, &RasCredentials, bClearPassword);
  634. if (ERROR_CANNOT_FIND_PHONEBOOK_ENTRY == dwRet)
  635. {
  636. //
  637. // Then the phonebook entry doesn't exist yet, lets create it.
  638. //
  639. LPRASENTRY pRasEntry = (LPRASENTRY)CmMalloc(sizeof(RASENTRY));
  640. if (pRasEntry && pArgs->rlsRasLink.pfnSetEntryProperties)
  641. {
  642. pRasEntry->dwSize = sizeof(RASENTRY);
  643. dwRet = pArgs->rlsRasLink.pfnSetEntryProperties(pszPhoneBook, pszConnectoid, pRasEntry, pRasEntry->dwSize, NULL, 0);
  644. //
  645. // Lets try to set the credentials one more time ...
  646. //
  647. if (ERROR_SUCCESS == dwRet)
  648. {
  649. dwRet = pArgs->rlsRasLink.pfnSetCredentials(pszPhoneBook, pszConnectoid, &RasCredentials, bClearPassword);
  650. }
  651. CmFree(pRasEntry);
  652. }
  653. }
  654. }
  655. CmWipePassword(RasCredentials.szPassword);
  656. CmFree(pszConnectoid);
  657. }
  658. }
  659. return dwRet;
  660. }
  661. //+---------------------------------------------------------------------------
  662. //
  663. // Function: WriteUserInfoToRas
  664. //
  665. // Synopsis: Write a userinfo data to ras credential storage
  666. //
  667. // Arguments: pArgs ptr to ArgsStruct
  668. // uiDataID the resource ID associated with the data
  669. // pvData userinfo data
  670. //
  671. // Returns: int TRUE = success, FALSE = failure, returns -1 if RAS
  672. // doesn't cache this piece of data and it should be put
  673. // in the registry instead.
  674. //
  675. //----------------------------------------------------------------------------
  676. int WriteUserInfoToRas(
  677. ArgsStruct *pArgs,
  678. UINT uiDataID,
  679. PVOID pvData)
  680. {
  681. int iReturn = -1;
  682. if (OS_NT5 && pArgs && pArgs->bUseRasCredStore)
  683. {
  684. DWORD dwMask;
  685. LPTSTR pszPhoneBook = NULL;
  686. switch (uiDataID)
  687. {
  688. case UD_ID_USERNAME:
  689. dwMask = RASCM_UserName;
  690. iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, (LPCTSTR)pvData));
  691. break;
  692. case UD_ID_PASSWORD:
  693. dwMask = RASCM_Password;
  694. iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, (LPCTSTR)pvData));
  695. MYDBGASSERT(iReturn);
  696. //
  697. // Note that if we are using the same username then we want to write the password to both the
  698. // password and the InetPassword storage. This is because we don't actually have a password, just
  699. // 16 *'s. This tells RAS to look in its internal store for the password. The trouble is that if
  700. // we don't cache the real password when we hand RAS the 16 *'s, it looks and finds a NULL password.
  701. // Thus we keep both passwords the same and this avoids that problem.
  702. //
  703. if (pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryUseSameUserName))
  704. {
  705. pszPhoneBook = CreateRasPrivatePbk(pArgs);
  706. if (pszPhoneBook)
  707. {
  708. iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pszPhoneBook, dwMask, (LPCTSTR)pvData));
  709. CmFree(pszPhoneBook);
  710. }
  711. }
  712. break;
  713. case UD_ID_DOMAIN:
  714. dwMask = RASCM_Domain;
  715. iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, (LPCTSTR)pvData));
  716. break;
  717. case UD_ID_INET_PASSWORD:
  718. dwMask = RASCM_Password;
  719. pszPhoneBook = CreateRasPrivatePbk(pArgs);
  720. if (pszPhoneBook)
  721. {
  722. iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pszPhoneBook, dwMask, (LPCTSTR)pvData));
  723. CmFree(pszPhoneBook);
  724. }
  725. break;
  726. case UD_ID_INET_USERNAME:
  727. dwMask = RASCM_UserName;
  728. pszPhoneBook = CreateRasPrivatePbk(pArgs);
  729. if (pszPhoneBook)
  730. {
  731. iReturn = (ERROR_SUCCESS == RasSetCredsWrapper(pArgs, pszPhoneBook, dwMask, (LPCTSTR)pvData));
  732. CmFree(pszPhoneBook);
  733. }
  734. break;
  735. default:
  736. break;
  737. }
  738. }
  739. if ((0 != iReturn) && (-1 != iReturn))
  740. {
  741. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  742. {
  743. CMTRACE1(TEXT("WriteUserInfoToRas() - %s saved to the Global RAS Credential store"), TranslateUserDataID(uiDataID));
  744. }
  745. else
  746. {
  747. CMTRACE1(TEXT("WriteUserInfoToRas() - %s saved to the User RAS Credential store"), TranslateUserDataID(uiDataID));
  748. }
  749. }
  750. return iReturn;
  751. }
  752. //+---------------------------------------------------------------------------
  753. //
  754. // Function: WriteUserInfoToReg
  755. //
  756. // Synopsis: Write a userinfo data to the registry.
  757. //
  758. // Arguments: pArgs ptr to ArgsStruct
  759. // uiDataID the resource ID associated with the data
  760. // pvData userinfo data
  761. //
  762. // Returns: BOOL TRUE = success, FALSE = failure
  763. //
  764. //----------------------------------------------------------------------------
  765. BOOL WriteUserInfoToReg(
  766. ArgsStruct *pArgs,
  767. UINT uiDataID,
  768. PVOID pvData)
  769. {
  770. MYDBGASSERT(pArgs);
  771. MYDBGASSERT(pvData);
  772. BOOL fRet = FALSE;
  773. UINT uiID = uiDataID; // can be changed in switch
  774. BYTE *lpData;
  775. if (NULL == pArgs || NULL == pvData)
  776. {
  777. return FALSE;
  778. }
  779. //
  780. // Determine Reg params based upon uiDataID
  781. //
  782. switch (uiID)
  783. {
  784. case UD_ID_USERNAME:
  785. case UD_ID_INET_USERNAME:
  786. case UD_ID_DOMAIN:
  787. case UD_ID_CURRENTACCESSPOINT:
  788. {
  789. //
  790. // Store as strings
  791. //
  792. DWORD dwSize = (lstrlenU((LPTSTR)pvData) + 1) * sizeof(TCHAR);
  793. MYDBGASSERT(dwSize <= (UNLEN + sizeof(TCHAR))); // Make sure size is reasonable
  794. lpData = (BYTE *) pvData;
  795. fRet = WriteDataToReg(pArgs->szServiceName, uiID, REG_SZ, lpData, dwSize, pArgs->fAllUser);
  796. break;
  797. }
  798. case UD_ID_PASSWORD:
  799. case UD_ID_INET_PASSWORD:
  800. {
  801. DWORD dwBufLen = 0;
  802. DWORD dwCrypt = 0;
  803. LPTSTR pszSubKey = BuildUserInfoSubKey(pArgs->szServiceName, pArgs->fAllUser);
  804. LPSTR pszAnsiSubKey = WzToSzWithAlloc(pszSubKey);
  805. if (UD_ID_INET_PASSWORD == uiID)
  806. {
  807. dwCrypt |= CMSECURE_ET_USE_SECOND_RND_KEY;
  808. }
  809. //
  810. // Encrypt
  811. //
  812. LPTSTR pszEncryptedData = EncryptPassword(pArgs, (LPTSTR) pvData, &dwBufLen, &dwCrypt, TRUE, pszAnsiSubKey);
  813. //
  814. // Free in case we return if the function failed
  815. //
  816. CmFree(pszSubKey);
  817. CmFree(pszAnsiSubKey);
  818. if (!pszEncryptedData)
  819. {
  820. return FALSE;
  821. }
  822. MYDBGASSERT(dwBufLen <= CM_MAX_PWD); // Can't read it out otherwise
  823. //
  824. // Write the password and the encryption type on success
  825. //
  826. if (WriteDataToReg(pArgs->szServiceName, uiID, REG_BINARY, (BYTE *) pszEncryptedData, dwBufLen, pArgs->fAllUser))
  827. {
  828. //
  829. // A second write for the encryption type. Written as a DWORD.
  830. //
  831. uiID = UD_ID_PCS;
  832. //
  833. // Now that we're UNICODE enabled, we will always be encrypting
  834. // a UNICODE string, so update the crypt type, so that it can be
  835. // properly decrypted.
  836. //
  837. dwCrypt = AnsiToUnicodePcs(dwCrypt);
  838. lpData = (BYTE *) &dwCrypt;
  839. fRet = WriteDataToReg(pArgs->szServiceName, uiID, REG_DWORD, lpData, sizeof(DWORD), pArgs->fAllUser);
  840. }
  841. //
  842. // Release the buffer before we go
  843. //
  844. CmFree(pszEncryptedData);
  845. break;
  846. }
  847. case UD_ID_NOPROMPT:
  848. case UD_ID_REMEMBER_PWD:
  849. case UD_ID_REMEMBER_INET_PASSWORD:
  850. case UD_ID_ACCESSPOINTENABLED:
  851. {
  852. //
  853. // Store BOOL as DWORD
  854. //
  855. DWORD dwTmp = *(LPBOOL)pvData;
  856. lpData = (BYTE *) &dwTmp;
  857. fRet = WriteDataToReg(pArgs->szServiceName, uiID, REG_DWORD, lpData, sizeof(DWORD), pArgs->fAllUser);
  858. break;
  859. }
  860. default:
  861. break;
  862. }
  863. MYDBGASSERT(fRet);
  864. return fRet;
  865. }
  866. //+----------------------------------------------------------------------------
  867. //
  868. // Function: WriteDataToReg
  869. //
  870. // Synopsis: Stores the specified data as the specifed value under the
  871. // specified key under the userinfo root.
  872. //
  873. // Arguments: LPCTSTR pszKey - The key name (service name)
  874. // UINT uiDataID - The resource ID, used to name the value
  875. // DWORD dwType - The registry data type
  876. // CONST BYTE *lpData - Ptr to the data to be stored
  877. // DWORD cbData - The size of the data buffer
  878. // BOOL fAllUser - Flag indicating that profile is All-User
  879. //
  880. // Returns: BOOL - TRUE on success, otherwise FALSE
  881. //
  882. // History: nickball Created 5/21/98
  883. //
  884. //+----------------------------------------------------------------------------
  885. BOOL WriteDataToReg(
  886. LPCTSTR pszKey,
  887. UINT uiDataID,
  888. DWORD dwType,
  889. CONST BYTE *lpData,
  890. DWORD cbData,
  891. BOOL fAllUser)
  892. {
  893. MYDBGASSERT(pszKey && *pszKey);
  894. MYDBGASSERT(lpData);
  895. HKEY hKeyCm;
  896. DWORD dwDisposition;
  897. DWORD dwRes = 1;
  898. LPTSTR pszSubKey;
  899. if (NULL == pszKey || !*pszKey || NULL == lpData)
  900. {
  901. return FALSE;
  902. }
  903. //
  904. // Per-user data is always stored under HKEY_CURRENT_USER
  905. // Build the sub key to be opened.
  906. //
  907. pszSubKey = BuildUserInfoSubKey(pszKey, fAllUser);
  908. if (NULL == pszSubKey)
  909. {
  910. return FALSE;
  911. }
  912. //
  913. // Open the sub key under HKCU
  914. //
  915. dwRes = RegCreateKeyExU(HKEY_CURRENT_USER,
  916. pszSubKey,
  917. 0,
  918. TEXT(""),
  919. REG_OPTION_NON_VOLATILE,
  920. KEY_SET_VALUE,
  921. NULL,
  922. &hKeyCm,
  923. &dwDisposition);
  924. //
  925. // If we opened the key successfully, write the value
  926. //
  927. if (ERROR_SUCCESS == dwRes)
  928. {
  929. dwRes = RegSetValueExU(hKeyCm,
  930. TranslateUserDataID(uiDataID),
  931. NULL,
  932. dwType,
  933. lpData,
  934. cbData);
  935. #ifdef DEBUG
  936. if (ERROR_SUCCESS == dwRes)
  937. {
  938. CMTRACE1(TEXT("WriteDataToReg() - %s written to registry"), TranslateUserDataID(uiDataID));
  939. }
  940. #endif
  941. RegCloseKey(hKeyCm);
  942. }
  943. CmFree(pszSubKey);
  944. return (ERROR_SUCCESS == dwRes);
  945. }
  946. //+----------------------------------------------------------------------------
  947. //
  948. // Function: DeleteDataFromReg
  949. //
  950. // Synopsis: Deletes the specified value under the specified by uiDataID
  951. //
  952. // Arguments: LPCTSTR pszKey - The key name (service name)
  953. // UINT uiDataID - The resource ID, used to name the value
  954. // BOOL fAllUser - Flag indicating that profile is All-User
  955. //
  956. // Returns: BOOL - TRUE on success, otherwise FALSE
  957. //
  958. // History: nickball Created 5/21/98
  959. //
  960. //+----------------------------------------------------------------------------
  961. BOOL DeleteDataFromReg(
  962. LPCTSTR pszKey,
  963. UINT uiDataID,
  964. BOOL fAllUser)
  965. {
  966. MYDBGASSERT(pszKey && *pszKey);
  967. HKEY hKeyCm;
  968. DWORD dwRes = 1;
  969. LPTSTR pszSubKey;
  970. if (NULL == pszKey || !*pszKey)
  971. {
  972. return FALSE;
  973. }
  974. //
  975. // Per-user data is always stored under HKEY_CURRENT_USER
  976. // Build the sub key to be opened.
  977. //
  978. pszSubKey = BuildUserInfoSubKey(pszKey, fAllUser);
  979. if (NULL == pszSubKey)
  980. {
  981. return FALSE;
  982. }
  983. //
  984. // Open the sub key under HKCU
  985. //
  986. dwRes = RegOpenKeyExU(HKEY_CURRENT_USER,
  987. pszSubKey,
  988. 0,
  989. KEY_SET_VALUE,
  990. &hKeyCm);
  991. //
  992. // If we opened the key successfully, delete the value
  993. //
  994. if (ERROR_SUCCESS == dwRes)
  995. {
  996. dwRes = RegDeleteValueU(hKeyCm, TranslateUserDataID(uiDataID));
  997. //
  998. // Delete the key used for encrypting the passwords
  999. //
  1000. if (UD_ID_PASSWORD == uiDataID)
  1001. {
  1002. dwRes = RegDeleteValueU(hKeyCm, c_pszCmRegKeyEncryptedPasswordKey);
  1003. }
  1004. if (UD_ID_INET_PASSWORD == uiDataID)
  1005. {
  1006. dwRes = RegDeleteValueU(hKeyCm, c_pszCmRegKeyEncryptedInternetPasswordKey);
  1007. }
  1008. #ifdef DEBUG
  1009. if (ERROR_SUCCESS == dwRes)
  1010. {
  1011. CMTRACE1(TEXT("DeleteDataFromReg() - %s removed from registry"), TranslateUserDataID(uiDataID));
  1012. }
  1013. #endif
  1014. RegCloseKey(hKeyCm);
  1015. }
  1016. CmFree(pszSubKey);
  1017. return (ERROR_SUCCESS == dwRes);
  1018. }
  1019. //+----------------------------------------------------------------------------
  1020. //
  1021. // Function: GetDataFromReg
  1022. //
  1023. // Synopsis: Allocates a buffer for and retrieves the specifed data from the
  1024. // registry.
  1025. //
  1026. // Arguments: LPCTSTR pszKey - The key name (service name)
  1027. // UINT uiDataID - The resource ID, used to name the value
  1028. // DWORD dwType - The registry data type
  1029. // DWORD dwSize - Numbrt of bytes in the data buffer
  1030. // BOOL fAllUser - Flag indicating that profile is All-User
  1031. //
  1032. // Returns: LPBYTE - Ptr to retrieved data, NULL on error
  1033. //
  1034. // History: nickball Created 5/21/98
  1035. //
  1036. //+----------------------------------------------------------------------------
  1037. LPBYTE GetDataFromReg(
  1038. LPCTSTR pszKey,
  1039. UINT uiDataID,
  1040. DWORD dwType,
  1041. DWORD dwSize,
  1042. BOOL fAllUser)
  1043. {
  1044. MYDBGASSERT(pszKey);
  1045. DWORD dwSizeTmp = dwSize;
  1046. DWORD dwTypeTmp = dwType;
  1047. if (NULL == pszKey || !*pszKey)
  1048. {
  1049. return NULL;
  1050. }
  1051. //
  1052. // Allocate a buffer of the desired size
  1053. //
  1054. LPBYTE lpData = (BYTE *) CmMalloc(dwSize);
  1055. if (NULL == lpData)
  1056. {
  1057. return FALSE;
  1058. }
  1059. //
  1060. // Read the data from the registry
  1061. //
  1062. if (!ReadDataFromReg(pszKey, uiDataID, &dwTypeTmp, lpData, &dwSizeTmp, fAllUser))
  1063. {
  1064. CmFree(lpData);
  1065. lpData = NULL;
  1066. }
  1067. return lpData;
  1068. }
  1069. //+---------------------------------------------------------------------------
  1070. //
  1071. // Function: ReadUserInfoFromReg
  1072. //
  1073. // Synopsis: Read the specified userinfo data from the registry.
  1074. //
  1075. // Arguments: pArgs ptr to ArgsStruct
  1076. // uiDataID the resource ID associated with the data
  1077. // ppvData ptr to ptr to be allocated and filled
  1078. //
  1079. // Returns: BOOL TRUE = success, FALSE = failure
  1080. //
  1081. //----------------------------------------------------------------------------
  1082. BOOL ReadUserInfoFromReg(
  1083. ArgsStruct *pArgs,
  1084. UINT uiDataID,
  1085. PVOID *ppvData)
  1086. {
  1087. MYDBGASSERT(pArgs);
  1088. MYDBGASSERT(ppvData);
  1089. BYTE *lpData = NULL;
  1090. if (NULL == pArgs || NULL == ppvData)
  1091. {
  1092. return FALSE;
  1093. }
  1094. //
  1095. // Set size and type as appropriate
  1096. //
  1097. switch (uiDataID)
  1098. {
  1099. case UD_ID_USERNAME:
  1100. case UD_ID_INET_USERNAME:
  1101. case UD_ID_DOMAIN:
  1102. case UD_ID_CURRENTACCESSPOINT:
  1103. {
  1104. lpData = GetDataFromReg(pArgs->szServiceName, uiDataID, REG_SZ, (UNLEN + 1) * sizeof(TCHAR), pArgs->fAllUser);
  1105. if (lpData)
  1106. {
  1107. *ppvData = lpData;
  1108. }
  1109. break;
  1110. }
  1111. case UD_ID_PASSWORD:
  1112. case UD_ID_INET_PASSWORD:
  1113. {
  1114. BYTE *lpTmp = NULL;
  1115. //
  1116. // Get the encryption type
  1117. //
  1118. lpData = GetDataFromReg(pArgs->szServiceName, UD_ID_PCS, REG_DWORD, sizeof(DWORD), pArgs->fAllUser);
  1119. if (!lpData)
  1120. {
  1121. return FALSE;
  1122. }
  1123. //
  1124. // Since we know the return value in this case is a DWORD, then cast it to DWORD pointer
  1125. // and get the value
  1126. //
  1127. DWORD dwCrypt = *((DWORD*)lpData);
  1128. CmFree(lpData);
  1129. //
  1130. // Now retrieve the encrypted password
  1131. //
  1132. lpData = GetDataFromReg(pArgs->szServiceName, uiDataID, REG_BINARY, CM_MAX_PWD, pArgs->fAllUser);
  1133. if (!lpData)
  1134. {
  1135. return FALSE;
  1136. }
  1137. //
  1138. // Decrypt it
  1139. //
  1140. DWORD dwSize = lstrlenU((LPTSTR)lpData)*sizeof(TCHAR);
  1141. //
  1142. // Crypt routines only know about Ansi PCS values, so convert as necessary
  1143. //
  1144. LPTSTR pszSubKey = BuildUserInfoSubKey(pArgs->szServiceName, pArgs->fAllUser);
  1145. LPSTR pszAnsiSubKey = WzToSzWithAlloc(pszSubKey);
  1146. if (UD_ID_INET_PASSWORD == uiDataID)
  1147. {
  1148. dwCrypt |= CMSECURE_ET_USE_SECOND_RND_KEY;
  1149. }
  1150. lpTmp = DecryptPassword(pArgs, (LPBYTE)lpData, UnicodeToAnsiPcs(dwCrypt), dwSize, TRUE, pszAnsiSubKey);
  1151. //
  1152. // Free the buffer for the reg query
  1153. //
  1154. CmFree(lpData);
  1155. //
  1156. // We're Unicode now, so if the password was encrypted
  1157. // as an Ansi string convert the data to a UNICODE string.
  1158. // Otherwise, just update the supplied buffer.
  1159. //
  1160. if (IsAnsiPcs(dwCrypt) && lpTmp)
  1161. {
  1162. *ppvData = SzToWzWithAlloc((LPSTR)lpTmp);
  1163. CmFree(lpTmp);
  1164. }
  1165. else
  1166. {
  1167. *ppvData = lpTmp;
  1168. }
  1169. //
  1170. // Assign lpData for return purposes
  1171. //
  1172. lpData = (BYTE*) *ppvData; // NULL on failure
  1173. CmFree(pszSubKey);
  1174. CmFree(pszAnsiSubKey);
  1175. break;
  1176. }
  1177. case UD_ID_NOPROMPT:
  1178. case UD_ID_REMEMBER_PWD:
  1179. case UD_ID_REMEMBER_INET_PASSWORD:
  1180. case UD_ID_ACCESSPOINTENABLED:
  1181. {
  1182. lpData = GetDataFromReg(pArgs->szServiceName, uiDataID, REG_DWORD, sizeof(DWORD), pArgs->fAllUser);
  1183. if (lpData)
  1184. {
  1185. //
  1186. // Translate to DWORD pointer and check the value
  1187. //
  1188. if (*((DWORD*)lpData))
  1189. {
  1190. *(BOOL *)*ppvData = TRUE;
  1191. }
  1192. else
  1193. {
  1194. *(BOOL *)*ppvData = FALSE;
  1195. }
  1196. CmFree(lpData);
  1197. }
  1198. break;
  1199. }
  1200. default:
  1201. MYDBGASSERT(FALSE);
  1202. return FALSE;
  1203. }
  1204. return (NULL != lpData);
  1205. }
  1206. //+----------------------------------------------------------------------------
  1207. //
  1208. // Function: ReadDataFromReg
  1209. //
  1210. // Synopsis: Retrieves the data from the specifed value under the
  1211. // specified key under the userinfo root.
  1212. //
  1213. // Arguments: LPCTSTR pszKey - The key name (service name)
  1214. // UINT uiDataID - The resource ID, used to name the value
  1215. // LPDWORD lpdwType - The registry data type expected, and returned
  1216. // CONST BYTE *lpData - Ptr to buffer for data
  1217. // LPDWORD lpcbData - The size of the data buffer
  1218. // BOOL fAllUser - Flag indicating that profile is All-User
  1219. //
  1220. // Returns: BOOL - TRUE on success, otherwise FALSE
  1221. //
  1222. // History: nickball Created 5/21/98
  1223. //
  1224. //+----------------------------------------------------------------------------
  1225. BOOL ReadDataFromReg(
  1226. LPCTSTR pszKey,
  1227. UINT uiDataID,
  1228. LPDWORD lpdwType,
  1229. BYTE *lpData,
  1230. LPDWORD lpcbData,
  1231. BOOL fAllUser)
  1232. {
  1233. MYDBGASSERT(pszKey && *pszKey);
  1234. MYDBGASSERT(lpData);
  1235. MYDBGASSERT(lpcbData);
  1236. MYDBGASSERT(lpdwType);
  1237. HKEY hKeyCm;
  1238. DWORD dwRes = 1;
  1239. DWORD dwTypeTmp; // the value returned by query
  1240. LPTSTR pszSubKey;
  1241. if (NULL == pszKey || !*pszKey || NULL == lpData)
  1242. {
  1243. return FALSE;
  1244. }
  1245. //
  1246. // Per-user data is always stored under HKEY_CURRENT_USER
  1247. // Build the sub key to be opened.
  1248. //
  1249. pszSubKey = BuildUserInfoSubKey(pszKey, fAllUser);
  1250. if (NULL == pszSubKey)
  1251. {
  1252. return FALSE;
  1253. }
  1254. //
  1255. // Open the sub key under HKCU
  1256. //
  1257. dwRes = RegOpenKeyExU(HKEY_CURRENT_USER,
  1258. pszSubKey,
  1259. 0,
  1260. KEY_QUERY_VALUE,
  1261. &hKeyCm);
  1262. //
  1263. // If we opened the key successfully, retrieve the value
  1264. //
  1265. if (ERROR_SUCCESS == dwRes)
  1266. {
  1267. dwRes = RegQueryValueExU(hKeyCm,
  1268. TranslateUserDataID(uiDataID),
  1269. NULL,
  1270. &dwTypeTmp,
  1271. lpData,
  1272. lpcbData);
  1273. if (ERROR_SUCCESS == dwRes)
  1274. {
  1275. CMTRACE1(TEXT("ReadDataFromReg() - %s read from registry"), TranslateUserDataID(uiDataID));
  1276. MYDBGASSERT(*lpdwType == dwTypeTmp);
  1277. if (*lpdwType == dwTypeTmp)
  1278. {
  1279. *lpdwType = dwTypeTmp;
  1280. }
  1281. }
  1282. RegCloseKey(hKeyCm);
  1283. }
  1284. CmFree(pszSubKey);
  1285. return (ERROR_SUCCESS == dwRes && (*lpdwType == dwTypeTmp)); // sanity check that type was expected
  1286. }
  1287. //+---------------------------------------------------------------------------
  1288. //
  1289. // Function: DeleteUserInfoFromReg
  1290. //
  1291. // Synopsis: Delete userinfo data from registry
  1292. //
  1293. // Arguments: pArgs ptr to ArgsStruct
  1294. // uiEntry cmp field entry id
  1295. //
  1296. // Returns: BOOL TRUE = success, FALSE = failure
  1297. //
  1298. //----------------------------------------------------------------------------
  1299. BOOL DeleteUserInfoFromReg(
  1300. ArgsStruct *pArgs,
  1301. UINT uiEntry
  1302. )
  1303. {
  1304. return DeleteDataFromReg(pArgs->szServiceName, uiEntry, pArgs->fAllUser);
  1305. }
  1306. //+---------------------------------------------------------------------------
  1307. //
  1308. // Function: DeleteUserInfoFromRas
  1309. //
  1310. // Synopsis: Delete userinfo data from the RAS credential cache
  1311. //
  1312. // Arguments: pArgs ptr to ArgsStruct
  1313. // uiEntry cmp field entry id
  1314. //
  1315. // Returns: int TRUE = success, FALSE = failure, -1 if RAS doesn't
  1316. // store this info
  1317. //
  1318. //----------------------------------------------------------------------------
  1319. int DeleteUserInfoFromRas(
  1320. ArgsStruct *pArgs,
  1321. UINT uiEntry
  1322. )
  1323. {
  1324. LPTSTR pszEmpty = TEXT("");
  1325. return WriteUserInfoToRas(pArgs, uiEntry, pszEmpty);
  1326. }
  1327. //+---------------------------------------------------------------------------
  1328. //
  1329. // Function: ReadPasswordFromCmp
  1330. //
  1331. // Synopsis: Read a null terminated password string from Cmp.
  1332. //
  1333. // Arguments: pArgs ptr to ArgsStruct
  1334. // uiEntry cmp entry name
  1335. // ppszPassword ptr to ptr of the password buffer.
  1336. //
  1337. // Returns: BOOL TRUE = success, FALSE = failure
  1338. //
  1339. //----------------------------------------------------------------------------
  1340. BOOL ReadPasswordFromCmp(
  1341. ArgsStruct *pArgs,
  1342. UINT uiEntry,
  1343. LPTSTR *ppszPassword
  1344. )
  1345. {
  1346. MYDBGASSERT(pArgs);
  1347. MYDBGASSERT(ppszPassword);
  1348. if (NULL == pArgs || NULL == ppszPassword)
  1349. {
  1350. return FALSE;
  1351. }
  1352. //
  1353. // Read in password from profile
  1354. //
  1355. BOOL fOk = FALSE;
  1356. LPTSTR pszEncryptedData = pArgs->piniProfile->GPPS(c_pszCmSection, TranslateUserDataID(uiEntry));
  1357. if (*pszEncryptedData)
  1358. {
  1359. //
  1360. // Trim away all the spaces at both ends
  1361. //
  1362. CmStrTrim(pszEncryptedData);
  1363. //
  1364. // Get the type and decrypt
  1365. //
  1366. DWORD dwEncryptionType = (DWORD)pArgs->piniProfile->GPPI(c_pszCmSection,
  1367. c_pszCmEntryPcs,
  1368. CMSECURE_ET_RC2); // default
  1369. //
  1370. // Since this was saved in the CMP in Ansi form, we need to convert the characters back to
  1371. // Ansi form so that we can decrypt them. We still may not be able to (if we cannot
  1372. // round trip the Unicode conversion for instance) but then we will fail and display a
  1373. // blank password. Not the end of the world but hopefully avoidable.
  1374. //
  1375. LPSTR pszAnsiEncryptedData;
  1376. LPSTR pszAnsiUnEncryptedData;
  1377. pszAnsiEncryptedData = WzToSzWithAlloc(pszEncryptedData);
  1378. if (NULL != pszAnsiEncryptedData)
  1379. {
  1380. DWORD dwSize = lstrlenA(pszAnsiEncryptedData)*sizeof(TCHAR);
  1381. //
  1382. // Here we don't need to differentiate between main password and internet password
  1383. // because we are reading this from a file and the mask is used when reading to/from
  1384. // registry.
  1385. //
  1386. pszAnsiUnEncryptedData = (LPSTR)DecryptPassword(pArgs,
  1387. (LPBYTE)pszAnsiEncryptedData,
  1388. dwEncryptionType,
  1389. dwSize,
  1390. FALSE,
  1391. NULL);
  1392. if (pszAnsiUnEncryptedData)
  1393. {
  1394. *ppszPassword = SzToWzWithAlloc(pszAnsiUnEncryptedData);
  1395. if (NULL != *ppszPassword)
  1396. {
  1397. fOk = ((BOOL)**ppszPassword);
  1398. }
  1399. CmWipePasswordA(pszAnsiUnEncryptedData);
  1400. CmFree(pszAnsiUnEncryptedData);
  1401. }
  1402. }
  1403. CmFree(pszAnsiEncryptedData);
  1404. }
  1405. CmFree(pszEncryptedData);
  1406. return fOk;
  1407. }
  1408. //+---------------------------------------------------------------------------
  1409. //
  1410. // Function: ReadUserInfoFromCmp
  1411. //
  1412. // Synopsis: Read a userinfo data from cmp.
  1413. //
  1414. // Arguments: pArgs ptr to ArgsStruct
  1415. // uiEntry the cmp file entry
  1416. // ppvData ptr to ptr to the data buffer. If the userinfo
  1417. // is multiple byte(e.g. password), the func allocs
  1418. // the buffer.
  1419. //
  1420. // Returns: BOOL TRUE = success, FALSE = failure
  1421. //
  1422. //----------------------------------------------------------------------------
  1423. BOOL ReadUserInfoFromCmp(
  1424. ArgsStruct *pArgs,
  1425. UINT uiEntry,
  1426. PVOID *ppvData
  1427. )
  1428. {
  1429. switch (uiEntry)
  1430. {
  1431. case UD_ID_USERNAME:
  1432. case UD_ID_INET_USERNAME:
  1433. case UD_ID_DOMAIN:
  1434. *ppvData = (PVOID)pArgs->piniProfile->GPPS(c_pszCmSection, TranslateUserDataID(uiEntry));
  1435. break;
  1436. case UD_ID_PASSWORD:
  1437. case UD_ID_INET_PASSWORD:
  1438. return ReadPasswordFromCmp(pArgs, uiEntry, (LPTSTR *)ppvData);
  1439. break;
  1440. case UD_ID_NOPROMPT:
  1441. case UD_ID_REMEMBER_PWD:
  1442. case UD_ID_REMEMBER_INET_PASSWORD:
  1443. *(BOOL *)(*ppvData) = pArgs->piniProfile->GPPB(c_pszCmSection, TranslateUserDataID(uiEntry));
  1444. break;
  1445. //
  1446. // None of these should be in the CMP by this point. Return a failure value.
  1447. //
  1448. case UD_ID_PCS:
  1449. case UD_ID_ACCESSPOINTENABLED:
  1450. case UD_ID_CURRENTACCESSPOINT: // if we are trying to read the access point
  1451. CMASSERTMSG(FALSE, TEXT("ReadUserInfoFromCmp -- trying to read a value that should never be in the cmp, why?"));
  1452. *ppvData = NULL;
  1453. return FALSE;
  1454. break;
  1455. default:
  1456. MYDBGASSERT(0);
  1457. break;
  1458. }
  1459. return TRUE;
  1460. }
  1461. //+---------------------------------------------------------------------------
  1462. //
  1463. // Function: DeleteUserInfoFromCmp
  1464. //
  1465. // Synopsis: Deletes userinfo data from cmp.
  1466. //
  1467. // Arguments: pArgs ptr to ArgsStruct
  1468. // uiEntry the cmp file entry
  1469. //
  1470. // Returns: BOOL TRUE = success, FALSE = failure
  1471. //
  1472. //----------------------------------------------------------------------------
  1473. BOOL DeleteUserInfoFromCmp(
  1474. ArgsStruct *pArgs,
  1475. UINT uiEntry
  1476. )
  1477. {
  1478. BOOL bReturn = FALSE;
  1479. UINT uiKeepDefCreds = 0;
  1480. const TCHAR* const c_pszKeepDefaultCredentials = TEXT("KeepDefaultCredentials");
  1481. if (NULL == pArgs)
  1482. {
  1483. return bReturn;
  1484. }
  1485. switch (uiEntry)
  1486. {
  1487. case UD_ID_USERNAME:
  1488. case UD_ID_DOMAIN:
  1489. case UD_ID_INET_USERNAME:
  1490. case UD_ID_NOPROMPT:
  1491. case UD_ID_REMEMBER_PWD:
  1492. case UD_ID_REMEMBER_INET_PASSWORD:
  1493. case UD_ID_PASSWORD:
  1494. case UD_ID_INET_PASSWORD:
  1495. //
  1496. // Get KeepDefaultCredentials value from CMP
  1497. //
  1498. uiKeepDefCreds = GetPrivateProfileIntU(c_pszCmSection, c_pszKeepDefaultCredentials, 0,
  1499. pArgs->piniProfile->GetFile());
  1500. if (0 == uiKeepDefCreds)
  1501. {
  1502. if (WritePrivateProfileStringU(c_pszCmSection, TranslateUserDataID(uiEntry),
  1503. NULL, pArgs->piniProfile->GetFile()))
  1504. {
  1505. bReturn = TRUE;
  1506. }
  1507. }
  1508. break;
  1509. default:
  1510. MYDBGASSERT(0);
  1511. break;
  1512. }
  1513. return bReturn;
  1514. }
  1515. //+---------------------------------------------------------------------------
  1516. //
  1517. // Function: RasGetCredsWrapper
  1518. //
  1519. // Synopsis: Wrapper function to call RasGetCredentials. The function
  1520. // calls RasGetCredentials and then copies the appropriate data
  1521. // from the RASCREDENTIALS struct into the buffer pointed to by
  1522. // *ppvData (allocated on the caller behalf). Note that the value
  1523. // set in dwMask determines which data item is retrieved from the
  1524. // credentials cache. Currently, dwMask must be one of RASCM_UserName,
  1525. // RASCM_Domain, or RASCM_Password.
  1526. //
  1527. // Arguments: pArgs ptr to ArgsStruct
  1528. // pszPhoneBook full path to the phonebook file to get the
  1529. // data from, or NULL to use the all user default pbk
  1530. // dwMask dwMask value for the RASCREDENTIALS struct
  1531. // ppvData ptr to ptr to the data buffer. If the userinfo
  1532. // is multiple byte(e.g. password), the func allocs
  1533. // the buffer.
  1534. //
  1535. // Returns: DWORD ERROR_SUCCESS on success, winerror on failure
  1536. //
  1537. //----------------------------------------------------------------------------
  1538. DWORD RasGetCredsWrapper(
  1539. ArgsStruct *pArgs,
  1540. LPCTSTR pszPhoneBook,
  1541. DWORD dwMask,
  1542. PVOID *ppvData
  1543. )
  1544. {
  1545. DWORD dwRet = ERROR_INVALID_PARAMETER;
  1546. MYDBGASSERT(pArgs && pArgs->rlsRasLink.pfnGetCredentials);
  1547. MYDBGASSERT(ppvData);
  1548. MYDBGASSERT((RASCM_UserName == dwMask) || (RASCM_Domain == dwMask) || (RASCM_Password == dwMask));
  1549. if (pArgs && ppvData && pArgs->rlsRasLink.pfnGetCredentials)
  1550. {
  1551. LPTSTR pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
  1552. if (pszConnectoid)
  1553. {
  1554. RASCREDENTIALS RasCredentials = {0};
  1555. RasCredentials.dwSize = sizeof(RasCredentials);
  1556. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  1557. {
  1558. RasCredentials.dwMask = dwMask | RASCM_DefaultCreds;
  1559. }
  1560. else
  1561. {
  1562. RasCredentials.dwMask = dwMask;
  1563. }
  1564. dwRet = pArgs->rlsRasLink.pfnGetCredentials(pszPhoneBook, pszConnectoid, &RasCredentials);
  1565. if (ERROR_SUCCESS == dwRet)
  1566. {
  1567. LPTSTR pszData = NULL;
  1568. if (RASCM_UserName == dwMask)
  1569. {
  1570. pszData = RasCredentials.szUserName;
  1571. }
  1572. else if (RASCM_Domain == dwMask)
  1573. {
  1574. pszData = RasCredentials.szDomain;
  1575. }
  1576. else if (RASCM_Password == dwMask)
  1577. {
  1578. pszData = RasCredentials.szPassword;
  1579. }
  1580. LPTSTR pszReturn = CmStrCpyAlloc(pszData);
  1581. if (NULL == pszReturn)
  1582. {
  1583. dwRet = ERROR_NOT_ENOUGH_MEMORY;
  1584. }
  1585. else
  1586. {
  1587. *ppvData = pszReturn;
  1588. }
  1589. }
  1590. CmWipePassword(RasCredentials.szPassword);
  1591. CmFree(pszConnectoid);
  1592. }
  1593. }
  1594. return dwRet;
  1595. }
  1596. //+---------------------------------------------------------------------------
  1597. //
  1598. // Function: ReadUserInfoFromRas
  1599. //
  1600. // Synopsis: Read userinfo data from the RAS credentials cache
  1601. //
  1602. // Arguments: pArgs ptr to ArgsStruct
  1603. // uiEntry the cmp file entry
  1604. // ppvData ptr to ptr to the data buffer. If the userinfo
  1605. // is multiple byte(e.g. password), the func allocs
  1606. // the buffer.
  1607. //
  1608. // Returns: BOOL TRUE = success, FALSE = failure
  1609. //
  1610. //----------------------------------------------------------------------------
  1611. BOOL ReadUserInfoFromRas(
  1612. ArgsStruct *pArgs,
  1613. UINT uiEntry,
  1614. PVOID *ppvData
  1615. )
  1616. {
  1617. BOOL bReturn = FALSE;
  1618. if (OS_NT5 && pArgs && pArgs->bUseRasCredStore)
  1619. {
  1620. DWORD dwMask;
  1621. LPTSTR pszPhoneBook = NULL;
  1622. switch (uiEntry)
  1623. {
  1624. case UD_ID_USERNAME:
  1625. dwMask = RASCM_UserName;
  1626. bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, ppvData));
  1627. break;
  1628. case UD_ID_PASSWORD:
  1629. dwMask = RASCM_Password;
  1630. bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, ppvData));
  1631. break;
  1632. case UD_ID_DOMAIN:
  1633. dwMask = RASCM_Domain;
  1634. bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pArgs->pszRasPbk, dwMask, ppvData));
  1635. break;
  1636. case UD_ID_INET_PASSWORD:
  1637. dwMask = RASCM_Password;
  1638. pszPhoneBook = CreateRasPrivatePbk(pArgs);
  1639. if (pszPhoneBook)
  1640. {
  1641. bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pszPhoneBook, dwMask, ppvData));
  1642. CmFree(pszPhoneBook);
  1643. }
  1644. break;
  1645. case UD_ID_INET_USERNAME:
  1646. dwMask = RASCM_UserName;
  1647. pszPhoneBook = CreateRasPrivatePbk(pArgs);
  1648. if (pszPhoneBook)
  1649. {
  1650. bReturn = (ERROR_SUCCESS == RasGetCredsWrapper(pArgs, pszPhoneBook, dwMask, ppvData));
  1651. CmFree(pszPhoneBook);
  1652. }
  1653. break;
  1654. }
  1655. }
  1656. if (bReturn)
  1657. {
  1658. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  1659. {
  1660. CMTRACE1(TEXT("ReadUserInfoFromRas() - %s retrieved from the Global RAS Credential store"), TranslateUserDataID(uiEntry));
  1661. }
  1662. else
  1663. {
  1664. CMTRACE1(TEXT("ReadUserInfoFromRas() - %s retrieved from the User RAS Credential store"), TranslateUserDataID(uiEntry));
  1665. }
  1666. }
  1667. return bReturn;
  1668. }
  1669. //+---------------------------------------------------------------------------
  1670. //
  1671. // Function: GetUserInfo
  1672. //
  1673. // Synopsis: Get an userinfo. The user info can reside in either the
  1674. // cache, cmp, or registry. This functions hides this from the
  1675. // user.
  1676. //
  1677. // We first try the cmp file. If that fails, we try the cache.
  1678. // We'll get the following user info:
  1679. // username,
  1680. // password,
  1681. // domain,
  1682. // remember main passwd,
  1683. // dial automatically,
  1684. // inet username,
  1685. // inet passwd
  1686. // remember inet password
  1687. // inet use same user name
  1688. //
  1689. // Arguments: pArgs ptr to ArgsStruct
  1690. // uiEntry the cmp file entry
  1691. // pvData ptr to ptr to the data buffer. If the userinfo
  1692. // is multiple byte(e.g. password), the func allocs
  1693. // the buffer.
  1694. //
  1695. // Returns: BOOL TRUE = success, FALSE = failure
  1696. //
  1697. //----------------------------------------------------------------------------
  1698. BOOL GetUserInfo(
  1699. ArgsStruct *pArgs,
  1700. UINT uiEntry,
  1701. PVOID *ppvData
  1702. )
  1703. {
  1704. BOOL bReturn = ReadUserInfoFromRas(pArgs, uiEntry, ppvData);
  1705. if (!bReturn)
  1706. {
  1707. bReturn = ReadUserInfoFromReg(pArgs, uiEntry, ppvData);
  1708. }
  1709. if (!bReturn)
  1710. {
  1711. bReturn = ReadUserInfoFromCmp(pArgs, uiEntry, ppvData);
  1712. }
  1713. return bReturn;
  1714. }
  1715. //+---------------------------------------------------------------------------
  1716. //
  1717. // Function: SaveUserInfo
  1718. //
  1719. // Synopsis: Save an userinfo. The user info can reside in either the
  1720. // RAS cred cache or the registry. This functions abstracts
  1721. // this from the user.
  1722. //
  1723. // We first try the RAS cred cache. If the RAS cred cache doesn't hold that
  1724. // piece of info we then save it in the registry.
  1725. // We'll save the following user info:
  1726. // username,
  1727. // password,
  1728. // domain,
  1729. // remember main passwd,
  1730. // dial automatically,
  1731. // inet username,
  1732. // inet passwd
  1733. // remember inet password
  1734. // inet use same user name
  1735. //
  1736. // Arguments: pArgs ptr to ArgsStruct
  1737. // uiEntry the cmp file entry
  1738. // pvData ptr to the data buffer. If the userinfo is
  1739. // multiple byte(e.g. password), the func allocs
  1740. // the buffer.
  1741. //
  1742. // Returns: BOOL TRUE = success, FALSE = failure
  1743. //
  1744. //----------------------------------------------------------------------------
  1745. BOOL SaveUserInfo(
  1746. ArgsStruct *pArgs,
  1747. UINT uiEntry,
  1748. PVOID pvData
  1749. )
  1750. {
  1751. //
  1752. // Try giving the Data to RAS first. If the function returns
  1753. // -1, then this is data that RAS doesn't hold for us and we will
  1754. // have to put it in the registry instead.
  1755. //
  1756. int iReturn = WriteUserInfoToRas(pArgs, uiEntry, pvData);
  1757. if (-1 == iReturn)
  1758. {
  1759. //
  1760. // Just write the data to the registry. Use CMP only as
  1761. // an upgrade reference for UserInfo data post CM 1.1
  1762. //
  1763. iReturn = WriteUserInfoToReg(pArgs, uiEntry, pvData);
  1764. }
  1765. return iReturn;
  1766. }
  1767. //+---------------------------------------------------------------------------
  1768. //
  1769. // Function: DeleteUserInfo
  1770. //
  1771. // Synopsis: Delete an userinfo. The user info can reside in either the
  1772. // RAS Cred cache or the registry. This functions abstracts
  1773. // this from the user.
  1774. //
  1775. // We first try the RAS cache first. If that piece of info isn't stored
  1776. // in the RAS cache then we try the registry.
  1777. //
  1778. // We'll delete the following user info:
  1779. // username,
  1780. // password,
  1781. // domain,
  1782. // remember main passwd,
  1783. // dial automatically,
  1784. // inet username,
  1785. // inet passwd
  1786. // remember inet password
  1787. // inet use same user name
  1788. //
  1789. // Arguments: pArgs ptr to ArgsStruct
  1790. // uiEntry the cmp file entry
  1791. //
  1792. // Returns: BOOL TRUE = success, FALSE = failure
  1793. //
  1794. //----------------------------------------------------------------------------
  1795. BOOL DeleteUserInfo(
  1796. ArgsStruct *pArgs,
  1797. UINT uiEntry
  1798. )
  1799. {
  1800. int iReturn = DeleteUserInfoFromRas(pArgs, uiEntry);
  1801. if (-1 == iReturn)
  1802. {
  1803. iReturn = DeleteUserInfoFromReg(pArgs, uiEntry);
  1804. }
  1805. return iReturn;
  1806. }
  1807. //+---------------------------------------------------------------------------
  1808. //
  1809. // Function: NeedToUpgradeUserInfo
  1810. //
  1811. // Synopsis: Do we need to upgrade the cm 1.0/1.1 userinfo to the cm 1.2 format?
  1812. //
  1813. // Arguments: pArgs - Ptr to global args struct
  1814. //
  1815. // Returns: BOOL TRUE = success, FALSE = failure
  1816. //
  1817. //----------------------------------------------------------------------------
  1818. int NeedToUpgradeUserInfo(
  1819. ArgsStruct *pArgs)
  1820. {
  1821. MYDBGASSERT(pArgs);
  1822. DWORD dwRes;
  1823. HKEY hKeyCm;
  1824. LPTSTR pszSubKey;
  1825. int iReturn = c_iNoUpgradeRequired;
  1826. if (pArgs)
  1827. {
  1828. //
  1829. // If this is NT5 or greater, we want to be storing our credentials with RAS
  1830. // instead of the registry.
  1831. //
  1832. // If this isn't NT5 we still want to upgrade the user to using the registry as
  1833. // storage instead of the cmp if they haven't already
  1834. // been upgraded. Thus the simple test is to open the service name key in HKCU.
  1835. // This key will exist, if the user has already run 1.2 bits.
  1836. //
  1837. pszSubKey = BuildUserInfoSubKey(pArgs->szServiceName, pArgs->fAllUser);
  1838. dwRes = RegOpenKeyExU(HKEY_CURRENT_USER,
  1839. pszSubKey,
  1840. 0,
  1841. KEY_QUERY_VALUE,
  1842. &hKeyCm);
  1843. if (ERROR_SUCCESS == dwRes)
  1844. {
  1845. //
  1846. // Then we have the registry method, unless we are supposed to be using the RAS
  1847. // cred store we are done. If we are supposed to be using the RAS cred store
  1848. // we need to check to make sure that we are using it. Note we could have a problem
  1849. // here if the user has registry cred data and then their registry gets write protected.
  1850. // This would allow us to read from it but not delete the old data. Thus the user
  1851. // would never be able to save any changes because we would always think they needed
  1852. // to upgrade. An unlikely scenario but possible ...
  1853. //
  1854. if (pArgs->bUseRasCredStore)
  1855. {
  1856. LPTSTR pszUserName = NULL;
  1857. BOOL bRet = ReadUserInfoFromReg(pArgs, UD_ID_USERNAME, (PVOID*)&pszUserName);
  1858. if (bRet && (NULL != pszUserName) && (TEXT('\0') != pszUserName[0]))
  1859. {
  1860. //
  1861. // Then we have the username in the registry. Lets upgrade to the RAS
  1862. // credential store.
  1863. //
  1864. iReturn = c_iUpgradeFromRegToRas;
  1865. }
  1866. CmFree(pszUserName);
  1867. }
  1868. RegCloseKey(hKeyCm);
  1869. }
  1870. else
  1871. {
  1872. iReturn = c_iUpgradeFromCmp;
  1873. }
  1874. CmFree(pszSubKey);
  1875. }
  1876. else
  1877. {
  1878. CMASSERTMSG(FALSE, TEXT("NeedToUpgradeUserInfo -- NULL pArgs passed"));
  1879. }
  1880. //
  1881. // We don't want to upgrade if it's ICS. This prevents from adding info to the registry.
  1882. //
  1883. if (CM_LOGON_TYPE_ICS == pArgs->dwWinLogonType)
  1884. {
  1885. iReturn = c_iNoUpgradeRequired;
  1886. }
  1887. return iReturn;
  1888. }
  1889. //+---------------------------------------------------------------------------
  1890. //
  1891. // Function: UpgradeUserInfoFromRegToRasAndReg
  1892. //
  1893. // Synopsis: Upgrade the userinfo from CM 1.2 registry only format to the
  1894. // CM 1.3 format which uses both RAS credential storage and
  1895. // the registry.
  1896. //
  1897. // Arguments: pArgs ptr to ArgsStruct
  1898. //
  1899. // Returns: BOOL TRUE = success, FALSE = failure
  1900. //
  1901. //----------------------------------------------------------------------------
  1902. BOOL UpgradeUserInfoFromRegToRasAndReg(
  1903. ArgsStruct *pArgs
  1904. )
  1905. {
  1906. BOOL bReturn = FALSE;
  1907. if (OS_NT5)
  1908. {
  1909. LPTSTR pszTmp;
  1910. pszTmp = NULL;
  1911. //
  1912. // If we get an empty string "" from ReadUserInfoFromReg we don't want to
  1913. // save the empty string to the RAS Credstore because it might overwrite
  1914. // global credentials information. This can happen if User1 saves global
  1915. // credentials and User2 tries using the same profile. Since User2 is running
  1916. // this profile for the 1st time, he'll run through an upgrade path and if global
  1917. // creds exist we don't want to null them out.
  1918. //
  1919. if (ReadUserInfoFromReg(pArgs, UD_ID_INET_USERNAME, (PVOID*)&pszTmp))
  1920. {
  1921. DeleteUserInfoFromReg(pArgs, UD_ID_INET_USERNAME);
  1922. if (pszTmp && lstrlenU(pszTmp))
  1923. {
  1924. WriteUserInfoToRas(pArgs, UD_ID_INET_USERNAME, pszTmp);
  1925. }
  1926. CmFree(pszTmp);
  1927. }
  1928. pszTmp = NULL;
  1929. if (ReadUserInfoFromReg(pArgs, UD_ID_INET_PASSWORD, (PVOID*)&pszTmp))
  1930. {
  1931. DeleteUserInfoFromReg(pArgs, UD_ID_INET_PASSWORD);
  1932. if (pszTmp && lstrlenU(pszTmp))
  1933. {
  1934. WriteUserInfoToRas(pArgs, UD_ID_INET_PASSWORD, pszTmp);
  1935. }
  1936. CmFree(pszTmp);
  1937. }
  1938. pszTmp = NULL;
  1939. if (ReadUserInfoFromReg(pArgs, UD_ID_USERNAME, (PVOID*)&pszTmp))
  1940. {
  1941. DeleteUserInfoFromReg(pArgs, UD_ID_USERNAME);
  1942. if (pszTmp && lstrlenU(pszTmp))
  1943. {
  1944. WriteUserInfoToRas(pArgs, UD_ID_USERNAME, pszTmp);
  1945. }
  1946. CmFree(pszTmp);
  1947. }
  1948. pszTmp = NULL;
  1949. if (ReadUserInfoFromReg(pArgs, UD_ID_DOMAIN, (PVOID*)&pszTmp))
  1950. {
  1951. DeleteUserInfoFromReg(pArgs, UD_ID_DOMAIN);
  1952. if (pszTmp && lstrlenU(pszTmp))
  1953. {
  1954. WriteUserInfoToRas(pArgs, UD_ID_DOMAIN, pszTmp);
  1955. }
  1956. CmFree(pszTmp);
  1957. }
  1958. pszTmp = NULL;
  1959. if (ReadUserInfoFromReg(pArgs, UD_ID_PASSWORD, (PVOID*)&pszTmp))
  1960. {
  1961. DeleteUserInfoFromReg(pArgs, UD_ID_PASSWORD);
  1962. if (pszTmp && lstrlenU(pszTmp))
  1963. {
  1964. WriteUserInfoToRas(pArgs, UD_ID_PASSWORD, pszTmp);
  1965. }
  1966. CmFree(pszTmp);
  1967. }
  1968. //
  1969. // Now delete the PCS value as it is no longer meaningful
  1970. //
  1971. DeleteUserInfoFromReg(pArgs, UD_ID_PCS);
  1972. }
  1973. else
  1974. {
  1975. MYDBGASSERT(FALSE);
  1976. }
  1977. return bReturn;
  1978. }
  1979. //+---------------------------------------------------------------------------
  1980. //
  1981. // Function: UpgradeUserInfoFromCmp
  1982. //
  1983. // Synopsis: Upgrade the userinfo from cm1.0/1,1 format to 1.3 format.
  1984. //
  1985. // Arguments: pArgs ptr to ArgsStruct
  1986. //
  1987. // Returns: BOOL TRUE = success, FALSE = failure
  1988. //
  1989. //----------------------------------------------------------------------------
  1990. BOOL UpgradeUserInfoFromCmp(
  1991. ArgsStruct *pArgs
  1992. )
  1993. {
  1994. LPTSTR pszTmp;
  1995. BOOL fTmp;
  1996. PVOID pv;
  1997. //
  1998. // First retrieve each of the non-cached data items
  1999. // Then delete username, internetusername, domain, password,
  2000. // internetpassword, remember password, remember internet password
  2001. // and noprompt (dial automatically) from the CMP file.
  2002. // If the KeepDefaultCredentials is set to 1 in the .CMP file then the
  2003. // DeleteUserInfoFromCmp function does not actually delete the values from
  2004. // the file.
  2005. // If we get an empty string "" from ReadUserInfoFromCmp we don't want to
  2006. // save the empty string to the RAS Credstore because it might overwrite
  2007. // global credentials information. This can happen if User1 saves global
  2008. // credentials and User2 tries using the same profile. Since User2 is running
  2009. // this profile for the 1st time, he'll run through an upgrade path and if global
  2010. // creds exist we don't want to null them out.
  2011. //
  2012. pszTmp = NULL;
  2013. ReadUserInfoFromCmp(pArgs, UD_ID_USERNAME, (PVOID*)&pszTmp);
  2014. if (pszTmp && lstrlenU(pszTmp))
  2015. {
  2016. SaveUserInfo(pArgs, UD_ID_USERNAME, pszTmp);
  2017. }
  2018. DeleteUserInfoFromCmp(pArgs, UD_ID_USERNAME);
  2019. CmFree(pszTmp);
  2020. pszTmp = NULL;
  2021. ReadUserInfoFromCmp(pArgs, UD_ID_DOMAIN, (PVOID*)&pszTmp);
  2022. if (pszTmp && lstrlenU(pszTmp))
  2023. {
  2024. SaveUserInfo(pArgs, UD_ID_DOMAIN, pszTmp);
  2025. }
  2026. DeleteUserInfoFromCmp(pArgs, UD_ID_DOMAIN);
  2027. CmFree(pszTmp);
  2028. pszTmp = NULL;
  2029. ReadUserInfoFromCmp(pArgs, UD_ID_INET_USERNAME, (PVOID*)&pszTmp);
  2030. if (pszTmp && lstrlenU(pszTmp))
  2031. {
  2032. SaveUserInfo(pArgs, UD_ID_INET_USERNAME, pszTmp);
  2033. }
  2034. DeleteUserInfoFromCmp(pArgs, UD_ID_INET_USERNAME);
  2035. CmFree(pszTmp);
  2036. pv = &fTmp;
  2037. ReadUserInfoFromCmp(pArgs, UD_ID_NOPROMPT, &pv);
  2038. SaveUserInfo(pArgs, UD_ID_NOPROMPT, pv);
  2039. DeleteUserInfoFromCmp(pArgs, UD_ID_NOPROMPT);
  2040. pv = &fTmp;
  2041. ReadUserInfoFromCmp(pArgs, UD_ID_REMEMBER_PWD, &pv);
  2042. SaveUserInfo(pArgs, UD_ID_REMEMBER_PWD, pv);
  2043. DeleteUserInfoFromCmp(pArgs, UD_ID_REMEMBER_PWD);
  2044. pv = &fTmp;
  2045. ReadUserInfoFromCmp(pArgs, UD_ID_REMEMBER_INET_PASSWORD, &pv);
  2046. SaveUserInfo(pArgs, UD_ID_REMEMBER_INET_PASSWORD, pv);
  2047. DeleteUserInfoFromCmp(pArgs, UD_ID_REMEMBER_INET_PASSWORD);
  2048. //
  2049. // Construct old cache entry name
  2050. //
  2051. LPTSTR pszCacheEntryName = GetLegacyKeyName(pArgs);
  2052. //
  2053. // main passwd
  2054. //
  2055. pszTmp = NULL;
  2056. //
  2057. // To get the passwords, the cm 1.1 logic is that we first try the cmp, then the cache.
  2058. //
  2059. if (ReadUserInfoFromCmp(pArgs, UD_ID_PASSWORD, (PVOID*)&pszTmp))
  2060. {
  2061. if (pszTmp && lstrlenU(pszTmp))
  2062. {
  2063. SaveUserInfo(pArgs, UD_ID_PASSWORD, pszTmp);
  2064. }
  2065. }
  2066. else
  2067. {
  2068. CmFree(pszTmp);
  2069. pszTmp = NULL;
  2070. #ifdef TEST_USERINFO_UPGRADE
  2071. MYVERIFY(WriteStringToCache(pArgs, pszCacheEntryName, TEXT("CM 1.1 main password")));
  2072. #endif
  2073. //
  2074. // Try to read it from cache
  2075. //
  2076. if (ReadStringFromCache(pArgs, pszCacheEntryName, &pszTmp))
  2077. {
  2078. if (pszTmp && lstrlenU(pszTmp))
  2079. {
  2080. if (SaveUserInfo(pArgs, UD_ID_PASSWORD, pszTmp))
  2081. {
  2082. #ifdef TEST_USERINFO_UPGRADE
  2083. MYVERIFY(DeleteStringFromCache(pArgs, pszCacheEntryName));
  2084. #endif
  2085. }
  2086. }
  2087. }
  2088. }
  2089. DeleteUserInfoFromCmp(pArgs, UD_ID_PASSWORD);
  2090. CmFree(pszTmp);
  2091. //
  2092. // inet passwd
  2093. //
  2094. pszTmp = NULL;
  2095. if (ReadUserInfoFromCmp(pArgs, UD_ID_INET_PASSWORD, (PVOID*)&pszTmp))
  2096. {
  2097. if (pszTmp && lstrlenU(pszTmp))
  2098. {
  2099. SaveUserInfo(pArgs, UD_ID_INET_PASSWORD, pszTmp);
  2100. }
  2101. }
  2102. else
  2103. {
  2104. CmFree(pszTmp);
  2105. pszTmp = NULL;
  2106. //
  2107. // Build tunnel entry name and read string from cache
  2108. //
  2109. pszCacheEntryName = CmStrCatAlloc(&pszCacheEntryName, TEXT("-tunnel"));
  2110. #ifdef TEST_USERINFO_UPGRADE
  2111. MYVERIFY(WriteStringToCache(pArgs, pszCacheEntryName, TEXT("CM 1.1 internet password")));
  2112. #endif
  2113. if (ReadStringFromCache(pArgs, pszCacheEntryName, &pszTmp))
  2114. {
  2115. if (pszTmp && lstrlenU(pszTmp))
  2116. {
  2117. if (SaveUserInfo(pArgs, UD_ID_INET_PASSWORD, pszTmp))
  2118. {
  2119. #ifdef TEST_USERINFO_UPGRADE
  2120. MYVERIFY(DeleteStringFromCache(pArgs, pszCacheEntryName));
  2121. #endif
  2122. }
  2123. }
  2124. }
  2125. }
  2126. DeleteUserInfoFromCmp(pArgs, UD_ID_INET_PASSWORD);
  2127. CmFree(pszTmp);
  2128. CmFree(pszCacheEntryName);
  2129. return TRUE; // MarkUserInfoUpgraded(pArgs);
  2130. }
  2131. //+----------------------------------------------------------------------------
  2132. //
  2133. // Function: GetLegacyKeyName
  2134. //
  2135. // Synopsis: Builds the string fragment used to build cache entry name. The "
  2136. // sign-in" prefix is maintained for legacy compatibility
  2137. //
  2138. // Arguments: ArgsStruct *pArgs - Ptr to global args struct
  2139. //
  2140. // Returns: LPTSTR - Ptr to allocated string containing "<service name> - Sign-In"
  2141. //
  2142. // Note: Used exclusively for cache entry name construction
  2143. //
  2144. // History: nickball Created Header 4/16/98
  2145. //
  2146. //+----------------------------------------------------------------------------
  2147. LPTSTR GetLegacyKeyName(ArgsStruct *pArgs)
  2148. {
  2149. MYDBGASSERT(pArgs);
  2150. //
  2151. // Service name is the basis of the key name. We also include
  2152. // IDMSG_TITLESERVICE and append a suffix of " (Connection Manager)"
  2153. //
  2154. LPTSTR pszRes = CmFmtMsg(g_hInst, IDMSG_TITLESERVICE, pArgs->szServiceName);
  2155. MYDBGASSERT(pszRes && *pszRes);
  2156. if (pszRes)
  2157. {
  2158. pszRes = CmStrCatAlloc(&pszRes, c_pszCacheEntryNameSuffix);
  2159. }
  2160. return (pszRes);
  2161. }
  2162. //+----------------------------------------------------------------------------
  2163. //
  2164. // Function: EncryptPassword
  2165. //
  2166. // Synopsis: Wrapper for encrypting password
  2167. //
  2168. // Arguments: ArgsStruct *pArgs - Ptr to global args struct
  2169. // LPCTSTR pszPassword - The password to be encrypted
  2170. // LPDWORD lpdwBufSize - Buffer for size of the encrypted buffer - optional
  2171. // LPDWORD lpdwCryptType - Buffer for crypto type used
  2172. // BOOL fReg - Password is disguised for registry storage
  2173. //
  2174. // Returns: LPTSTR - Ptr to allocated buffer containing encrypted form of password
  2175. //
  2176. // History: nickball Created Header 5/22/98
  2177. //
  2178. //+----------------------------------------------------------------------------
  2179. LPTSTR EncryptPassword(
  2180. ArgsStruct *pArgs,
  2181. LPCTSTR pszPassword,
  2182. LPDWORD lpdwBufSize,
  2183. LPDWORD lpdwCryptType,
  2184. BOOL /*fReg*/,
  2185. LPSTR pszSubKey)
  2186. {
  2187. MYDBGASSERT(pArgs);
  2188. MYDBGASSERT(pszPassword);
  2189. MYDBGASSERT(lpdwCryptType);
  2190. DWORD dwEncryptedBufferLen;
  2191. DWORD dwSize = 0;
  2192. LPTSTR pszEncryptedData = NULL;
  2193. TCHAR szSourceData[PWLEN + 1];
  2194. if (NULL == pArgs || NULL == pszPassword || NULL == lpdwCryptType)
  2195. {
  2196. return NULL;
  2197. }
  2198. //
  2199. // Standard encryption, copy the password
  2200. //
  2201. lstrcpyU(szSourceData, pszPassword);
  2202. //
  2203. // It is not safe to call InitSecure more than once
  2204. //
  2205. if (!pArgs->fInitSecureCalled)
  2206. {
  2207. pArgs->fInitSecureCalled = TRUE;
  2208. InitSecure(FALSE); // don't use fast encryption anymore
  2209. }
  2210. //
  2211. // Encrypt the provided password
  2212. //
  2213. if (EncryptData(
  2214. (LPBYTE)szSourceData,
  2215. (lstrlenU(szSourceData)+1) * sizeof(TCHAR),
  2216. (LPBYTE*)&pszEncryptedData,
  2217. &dwEncryptedBufferLen,
  2218. lpdwCryptType,
  2219. #if defined(DEBUG) && defined(DEBUG_MEM)
  2220. (PFN_CMSECUREALLOC)AllocDebugMem, // Give the DEBUG_MEM version of alloc/free
  2221. (PFN_CMSECUREFREE)FreeDebugMem)) // Not quit right, AllocDebugMem takes 3 param
  2222. #else
  2223. (PFN_CMSECUREALLOC)CmMalloc,
  2224. (PFN_CMSECUREFREE)CmFree,
  2225. pszSubKey))
  2226. #endif
  2227. {
  2228. if (lpdwBufSize)
  2229. {
  2230. *lpdwBufSize = dwEncryptedBufferLen;
  2231. }
  2232. }
  2233. MYDBGASSERT(pszEncryptedData);
  2234. CmWipePassword(szSourceData);
  2235. return pszEncryptedData;
  2236. }
  2237. //+----------------------------------------------------------------------------
  2238. //
  2239. // Function: DecryptPassword
  2240. //
  2241. // Synopsis: Wrapper to decrypt password
  2242. //
  2243. // Arguments: ArgsStruct *pArgs - Ptr to global args struct
  2244. // LPCTSTR pszEncryptedData - The encrypted data
  2245. // DWORD dwEncryptionType - The encryption type of the data
  2246. // BOOL fReg - Password is disguised for registry storage
  2247. //
  2248. // Returns: LPTSTR - Ptr to a buffer containing the decrypted form of the password.
  2249. //
  2250. // History: nickball Created 5/22/98
  2251. //
  2252. //+----------------------------------------------------------------------------
  2253. LPBYTE DecryptPassword(
  2254. ArgsStruct *pArgs,
  2255. LPBYTE pszEncryptedData,
  2256. DWORD dwEncryptionType,
  2257. DWORD dwEncryptedBytes,
  2258. BOOL /*fReg*/,
  2259. LPSTR pszSubKey)
  2260. {
  2261. MYDBGASSERT(pArgs);
  2262. MYDBGASSERT(pszEncryptedData);
  2263. DWORD dwDecryptedBufferLen;
  2264. LPBYTE pszDecryptedData = NULL;
  2265. if (NULL == pArgs || NULL == pszEncryptedData)
  2266. {
  2267. return NULL;
  2268. }
  2269. //
  2270. // It is not safe to call InitSecure more than once
  2271. //
  2272. if (!pArgs->fInitSecureCalled)
  2273. {
  2274. pArgs->fInitSecureCalled = TRUE;
  2275. InitSecure(FALSE); // don't use fast encryption anymore
  2276. }
  2277. if (DecryptData(pszEncryptedData, dwEncryptedBytes, &pszDecryptedData, &dwDecryptedBufferLen,
  2278. dwEncryptionType,
  2279. #if defined(DEBUG) && defined(DEBUG_MEM)
  2280. (PFN_CMSECUREALLOC)AllocDebugMem, // Give the DEBUG_MEM version of alloc/free
  2281. (PFN_CMSECUREFREE)FreeDebugMem)) // Not quit right, AllocDebugMem takes 3 param
  2282. #else
  2283. (PFN_CMSECUREALLOC)CmMalloc,
  2284. (PFN_CMSECUREFREE)CmFree,
  2285. pszSubKey))
  2286. #endif
  2287. {
  2288. return pszDecryptedData;
  2289. }
  2290. return NULL;
  2291. }
  2292. //+----------------------------------------------------------------------------
  2293. //
  2294. // Function: TranslateUserDataID
  2295. //
  2296. // Synopsis: Wrapper to map user data ID to string name of .CMP entry
  2297. //
  2298. // Arguments: UINT uiDataID - UserInfo data ID to be translated
  2299. //
  2300. // Returns: LPCTSTR - Ptr to a constant containing the .CMP entry flag
  2301. //
  2302. // History: nickball Created 10/13/98
  2303. //
  2304. //+----------------------------------------------------------------------------
  2305. LPCTSTR TranslateUserDataID(UINT uiDataID)
  2306. {
  2307. switch(uiDataID)
  2308. {
  2309. case UD_ID_USERNAME:
  2310. return c_pszCmEntryUserName;
  2311. break;
  2312. case UD_ID_INET_USERNAME:
  2313. return c_pszCmEntryInetUserName;
  2314. break;
  2315. case UD_ID_DOMAIN:
  2316. return c_pszCmEntryDomain;
  2317. break;
  2318. case UD_ID_PASSWORD:
  2319. return c_pszCmEntryPassword;
  2320. break;
  2321. case UD_ID_INET_PASSWORD:
  2322. return c_pszCmEntryInetPassword;
  2323. break;
  2324. case UD_ID_NOPROMPT:
  2325. return c_pszCmEntryNoPrompt;
  2326. break;
  2327. case UD_ID_REMEMBER_PWD:
  2328. return c_pszCmEntryRememberPwd;
  2329. break;
  2330. case UD_ID_REMEMBER_INET_PASSWORD:
  2331. return c_pszCmEntryRememberInetPwd;
  2332. break;
  2333. case UD_ID_PCS:
  2334. return c_pszCmEntryPcs;
  2335. break;
  2336. case UD_ID_ACCESSPOINTENABLED:
  2337. return c_pszCmEntryAccessPointsEnabled;
  2338. break;
  2339. case UD_ID_CURRENTACCESSPOINT:
  2340. return c_pszCmEntryCurrentAccessPoint;
  2341. break;
  2342. default:
  2343. break;
  2344. }
  2345. MYDBGASSERT(FALSE);
  2346. return NULL;
  2347. }